玩命加载中 . . .

异步fifo代码

module afifo
#(parameter DATA_WIDTH = 64,
            FIFO_DEPTH = 8,
            AF_LEVEL   = (1<<FIFO_DEPTH - 10),
            AE_LEVEL   = 10
)
(
  input                         wclk          ,
  input                         wrst          ,
  input                         wen           ,
  input       [DATA_WIDTH-1:0]  wdata         ,
  output reg                    wfull         ,
  output reg                    walmost_full  ,

  input                         rclk          ,
  input                         rrst          ,
  input                         ren           ,
  output reg  [DATA_WIDTH-1:0]  rdata         ,
  output reg                    rempty        ,
  output reg                    ralmost_empty
);


wire                  fifo_rd;
wire                  fifo_wr;
wire [FIFO_DEPTH-1:0] raddr;
wire [FIFO_DEPTH-1:0] waddr;
reg  [DATA_WIDTH-1:0] memory [0:(1<<FIFO_DEPTH)-1];

wire                  wen_mask;
wire [FIFO_DEPTH:0]   wbinnext;
wire [FIFO_DEPTH:0]   wptrnext;
reg  [FIFO_DEPTH:0]   wbin;
reg  [FIFO_DEPTH:0]   wptr;
reg  [FIFO_DEPTH:0]   wptr_rsync1;
reg  [FIFO_DEPTH:0]   wptr_rsync2;
wire [FIFO_DEPTH:0]   wbin_rsync;

wire                  ren_mask;
wire [FIFO_DEPTH:0]   rbinnext;
wire [FIFO_DEPTH:0]   rptrnext;
reg  [FIFO_DEPTH:0]   rbin;
reg  [FIFO_DEPTH:0]   rptr;
reg  [FIFO_DEPTH:0]   rptr_wsync1;
reg  [FIFO_DEPTH:0]   rptr_wsync2;
wire [FIFO_DEPTH:0]   rbin_wsync;

genvar i;

//*************************************
// Dual port RAM
//*************************************
assign fifo_wr = wen_mask;
always @(posedge wclk) begin
  if(fifo_wr)
    memory[waddr] <= wdata;
end

assign fifo_rd = ren_mask;
always @(posedge rclk) begin
  if(fifo_rd)
    rdata <= memory[raddr];
end
//

//*************************************
// sync wptr to rclk domain
//*************************************
always @(posedge rclk or negedge rrst) begin
  if(rrst)
    {wptr_rsync2,wptr_rsync1} <= 0;
  else
    {wptr_rsync2,wptr_rsync1} <= {wptr_rsync1,wptr};
end

