用verilog写了一段分频器的程序,想仿真出图是不是需要些testbench,如果需要下面的验证程序怎么写啊

用verilog写了一段分频器的程序,想仿真出图是不是需要些testbench,如果需要下面的验证程序怎么写啊,第1张

module tb_clk;
// Inputs
reg clk_100m;
reg rst;
// Outputs
wire clk_1m;
// Instantiate the Unit Under Test (UUT)
sdio_slave uut (
clk_100m(clk_100m),
rst(rst),
clk_1m(clk_1m)
);
initial begin
// Initialize Inputs
clk_100m=0;
rst= 0;
// Wait 100 ns for global reset to finish
#100;
rst=1;
#100000;
$finish
end
always #5 clk_100m=!clk_100m;
endmodule
O了 但是就怕给了你代码,你连仿真软件都不会用

如何编写 testbench 的总结(非常实用的总结) 1.激励的设置 相应于被测试模块的输入激励设置为 reg 型,输出相应设置为 wire 类型,双向端口 inout 在 测试中需要进行处理。 方法 1:为双向端口设置中间变量 inout_reg 作为该 inout 的输出寄存,inout 口在 testbench 中要定义为 wire 型变量,然后用输出使能控制传输方向。 eg: inout[0:0]bi_dir_port; wire[0:0]bi_dir_port; reg[0:0]bi_dir_port_reg; regbi_dir_port_oe; assignbi_dir_port=bi_dir_port_oebi_dir_port_reg:1'bz; 用 bi_dir_port_oe 控制端口数据方向,并利用中间变量寄存器改变其值。等于两个模块之间 用 inout 双向口互连。往端口写(就是往模块里面输入) 方法 2:使用 force 和 release 语句,这种方法不能准确反映双向端口的信号变化,但这种方 法可以反映块内信号的变化。具体如示: moduletest(); wiredata_inout; regdata_reg; reglink; #xx;//延时 forcedata_inout=1'bx;//强制作为输入端口 #xx; releasedata_inout;//释放输入端口 endmodule 从文本文件中读取和写入向量 1)读取文本文件:用$readmemb 系统任务从文本文件中读取二进制向量(可以包含输入激 励和输出期望值) 。$readmemh 用于读取十六进制文件。例如: reg[7:0]mem[1:256]//a8-bit,256-word 定义存储器 mem initial$readmemh("memdata",mem)// 将dat 文件读入寄存器 mem 中 initial$readmemh("memdata",mem,128,1)// 参数为寄存器加载数据的地址始终 2)输出文本文件:打开输出文件用$fopen 例如: integerout_file;//out_file 是一个文件描述,需要定义为 integer 类型 out_file=$fopen("cpudata");//cpudata 是需要打开的文件,也就是最终的输出文本 设计中的信号值可以通过$fmonitor,$fdisplay, 2Verilog 和 Ncverilog 命令使用库文件或库目录 ex)ncverilog-frunf-vlib/libv-ylib2+libext+v//一般编译文件在 runf 中, 库文件在 libv 中,lib2 目录中的v 文件系统自动搜索 使用库文件或库目录,只编译需要的模块而不必全部编译 3.VerilogTestbench 信号记录的系统任务: 1)SHM 数据库可以记录在设计仿真过程中信号的变化 它只在 probes 有效的时间内记录你 setprobeon 的信号的变化 ex)$shm_open("wavesshm");//打开波形数据库 $shm_probe(top,"AS");//setprobeon"top", 第二个参数:A--signalsofthespecificscrope S--Portsofthespecifiedscopeandbelow,excludinglibrarycells C--Portsofthespecifiedscopeandbelow,includinglibrarycells AS--Signalsofthespecifiedscopeandbelow,excludinglibrarycells AC--Signalsofthespecifiedscopeandbelow,includinglibrarycells 还有一个 M,表示当前 scope 的 memories,可以跟上面的结合使用,"AM""AMS""AMC" 什么都不加表示当前 scope 的 ports; $shm_close//关闭数据库 2)VCD 数据库也可以记录在设计仿真过程中信号的变化 它只记录你选择的信号的变化 ex)$dumpfile("filename");//打开数据库 $dumpvars(1,topu1);//scope=topu1,depth=1 第一个参数表示深度, 为 0 时记录所有深度; 第二个参数表示 scope,省略时表当前的 scope $dumpvars;//depth=allscope=all $dumpvars(0);//depth=allscope=current $dumpvars(1,topu1);//depth=1scope=topu1 $dumpoff//暂停记录数据改变,信号变化不写入库文件中 $dumpon//重新恢复记录 3)Debussyfsdb 数据库也可以记录信号的变化,它的优势是可以跟 debussy 结合,方便调试 如果要在 ncverilog 仿真时,记录信号, 首先要设置 debussy: asetenvLD_LIBRARY_PATHLD_LIBRARY_PATH (pathfordebplisofile(/share/PLI/nc_xl//nc_loadpli1)) bwhileinvokingncverilogusethe+ncloadpli1option ncverilog-frunf+debug+ncloadpli1=debpli:deb_PLIPtr fsdb 数据库文件的记录方法,是使用$fsdbDumpfile 和$fsdbDumpvars 系统函数,使用方法参见 VCD 注意: 在用 ncverilog 的时候,为了正确地记录波形,要使用参数:"+access+rw", 否则没有读写 权限 在记录信号或者波形时需要指出被记录信号的路径,如:tbmoduleu1clk 关于信号记录的系统任务的说明: 在 testbench 中使用信号记录的系统任务,就可以将自己需要的部分的结果以及波形文件记 录下来(可采用 sigalscan 工具查看) ,适用于对较大的系统进行仿真,速度快,优于全局仿 真。使用简单,在 testbench 中添加: initialbegin $shm_open("wavesshm"); $shm_probe("要记录信号的路径“, ”AS“) ; #10000 $shm_close;即可。 4ncverilog 编译的顺序:ncverilogfile1file2 有时候这些文件存在依存关系,如在 file2 中要用到在 file1 中定义的变量,这时候就要注意其 编译的顺序是 从后到前,就先编译 file2 然后才是 file2 5信号的强制赋值 force 首先, force 语句只能在过程语句中出现,即要在 initial 或者 always 中间 去除 force 用 release 语句 initialbeginforcesig1=1'b1;;releasesig1;end force 可以对 wire 赋值,这时整个 net 都被赋值; 也可以对 reg 赋值 6.加载测试向量时,避免在时钟的上下沿变化 为了模拟真实器件的行为,加载测试向量时,避免在时钟的上下沿变化,而是在时钟的上升 沿延时一个时间单位后,加载的测试向量发生变化。如: assign#5c=a^b @(posedgeclk)#(01`cycle)A=1; //testbench 的波形输出 moduletop; initial begin $dumpfile("/topvcd");//存储波形的文件名和路径,一般是vcd 格式 $dumpvars(1,top);//存储 top 这一层的所有信号数据 $dumpvars(2,topu1);//存储 topu1 之下两层的所有数据信号(包含 topu1 这一层) $dumpvars(3,topu2);//存储 topu2 之下三层的所有数据信号(包含 topu2 这一层) $dumpvars(0,topu3);//存储 topu3 之下所有层的所有数据信号 end endmodule //产生随机数,seed 是种子 $random(seed); ex:din<=$random(20); //仿真时间,为 unsigned 型的 64 位数据 $time ex: timecondition_happen_time; condition_happen_time=$time; $monitor($time,"dataoutput=%d",dout); //参数 parameterpara1=10, para2=20, para3=30; //显示任务 $display(); //监视任务 $monitor(); //延迟模型 specify //describpin-to-pindelay endspecify ex: modulenand_or(Y,A,B,C); inputA,B,C; outputY; AND2#02(N,A,B); OR2#01(Y,C,N); specify (A->Y)=02; (B->Y)=03; (C->Y)=01; endspecify endmodule //时间刻度 `timescale 单位时间/时间精确度 //文件 I/O 1打开文件 integerfile_id; file_id=fopen("file_path/file_name"); 2写入文件 //$fmonitor 只要有变化就一直记录 $fmonitor(file_id,"%format_char",parameter); egfmonitor(file_id,"%m:%tin1=%do1=%h",$time,in1,o1); //$fwrite 需要触发条件才记录 $fwrite(file_id,"%format_char",parameter); //$fdisplay 需要触发条件才记录 $fdisplay(file_id,"%format_char",parameter); $fstrobe(); 3读取文件 integerfile_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:针对 timmingdelay 中的最小延时 min,典型延迟 typ,最大延时 max 调整延迟参 数 //generate 语句,在 Verilog-2001 中定义用于表达重复性动作 //必须事先声明 genvar 类型变量作为 generate 循环的指标 eg: genvari; generatefor(i=0;i<4;i=i+1) begin assign=din=i%2; end endgenerate //资源共享 always@(AorBorCorD) sum=sel(A+B) C+D); //上面例子使用两个加法器和一个 MUX,面积大 //下面例子使用一个加法器和两个 MUX,面积小 always@(AorBorCorD) begin tmp1=selA:C; tmp2=selB ; end always@(tmp1ortmp2) sum=tmp1+tmp2; 模板: moduletestbench;//定义一个没有输入输出的 module reg//将 DUT 的输入定义为 reg 类型 wire//将 DUT 的输出定义为 wire 类型 //在这里例化 DUT initial begin //在这里添加激励(可以有多个这样的结构) end always//通常在这里定义时钟信号 initial //在这里添加比较语句(可选) end initial //在这里添加输出语句(在屏幕上显示仿真结果) end endmodule 一下介绍一些书写 Testbench 的技巧: 1如果激励中有一些重复的项目,可以考虑将这些语句编写成一个 task,这样会给书写和仿 真带来很大方便。例如,一个存储器的 testbench 的激励可以包含 write,read 等 task。 2如果 DUT 中包含双向信号(inout),在编写 testbench 时要注意。需要一个 reg 变量来表示 其 输入,还需要一个 wire 变量表示其输出。 3如果 initial 块语句过于复杂,可以考虑将其分为互补相干的几个部分,用数个 initial 块来 描述。在仿真时,这些 initial 块会并发运行。这样方便阅读和修改。 4每个 testbench 都最好包含$stop 语句,用以指明仿真何时结束。

