verilog 代码设计完成后,还需要进行重要的步骤,即逻辑功能仿真。仿真激励文件称之为 testbench,放在各设计模块的顶层,以便对模块进行系统性的例化调用进行仿真。
毫不夸张的说,对于稍微复杂的 verilog 设计,如果不进行仿真,即便是经验丰富的老手,99.9999% 以上的设计都不会正常的工作。不能说仿真比设计更加的重要,但是一般来说,仿真花费的时间会比设计花费的时间要多。有时候,考虑到各种应用场景,testbench 的编写也会比 verilog 设计更加的复杂。所以,数字电路行业会具体划分设计工程师和验证工程师。
下面,对 testbench 做一个简单的学习。
testbench 结构划分
testbench 一般结构如下。
其实 testbench 最基本的结构包括信号声明、激励和模块例化。
根据设计的复杂度,需要引入时钟和复位部分。当然更为复杂的设计,激励部分也会更加复杂。根据自己的验证需求,选择是否需要自校验和停止仿真部分。
当然,复位和时钟产生部分,也可以看做激励,所以它们都可以在一个语句块中实现。也可以拿自校验的结果,作为结束仿真的条件。
实际仿真时,可以根据自己的个人习惯来编写 testbench,这里只是做一份个人的总结。
testbench 仿真举例
前面的章节中,已经写过很多的 testbench。其实它们的结构也都大致相同。下面,列举一个数据拼接的简单例子,对 testbench 再做一个具体的分析。
◆ 一个 2bit 数据拼接成 8bit 数据的功能模块描述如下。
module data_consolidation ( input clk , input rstn , input [1:0] din , //data in input din_en , output [7:0] dout , output dout_en //data out ); // data shift and counter reg [7:0] data_r ; reg [1:0] state_cnt ; always @(posedge clk or negedge rstn) begin if (!rstn) begin state_cnt <= 'b0 ; data_r <= 'b0 ; end else if (din_en) begin state_cnt <= state_cnt + 1'b1 ; //数据计数 data_r <= {data_r[5:0], din} ; //数据拼接 end else begin state_cnt <= 'b0 ; end end assign dout = data_r ; // data output en reg dout_en_r ; always @(posedge clk or negedge rstn) begin if (!rstn) begin dout_en_r <= 'b0 ; end //计数为 3 且第 4 个数据输入时,同步输出数据输出使能信号 else if (state_cnt == 2'd3 & din_en) begin dout_en_r <= 1'b1 ; end else begin dout_en_r = 10000) begin if (!err_cnt) begin $display(-------------------------------------); $display(data process is ok!!!); $display(-------------------------------------); end else begin $display(-------------------------------------); $display(error occurs in data process!!!); $display(-------------------------------------); end #1 ; $finish ; end endendmodule // test◆仿真结果如下。由图可知,数据整合功能的设计符合要求。
testbench 具体分析
1)信号声明
testbench 模块声明时,一般不需要声明端口。因为激励信号一般都在 testbench 模块内部,没有外部信号。
声明的变量应该能全部对应被测试模块的端口。当然,变量不一定要与被测试模块端口名字一样。但是被测试模块输入端对应的变量应该声明为 reg 型,如 clk,rstn 等,输出端对应的变量应该声明为 wire 型,如 dout,dout_en。
2)时钟生成
生成时钟的方式有很多种,以下两种生成方式可以借鉴。
initial clk = 0 ;always #(cycle_200mhz/2) clk = ~clk;initial begin clk = 0 ; forever begin #(cycle_200mhz/2) clk = ~clk; endend需要注意的是,利用取反方法产生时钟时,一定要给 clk 寄存器赋初值。
利用参数的方法去指定时间延迟时,如果延时参数为浮点数,该参数不要声明为 parameter 类型。例如实例中变量 cycle_200mhz 的值为 2.5。如果其变量类型为 parameter,最后生成的时钟周期很可能就是 4ns。当然,timescale 的精度也需要提高,单位和精度不能一样,否则小数部分的时间延迟赋值也将不起作用。
3)复位生成
复位逻辑比较简单,一般赋初值为 0,再经过一段小延迟后,复位为 1 即可。
这里大多数的仿真都是用的低有效复位。
4)激励部分
激励部分该产生怎样的输入信号,是根据被测模块的需要来设计的。
本次实例中,(4.1) 对被测模块的输入信号进行一个初始化,防止不确定值 x 的出现。
激励数据的产生,需要从数据文件内读入。(4.2) 处利用一个 task 去打开一个文件,只要指定文件存在,就可以得到一个不为 0 的句柄信号 fp_rd。fp_rd 指定了文件数据的起始地址。
(4.3) 的操作是为了等待复位后,系统有一个安全稳定的可测试状态。
(4.4) 开始循环读数据、给激励。在时钟下降沿送出数据,是为了被测试模块能更好的在上升沿采样数据。
利用系统任务 $fread ,通过句柄信号 fd_rd 将读取的 16bit 数据变量送入到 read_temp 变量进行缓存。
输入数据文件前几个数据截图如下。因为 $fread 只能读取 2 进制文件,所以输入文件的第一行对应的 ascii 码应该是 330a,所以我们想要得到文件里的数据 3,应该取变量 read_temp 的第 9 到第 8bit 位的数据。
信号 data_in_temp 是对输入数据信号的一个紧随的整合,后面校验模块会以此为参考,来判断仿真是否正常,模块设计是否正确。
(4.5) 选择在时钟上升沿延迟 2 个周期后停止输入数据,是为了被测试模块能够正常的采样到最后一个数据使能信号,并对数据进行正常的整合。
当数据量相对较少时,可以利用 verilog 中的系统任务 $readmemh 来按行直接读取 16 进制数据。保持文件 data_in.dat 内数据和格式不变,则该激励部分可以描述为:
reg [1:0] data_mem [39:0] ; reg [7:0] data_in_temp ; //for self check integer k1 ; initial begin din_en = 1'b0 ; din = 'b0 ; $readmemh(../tb/data_in.dat, data_mem); wait (rstn) ; # cycle_200mhz ; //read data from file for(k1=0; k1< 40; k1=k1+1) begin @(negedge clk) ; din = data_mem[k1] ; data_in_temp = {data_in_temp[5:0], din} ; din_en = 1'b1 ; end //stop data @(posedge clk) ; #2 din_en = 1'b0 ; end5)模块例化
这里利用 testbench 开始声明的信号变量,对被测试模块进行例化连接。
6)自校验
如果设计比较简单,完全可以通过输入、输出信号的波形来确定设计是否正确,此时可以不采用自校验部分。如果数据很多,有时候拿肉眼观察并不能对设计的正确性进行一个有效判定。此时加入一个自校验模块,会大大增加仿真的效率。
实例中,我们会在数据输出使能 dout_en 有效时,对输出数据 dout 与参考数据 read_temp(激励部分产生)做一个对比,并将对比结果置于信号 err_cnt 中。最后就可以通过观察 err_cnt 信号是否为 0 来直观的对设计的正确性进行判断。
如实例中所示,也可以将数据写入到对应文件中,利用其他方式对两个文件进行对比。
7)结束仿真
如果我们不加入结束仿真部分,仿真就会无休止的运行下去,波形太长有时候并不方便分析。verilog 中提供了系统任务 $finish 来停止仿真。
停止仿真之前,可以将自校验的结果,通过系统任务 $display 在终端进行显示。
文件读写选项
用于打开文件的系统任务 $fopen 格式如下:
fd = $fopen(, mode)和 c 语言类似,打开方式的选项 mode 意义如下:
氮化镓功率器件电压650V限制原因
罗德与施瓦茨空管辅助测向系统CERTIUM Locate已通过最终验收
工业智能网关实现的功能是
测报工具箱可以大大提高病虫害测报工作的效率
飞秒激光:细分时间,细分领域
Verilog仿真激励举例
对于海尔电器而言 能否保住过往积累下的竞争优势仍有待时间的检验
具有高灵敏度和良好指向性的新型MEMS压电矢量水听器
高分子电容器的基本参数
家庭用的蔬菜农药残留检测仪的功能有哪些?
魅族Pro7超憋屈:魅蓝新机将带副屏,便宜太多!
NE555引脚图及应用电路
六六顺——东南大学文章总汇 | 科技老兵戴辉
怎样做物联网时代的先行者
美国施压下,华为5G在欧洲遇冷,亚太市场却收获颇丰
vivo X60系列斩获京东手机销量与销售额双冠军
华为Mate30系列和华为MateBook系列笔记本新功能曝光支持多屏协同
恒生电子股灾后豪赌区块链,是否能重生?
realme智能手表通过印度BIS认证,将于2020年上半年推出
5G与物联网结合将如何改变各个领域