generate
  for(i=FIFO_DEPTH;i>=0;i=i-1) begin: wbin_rsync_gen
    assign wbin_rsync[i] = ^({ {i{1'b0}},wptr_rsync2[FIFO_DEPTH:i]});
  end
endgenerate

//*************************************
// sync rptr to wclk domain
//*************************************
always @(posedge wclk or negedge wrst) begin
  if(wrst)
    {rptr_wsync2,rptr_wsync1} <= 0;
  else
    {rptr_wsync2,rptr_wsync1} <= {rptr_wsync1,rptr};
end

generate
  for(i=FIFO_DEPTH;i>=0;i=i-1) begin: rbin_wsync_gen
    assign rbin_wsync[i] = ^({ {i{1'b0}},rptr_wsync2[FIFO_DEPTH:i]});
  end
endgenerate

//*************************************
// rd addr generate
//*************************************
always @(posedge rclk or negedge rrst) begin
  if(rrst)
    {rbin,rptr} <= 0;
  else
    {rbin,rptr} <= {rbinnext,rptrnext};
end
assign raddr    = rbin[FIFO_DEPTH-1:0];
assign ren_mask = ren & (~rempty);
assign rbinnext = ren_mask ? (rbin + 1'b1) : rbin;
assign rptrnext = (rbinnext>>1) ^ rbinnext;


//*************************************
// wr addr generate
//*************************************
always @(posedge wclk or negedge wrst) begin
  if(wrst)
    {wbin,wptr} <= 0;
  else
    {wbin,wptr} <= {wbinnext,wptrnext};
end
assign waddr = wbin[FIFO_DEPTH-1:0];
assign wen_mask = (wen & (~wfull));
assign wbinnext = wen_mask ? (wbin + 1'b1) : wbin;
assign wptrnext = (wbinnext>>1) ^ wbinnext;

//*************************************
// FIFO status
//*************************************
always @(posedge rclk or negedge rrst) begin
  if(rrst)
    rempty <= 1'b1;
  else
    rempty <= (rptrnext == wptr_rsync2);
end

always @(posedge rclk or negedge rrst) begin
  if(rrst)
    ralmost_empty <= 1'b1;
  else
    ralmost_empty <= (wbin_rsync - rbinnext <= AE_LEVEL);
end

always @(posedge wclk or negedge wrst) begin
  if(wrst)
    wfull <= 0;
  else
    wfull <= (wptrnext == {~rptr_wsync2[FIFO_DEPTH:FIFO_DEPTH-1],rptr_wsync2[FIFO_DEPTH-2:0]});
end

always @(posedge wclk or negedge wrst) begin
  if(wrst)
    walmost_full <= 1'b1;
  else
    walmost_full <= (wbinnext - rbin_wsync >= AF_LEVEL);
end

endmodule

小环境makefile模板

design = tb
verilog_flist = -f ./test.vc tb.v
vhd_flist =
wave = wave.fsdb

#whether to open verdi wave gui
ifdef wave
	verdi_cmd += -ssf $(wave)
endif

.PHONY: help clean ius compile verdi

help:
	@echo "#==============================================================="
	@echo "# [Info] make help    : show help infomation"   
	@echo "# [Info] make clean   : clean ius and verdi compile library,log"   
	@echo "# [Info] make compile : compile for verdi"   
	@echo "# [Info] make verdi   : raise verdi gui"   
	@echo "#==============================================================="

clean:
	@rm chip_lib.lib++ work.lib++ INCA_libs verdiLog vericomLog vhdlcomLog -rf

ius:
	irun +access+wr -smartorder -clean -ntcnotchks -V93 -vtimescale 1ns/1ps +define+RD=1 -work chip_lib $(verilog_flist) $(vhd_flist) -top $(design) -64bit

compile:
ifdef vhdl_flist
	vhdlcom -V93 -sup_sem_error -smartorder -work chip_lib $(vhdl_flist)
endif
ifdef verilog_flist
	vericom -sv +systemverilog+sv +v95ext+v95 +verilog2001ext+v -ignorekwd_config +define+RD=1  -work chip_lib $(verilog_flist)
endif

verdi:compile
	verdi -lib chip_lib $(verdi_cmd) &

git配置

放在~/.gitconfig文件中

[user]
  name = victor.dong
  email = dxs_uestc@163.com
[color]
  ui = auto
[alias]
  st = status
  co = checkout
  ci = commit
  br = branch
  df = diff
  dfn = diff --name-only
  dfs = diff --staged
  dft = difftool
  dfts = difftool --staged
  mr = merge
  mrt = mergetool
  last = log -1 HEAD
  amend = commit -C HEAD -a --amend
  lg = log --color --graph --pretty=format:'%C(yellow)%h%C(reset) - %C()%cd%C(reset) %C()<%an>%C(reset)%C(red)%d%C(reset) %C(ul)%s%C(reset)' --abbrev-commit --date=format:'%y/%m/%d %H:%M:%S'
  ls = log --name-only --color --graph --pretty=format:'%C(yellow)%h%C(reset) - %C()%cd%C(reset) %C()<%an>%C(reset)%C(red)%d%C(reset) %C(ul)%s%C(reset)' --abbrev-commit --date=format:'%y/%m/%d %H:%M:%S'

#not show log in new page
[core]
	pager =

#diff tool use beyond compare
[diff]
  tool = bcomp
[difftool "bcomp"]
  cmd = \"/usr/bin/bcompare\" \"$LOCAL\" \"$REMOTE\"
[difftool]
  prompt = false

#merge tool use beyond compare
[merge]
  tool = bcomp
[mergetool "bcomp"]
  cmd = \"/usr/bin/bcompare\" \"$LOCAL\" \"$REMOTE\" \"$BASE\" \"$MERGED\"
[mergetool]
  prompt = false

VIM插件及效果图

插件推荐:

使用案例
Examples:

        :I
                    Use ctrl-V to
        Original    Select, :I
           8            8
           8            9
           8            10
           8            11
           8            12

        :I -1
                    Use ctrl-V to
        Original    Select, :I -1
           8            8
           8            7
           8            6
           8            5
           8            4


        :II
                    Use ctrl-V to
        Original    Select, :II
           8             8
           8             9
           8            10
           8            11
           8            12

        :II -1
                    Use ctrl-V to
        Original    Select, :II -1
           8            8
           8            7
           8            6
           8            5
           8            4


        :IMDY
                  Use ctrl-V to
        Original  Select, :IMDY
        06/10/03     6/10/03
        06/10/03     6/11/03
        06/10/03     6/12/03
        06/10/03     6/13/03
        06/10/03     6/14/03


        :IYMD
                  Use ctrl-V to
        Original  Select, :IYMD
        03/06/10    03/06/10
        03/06/10    03/06/11
        03/06/10    03/06/12
        03/06/10    03/06/13
        03/06/10    03/06/14




        :IDMY
                  Use ctrl-V to
        Original  Select, :IDMY
        10/06/03    10/06/03
        10/06/03    11/06/03
        10/06/03    12/06/03
        10/06/03    13/06/03
        10/06/03    14/06/03


        :ID
                  Use ctrl-V to
        Original  Select, :ID
          Sun       Sun
          Sun       Mon
          Sun       Tue
          Sun       Wed
          Sun       Thu


        :ID
                  Use ctrl-V to
        Original  Select, :ID
         Sunday     Sunday
         Sunday     Monday
         Sunday     Tuesday
         Sunday     Wednesday
         Sunday     Thursday

        :IA
                  Use ctrl-V to
        Original  Select, :IA
           a          a
           a          b
           a          c
           a          d
           a          e

        :IO
                  Use ctrl-V to
        Original  Select, :IO
            5         5 
            5         6 
            5         7 
            5         10
            5         11

        :IR
                  Use ctrl-V to
        Original  Select, :IR
           II         II
           II         III
           II         IV
           II         V 
           II         VI

                  Use ctrl-V to
        Original  Select, :IX
            8         8
            8         9
            8         a
            8         b
            8         c
NaN
  • minibufexpl:Elegant buffer explorer - takes very little screen space. 在路径上gf会自动生成buffer explorer,在buffer explorer上按d可以删除当前buffer explorer

主题(放在~/.vim/colors/):

字体(放在~/.fonts/):

效果图:
vim效果图

CPF, UPF, IEEE1801 这些名称的渊源可参阅《一文读懂power intent的历史:从CPF/UPF到IEEE1801》,1801的内容其实十分简明,概括来说一个完整的1801 文件可以分成三部分[1]

  • 区域划分: 上帝的归上帝,凯撒的归凯撒,包括supply set 跟power domain 两个东西。
  • 策略定义: 没有清规戒律,何以服众,包括isolation, level shifter, retention, power switch 四种策略。
  • 模式定义: 宿命就是划定的圈,听天由命也是宿命,只有power state.

SOC UPF结构图

AHB组成部分

  • AHB主设备(master)
    • 发起一次读写操作
    • 某一时刻只允许一个master使用总线
  • AHB从设备(slave)
    • 响应一次读写操作
    • 通过地址映射来选择使用哪个slave
  • AHB仲裁器(arbiter)
    • 允许某一个主设备控制总线
    • 在AMBA协议中没有定义仲裁算法
  • AHB译码器(decoder)
    • 通过地址译码来决定选择哪个slave

AHB总线结构图

force verilog内部信号

force verilog内部信号为某个值,可以这样写:

initial begin  //verilog internal signal access
  force xxx.xxx.xxx = 16'hfffd;
  #500 release xxx.xxx.xxx;
end

force vhdl内部信号

而对于vhdl内部信号,使用force是错误的,vhdl语言不允许这样做。但是EDA工具一般都会提供函数,例如cadence的ncsim,可以使用$nc_forcenc_release访问vhdl内部信号。

initial begin //vhdl internal signal access
  $nc_force("xxx.xxx.xxx", "X'FFFD'");
  #500 $nc_release(xxx.xxx.xxx);
end
  • 类封装了数据和操作这些数据的子程序
  • 类可以定义在program、package、module中,或者在这些块之外的任何地方。类应当在program或者module之外的package中定义,避免与其他块内变量出现冲突。
  • new()创建对象、分配空间并执行构造函数
  • 赋值为null释放对象空间
  • 通过static来声明静态变量,是的该变量被该类的所有实例所共享,但使用范围仅限于该类
  • 通过类名::变量来访问静态变量
  • 静态变量在声明时初始化
  • 静态方法跟静态变量类似,也通过static声明
  • 静态方法不允许读写非静态变量
  • 类中的方法默认是自动存储的
  • 当使用一个变量时,会优先在当前作用域中寻找,接着在上一级作用域寻找,直到找到该变量为止。this可以明确指定当前作用域。
  • 接口信号必须使用非阻塞赋值来驱动
  • modport将信号分组并指定方向
  • clocking时钟块用于控制同步信号的时序

testbench注意事项:

  • $exit用于结束程序块,$finish用于结束仿真
  • 时钟产生不应该放在program程序块中,会引起信号的竞争,而应该放在module中
  • 例化时如果端口名字和数据类型一致,例化时可以用.*(隐式端口连接)

DUT代码

以简单的乘法器为例写testbench

//mul.v
module mul(
  input             clk,
  input             rst_n,
  input             in_vld,
  input      [11:0] mul_ain,
  input      [11:0] mul_bin,
  output reg [22:0] mul_out,
  output reg        out_vld
);

always @(posedge clk)
  if(in_vld)
    mul_out <= $signed(mul_ain) * $signed(mul_bin);

always @(posedge clk,negedge rst_n)
  if(!rst_n)
    out_vld <= 1'b0;
  else
    out_vld <= in_vld;

endmodule
  • 缺省情况下参数的类型是与其前一个参数相同的,而第一个参数的缺省类型是logic单bit输入
  • 参数的传递方式可以使用ref指定为引用,通常用于数组引用;当不希望子程序改变数组值时,可以使用const ref类型
  • ref参数只能被用于带自动存储(automatic)的子程序中,即使用ref参数时子程序必须指明automatic属性
  • 自动存储相对的是静态存储,当多个地方调用静态存储子程序时,不同的线程之间会窜用这些局部变量,而自动存储能够迫使仿真器使用堆栈存储局部变量
  • 函数使用return返回一个值,调用时可以使用void忽略返回值,例如void'($fscanf(file,"%d",i));
module test_func();

int arr[];

//************************************
// operator = "+", return a.sum
// operator = "x", return a.product
//************************************
function automatic int alu(
    const ref int a[],           //数组引用,const不能改变数组
    input string operator = "+"  //指定default值
);

int result;

if(operator=="x") begin
  result = 1;
  for(a[i])
    result *= a[i];
end
else begin
  result = 0;
  for(a[i])
    result += a[i];
end

return result;
endfunction

initial begin
  arr = new[5];
  arr = '{1,2,3,4,5};
  $display(alu(arr));    //15, use default operator
  $display(alu(arr,"x")) //120
end

endmodule