`timescale 1ns/100ps
module testbench ();

reg a;
//reg b;
wire c;
trrry DUT (
a(a),
//b(b),
c(c)
);

initial begin
a = 1;

end

endmodule
module trrry(a, c);
input a;
wire b;
output c;

ad ad(a, b);

bc bc(b, c);

endmodule
module ad(a, b);
input wire a;
output b;

always @ ()
b = a;

endmodule
module bc(b, c);
input wire b;
output c;

always @ ()
c = b;

endmodule
我改了一些,你试试

`timescale 1ns/1ns
module testbench ();
reg clk;
initial
begin
clk = 0;
repeat(1000) #500 clk = ~clk;
repeat(2000) #250 clk = ~clk;
$finish;
end
endmodule
如果定义`timescale 10ns/10ns
改为repeat(1000) #50 clk = ~clk;
repeat(2000) #25 clk = ~clk;
降低了仿真精度 可以提高仿真速度
如果定义`timescale 100ns/100ns
改为repeat(1000) #5 clk = ~clk;
repeat(1000)
begin
#3 clk = ~clk;
#2 clk = ~clk;
end
进一步降低了仿真精度同时提高仿真速度 但时钟占空比不再是1:1 对一般的rtl仿真也没有影响


欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/yw/12799652.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-28
下一篇 2023-05-28

发表评论

登录后才能评论

评论列表(0条)

保存