verilog和Ncverilog命令使用库文件或库目录
ex). ncverilog -f run.f -v lib/lib.v -y lib2 +libext+.v //一般编译文件在run.f中, 库文件在lib.v中,lib2目录中的.v文件系统自动搜索使用库文件或库目录,只编译需要的模块而不必全部编译.
2). Debussy fsdb数据库也可以记录信号的变化,它的优势是可以跟debussy结合,方便调试.
如果要在ncverilog仿真时,记录信号, 首先要设置debussy:
a. setenv LD_LIBRARY_PATH :$LD_LIBRARY_PATH
(path for debpli.so file (/share/PLI/nc_xl//nc_loadpli1))
b. while invoking ncverilog use the +ncloadpli1 option.
ncverilog -f run.f +debug +ncloadpli1=debpli:deb_PLIPtr
fsdb数据库文件的记录方法,是使用$fsdbDumpfile和$fsdbDumpvars系统函数,使用方法参见VCD
注意: 在用ncverilog的时候,为了正确地记录波形,要使用参数: "+access+rw", 否则没有读写权限
在记录信号或者波形时需要指出被记录信号的路径,如:tb.module.u1.clk.
3)
ncverilog编译的顺序
ncverilog file1 file2 ....
有时候这些文件存在依存关系,如在file2中要用到在file1中定义的变量,这时候就要注意其编译的顺序是
从后到前,就先编译file1然后才是file2.
4
信号的强制赋值force
首先, force语句只能在过程语句中出现,即要在initial 或者 always 中间. 去除force 用 release 语句.
initial begin force sig1 = 1'b1; ... ; release sig1; end
force可以对wire赋值,这时整个net都被赋值; 也可以对reg赋值.
5
加载测试向量时,避免在时钟的上下沿变化
为了模拟真实器件的行为,加载测试向量时,避免在时钟的上下沿变化,而是在时钟的上升沿延时一个时间单位后,加载的测试向量发生变化。如:
assign #5 c=a^b
……
@(posedge clk) #(0.1*`cycle) A=1;
6
testbench的波形输出
module top;
...
initial
begin
$dumpfile("./top.vcd"); //存储波形的文件名和路径,一般是.vcd格式.
$dumpvars(1,top); //存储top这一层的所有信号数据
$dumpvars(2,top.u1); //存储top.u1之下两层的所有数据信号(包含top.u1这一层)
$dumpvars(3,top.u2); //存储top.u2之下三层的所有数据信号(包含top.u2这一层)
$dumpvars(0,top.u3); //存储top.u3之下所有层的所有数据信号
end
endmodule
7
产生随机数,seed是种子
$random(seed);
ex: din <= $random(20);
8
仿真时间
//仿真时间,为unsigned型的64位数据
$time
ex:
...
time condition_happen_time;
...
condition_happen_time = $time;
...
$monitor($time,"data utput = %d", dout);
9
参数
 
  | parameter para1 = 10,para2 = 20,
 para3 = 30;
 | 
延迟模型
 
  | specify...
 //describ pin-to-pin delay
 endspecify
 
 ex:
 
 module nand_or(Y,A,B,C);
 input A,B,C;
 output Y;
 AND2 #0.2 (N,A,B);
 OR2 #0.1 (Y,C,N);
 specify
 (A*->Y) = 0.2;
 (B*->Y) = 0.3;
 (C*->Y) = 0.1;
 endspecify
 endmodule
 | 
文件I/O
 
  | 1.打开文件
 integer file_id;
 file_id = fopen("file_path/file_name");
 
 2.写入文件
 
 //$fmonitor只要有变化就一直记录
 $fmonitor(file_id, "%format_char", parameter);
 eg:$fmonitor(file_id, "%m: %t in1=%d o1=%h", $time, in1, o1);
 //$fwrite需要触发条件才记录
 $fwrite(file_id, "%format_char", parameter);
 //$fdisplay需要触发条件才记录
 $fdisplay(file_id, "%format_char", parameter);
 $fstrobe();
 
 3.读取文件
 
 integer file_id;
 file_id = $fread("file_path/file_name", "r");
 
 4.关闭文件
 $fclose(fjile_id);
 
 5.由文件设定存储器初值
 $readmemh("file_name", memory_name"); //初始化数据为十六进制
 $readmemb("file_name", memory_name"); //初始化数据为二进制
 | 
仿真控制
 
  | $finish(parameter); //parameter = 0,1,2$stop(parameter);
 | 
读入SDF文件
 
  | //$sdf_annotate("sdf_file_name", module_instance,
  "scale_factors");
 //module_instance: sdf文件所对应的instance名.
 //scale_factors:针对timming delay中的最小延时min,典型延迟typ,最大延时max调整延迟参数
 | 
一些书写Testbench的技巧
 
  | 1.如果激励中有一些重复的项目,可以考虑将这些语句编写成一个task,这样会给书写和仿真带来很大方便。例如,一个存储器的testbench的激励可以包含write,read等task。
 2.如果DUT中包含双向信号(inout),在编写testbench时要注意。需要一个reg变量来表示其输入,还需要一个wire变量表示其输出。
 
 3.如果initial块语句过于复杂,可以考虑将其分为互补相干的几个部分,用数个initial块来描述。在仿真时,这些initial块会并发运行。这样方便阅读和修改。
 
 4.每个testbench都最好包含$stop语句,用以指明仿真何时结束。
 
 最后提供一个简单的示例(转自Xilinx文档):
 
 DUT:
 
 module shift_reg (clock, reset, load, sel, data, shiftreg);
 
 input clock;
 
 input reset;
 
 input load;
 
 input [1:0] sel;
 
 input [4:0] data;
 
 output [4:0] shiftreg;
 
 reg [4:0] shiftreg;
 
 always @ (posedge clock)
 
 begin
 
 if (reset)
 
 shiftreg = 0;
 
 else if (load)
 
 shiftreg = data;
 
 else
 
 case (sel)
 
 2’b00 : shiftreg = shiftreg;
 
 2’b01 : shiftreg = shiftreg << 1;
 
 2’b10 : shiftreg = shiftreg >> 1;
 
 default : shiftreg = shiftreg;
 
 endcase
 
 end
 
 endmodule
 
 Testbench:
 
 module testbench; // declare testbench name
 
 reg clock;
 
 reg load;
 
 reg reset; // declaration of signals
 
 wire [4:0] shiftreg;
 
 reg [4:0] data;
 
 reg [1:0] sel;
 
 // instantiation of the shift_reg design below
 
 shift_reg dut(.clock (clock),
 
 .load (load),
 
 .reset (reset),
 
 .shiftreg (shiftreg),
 
 .data (data),
 
 .sel (sel));
 
 //this process block sets up the free running clock
 
 initial begin
 
 clock = 0;
 
 forever #50 clock = ~clock;
 
 end
 
 initial begin// this process block specifies the stimulus.
 
 reset = 1;
 
 data = 5’b00000;
 
 load = 0;
 
 sel = 2’b00;
 
 #200
 
 reset = 0;
 
 load = 1;
 
 #200
 
 data = 5’b00001;
 
 #100
 
 sel = 2’b01;
 
 load = 0;
 
 #200
 
 sel = 2’b10;
 
 #1000 $stop;
 
 end
 
 initial begin// this process block pipes the ASCII results to the
 
 //terminal or text editor
 
 $timeformat(-9,1,"ns",12);
 
 $display(" Time Clk Rst Ld SftRg Data Sel");
 
 $monitor("%t %b %b %b %b %b %b", $realtime,
 
 clock, reset, load, shiftreg, data, sel);
 
 end
 
 endmodule
 | 
》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
testbench
在顶层调用设计内部层次信号,无需将信号从端口引出,可以使用verilog的层次化调用
wire [7:0]  data = test_top.dut.data ;