- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
6.3 仿真模型建模实例
integer i; reg [35:0] line; wire [3:0] cmd = line[35:32]; // 指令 wire [15:0] addr = line[31:16]; // 地址 wire [15:0] data = line[15:0]; // 写数据或读操作期望的数据 initial begin #0 rst_n = 1'b1; write = 1'b0; select = 1'b0; resp_ok = 1'b0; #50 rst_n = 1'b0; #50 if (stat_cur != Reset) $display("error: expect Reset, stat_cur = %b", stat_cur); #50 rst_n = 1'b1; #50 i = 0; line = stimulus[i]; if (stat_cur != Idle) $display("error: expect Idle, stat_cur = %b", stat_cur); // 寄存器变量值的要在下一个仿真时刻才稳定,因此我们在进行while判断之 // 前先延迟1。 // 后面代码中也有很多#1的延迟,其作用和这里相似。
6.1 行为级建模概述
Testbench 被测模块
时钟发生器 可综合的模块
输入激励加载 模拟或者IP模块 的仿真模型 输出结果检查
被测对象我 们又可以叫 做“芯片”, 因为它描述 的是我们希 望设计的芯 片本身的功 能。
Testbench通常是用 Verilog HDL语言描述的 不可综合的模块,用来产 生与芯片真实的工作环境 相同的输入激励,来对芯 片的功能进行测试。
6.3 仿真模型建模实例
6.3.3从文件读取激励 【例6.5】用Verilog HDL语言设计一个测试环境,对本书第5章例5.9所示的有限状态机进 行测试。状态机的激励从文件中读取,该激励将模拟多次总线的传输过程,以检测状态机 是否能够按照预先设想的转换图进行状态转换。 // exmaple_6_5: Testbench for the sample bus controller FSM from example_5_9 module fsm_bus_control_tb (); reg rst_n, write, select, resp_ok; wire clk; wire [2:0] stat_cur, stat_nxt; // 激励从文件中读取后存储在该寄存器变量 reg [35:0] stimulus [0:31]; parameter Reset = 3'b000; parameter Idle = 3'b001; parameter Read = 3'b010; parameter Write = 3'b011; parameter Delay = 3'b100;
6.3 仿真模型建模实例
.o_dout(dout) ); // 加载输入激励 initial begin // 初始化仿真模型的寄存器变量 #0 rst_n = 1'b1; din = 1'b0; flag_data_check = 1'b0; // 开始进行复位,复位时间视系统要求而定 #50 rst_n = 1'b0; #50 rst_n = 1'b1; // 复位完成,向数据输入端口加载激励 #10 din = 1'b1; flag_data_check = 1'b1; // 再次加载新的激励 #50 din = 1'b0; flag_data_check = 1'b1; #50 $finish; end // 自动检测输出数据
6.3 仿真模型建模实例
#1; // 每个while循环进行一次读/写操作,即FSM状态转换一圈。 while (cmd != 4'h2) begin $display("info: cmd = %h, addr = %h, data = %h", cmd, addr, data); if (cmd == 4'h0) begin // 写操作 write = 1'b1; select = 1'b1; @ (posedge clk) #1 if (stat_cur != Write) $display("error: expect Write, stat_cur = %b", stat_cur); end else if (cmd == 4'h1) begin // 读操作 write = 1'b0; select = 1'b1; @ (posedge clk) #1 if (stat_cur != Read) $display("error: expect Read, stat_cur = %b", stat_cur); end // 等待设备回复 @ (posedge clk)
6.3 仿真模型建模实例
6.3.4输出结果监控 【例6.6】利用$monitor系统函数构建一个简单的持续监控变量值变化情况的模块。 // example_6_6: A simple signal monitor program module monitor_tb (); wire out; reg opa, opb; assign #2 out = opa & opb; initial begin #0 opa = 1'b0; opb = 1'b0; #10 opa = ~opa; #10 opb = ~opb; #10 $finish; end initial begin $monitor("out = %b; opa = %b; opb = %b", out, opa, opb); end endmodule
Verilog HDL 数字系统设计及实践
第6章 行为级仿真模型建模
学习指南
【知识目标】 (1)了解Verilog HDL语言不可综合行为描述的特点; (2)了解仿真模型和Testbench的概念和作用; (3)掌握各种常用Verilog HDL行为描述方法。 【技能目标】 (1) 熟练应用Verilog行为描述构建仿真模型和Testbench; (2) 熟练构建可进行自动测试的芯片仿真环境。 【重点难点】 (1) 行为级建模与可综合建模的区别与联系; (2) 如何构建可进行自动测试的仿真环境。
6.3 仿真模型建模实例
6.3.2简单的仿真环境
【例6.4】用Verilog HDL设计一个简单的仿真环境,对本书例5.2所示的带异步复位端口的 寄存器模块进行自动测试。 // example_6_4: Testbench for the DFF appears as example_5_2 module dff_asyn_reset_tb (); wire clk; wire dout; reg rst_n; reg din; reg flag_data_check; // 该标志位用来表示是否进行输出数据检查 clock_gen #(15) cgen ( .o_clk(clk) ); dff_asyn_reset dff1 ( .i_clk(clk), .i_rst_n(rst_n), .i_din(din),
6.3 仿真模型建模实例
always @ (posedge clk) begin if (flag_data_check) begin #1 if (din != dout) $display("error: output wrong data: dout = %b, din = %b", dout, din); else $display("ok: output correct data: dout = din = %b", dout); flag_data_check = 1'b0; end end endmodule
6.3 仿真模型建模实例
clock_gen #(15) cgen ( .o_clk(clk) ); fsm_bus_control fsm ( .i_clk(clk), .i_rst_n(rst_n), .i_write(write), .i_sel(select), .i_ok(resp_ok), .o_stat_next(stat_nxt), .o_stat_current(stat_cur) ); // 利用$readmemh系统函数从文件中读取激励 initial $readmemh("fsm_sim.dat", stimulus); // 循环从stimulus变量中读取指令
图6.1 一个完整的芯片设计工程
一个完整的芯片设计工程应该包含Testbench测试 环境的设计和被测对象的设计。
6.2 仿真时间和时序控制
在运行真实芯片时,芯片的各个时间参数和我们真实生活中使用的时间是相同的。在 仿真的时候,我们也有自己的时间,这个时间是仿真器虚拟出来的,与真实的时间不一定 相同。 复杂的电路行为往往在时间上有很强的前后依赖关系。在可综合的电路描述中,这种 时序上的控制只能通过同步时钟和有限状态机来实现。当电路的功能变得复杂以后,对时 序控制逻辑的设计也变得越来越困难。 Verilog HDL提供的时序控制语句主要有3种:延迟控制语句,事件控制语句和条件等 待语句。 延迟控制语句用#加数字的形式来表示程序继续运行需要等待的仿真时间。 ... initial begin #10 a = b; #20 a = c; end
6.3 仿真模型建模实例
6.3.1 时钟发生器 时钟发生器是Verilog HDL仿真模型中最重要的模块。所有硬件电路的工作都离不开时钟 输入。同步时序电路中的存储单元在时钟沿触发,对电路的数据流和状态进行控制。
【例6.1】用Verilog HDL设计一个时钟发生模块。时钟周期可通过参数period调节,占空 比为50% // example_6_1: A simple clock generator for simulation module clock_gen #( parameter period = 10 ) ( output reg o_clk ); initial // 设置时钟的初始值 o_clk = 1'b0; // 每隔半周期,时钟信号反转一次。 always #(period/2) o_clk = ~o_clk; endmodule
6.3 仿真模型建模实例
#1 if (stat_cur != Delay) $display("error: expect Delay, stat_cur = %b", stat_cur); // 没有给ok信号,Delay状态应该保持 @ (posedge clk) #1 if (stat_cur != Delay) $display("error: expect Delay, stat_cur = %b", stat_cur); resp_ok = 1'b1; @ (posedge clk) #1 if (stat_cur != Idle) $display("error: expect Idle, stat_cur = %b", stat_cur); i = i + 1; line = stimulus[i]; resp_ok = 1'b0; #1; end #50 $finish; end endmodule
6.2 仿真时间和Βιβλιοθήκη Baidu序控制
事件控制语句指利用语法@()进行描述。@后面的括号里包含需要等待的事件。当 事件满足后,程序继续运行,事件不满足时,程序等待在此处,直到条件满足。 ... initial begin @ (posedge clk) a = b; @ (posedge clk) #10 a = b; end 条件等待语句是指用关键词wait描述的过程语句。 ... initial begin wait (rst_n) a = b; @ (rst_n) a = c; end