路科IC验证--SVlab1中的细节
仿真器是questasim,运行lab1需要配置的文件
本文主要分析tb4中的代码细节
tb4.sv代码

`timescale 1ns/1ps module chnl_initiator( input clk, input rstn, output logic [31:0] ch_data, output logic ch_valid, input ch_ready, input [ 5:0] ch_margin ); string name; function void set_name(string s); name = s; endfunction task chnl_write(input logic[31:0] data); // USER TODO // drive valid data // ... @(posedge clk); ch_valid <= 1; ch_data <= data; @(negedge clk); wait(ch_ready === 'b1); $display("%t channel initial [%s] sent data %x", $time, name, data); chnl_idle(); endtask task chnl_idle(); // USER TODO // drive idle data // ... @(posedge clk); ch_valid <= 0; ch_data <= 0; endtask endmodule module tb4; logic clk; logic rstn; logic [31:0] ch0_data; logic ch0_valid; logic ch0_ready; logic [ 5:0] ch0_margin; logic [31:0] ch1_data; logic ch1_valid; logic ch1_ready; logic [ 5:0] ch1_margin; logic [31:0] ch2_data; logic ch2_valid; logic ch2_ready; logic [ 5:0] ch2_margin; logic [31:0] mcdt_data; logic mcdt_val; logic [ 1:0] mcdt_id; mcdt dut( .clk_i(clk) ,.rstn_i(rstn) ,.ch0_data_i(ch0_data) ,.ch0_valid_i(ch0_valid) ,.ch0_ready_o(ch0_ready) ,.ch0_margin_o(ch0_margin) ,.ch1_data_i(ch1_data) ,.ch1_valid_i(ch1_valid) ,.ch1_ready_o(ch1_ready) ,.ch1_margin_o(ch1_margin) ,.ch2_data_i(ch2_data) ,.ch2_valid_i(ch2_valid) ,.ch2_ready_o(ch2_ready) ,.ch2_margin_o(ch2_margin) ,.mcdt_data_o(mcdt_data) ,.mcdt_val_o(mcdt_val) ,.mcdt_id_o(mcdt_id) ); // clock generation initial begin clk <= 0; forever begin #5 clk <= !clk; end end // reset trigger initial begin #10 rstn <= 0; repeat(10) @(posedge clk); rstn <= 1; end logic [31:0] chnl0_arr[]; logic [31:0] chnl1_arr[]; logic [31:0] chnl2_arr[]; // USER TODO // generate 100 data for each dynamic array initial begin chnl0_arr = new[100]; chnl1_arr = new[100]; chnl2_arr = new[100]; foreach(chnl0_arr[i]) begin chnl0_arr[i] = 'h00C0_00000 + i; chnl1_arr[i] = 'h00C1_00000 + i; chnl2_arr[i] = 'h00C2_00000 + i; end end // USER TODO // use the dynamic array, user would send all of data // data test initial begin @(posedge rstn); repeat(5) @(posedge clk); chnl0_init.set_name("chnl0_init"); foreach(chnl0_arr[i]) chnl0_init.chnl_write(chnl0_arr[i]); end initial begin @(posedge rstn); repeat(5) @(posedge clk); chnl0_init.set_name("chnl0_init"); foreach(chnl0_arr[i]) chnl0_init.chnl_write(chnl0_arr[i]); end initial begin @(posedge rstn); repeat(5) @(posedge clk); chnl0_init.set_name("chnl0_init"); foreach(chnl0_arr[i]) chnl0_init.chnl_write(chnl0_arr[i]); end chnl_initiator chnl0_init( .clk (clk), .rstn (rstn), .ch_data (ch0_data), .ch_valid (ch0_valid), .ch_ready (ch0_ready), .ch_margin(ch0_margin) ); chnl_initiator chnl1_init( .clk (clk), .rstn (rstn), .ch_data (ch1_data), .ch_valid (ch1_valid), .ch_ready (ch1_ready), .ch_margin(ch1_margin) ); chnl_initiator chnl2_init( .clk (clk), .rstn (rstn), .ch_data (ch2_data), .ch_valid (ch2_valid), .ch_ready (ch2_ready), .ch_margin(ch2_margin) ); endmodule
initial begin @(posedge rstn); repeat(5) @(posedge clk); chnl0_init.set_name("chnl0_init"); foreach(chnl0_arr[i]) chnl0_init.chnl_write(chnl0_arr[i]); end
【问题】:三个initial中开启通道采样的代码中为什么用repeat(5)?
【解答与分析】
注意到repeat(5)后面没跟beign,所以只能作用到后面的第一个语句。即循环5次时钟上升沿。
对于复杂设计,其内部reset周期不一定在当前外部的reset周期,有可能需要消化,还要去过一拍两拍的情况,它才能做完reset。因此等待5个时钟上升沿,改为等待1个时钟上升沿也没问题(对于lab1这mcdt小型设计而言)
task chnl_write(input logic[31:0] data); // USER TODO // drive valid data // ... @(posedge clk); ch_valid <= 1; ch_data <= data; @(negedge clk); wait(ch_ready === 'b1); $display("%t channel initial [%s] sent data %x", $time, name, data); chnl_idle(); endtask
【问题】:delta-cycle竞争问题,如何理解@(negedge clk); wait(ch_ready ==='b1)代码含义?
仿真图
【解答与分析】
看图中红线的时钟沿,在红线位置,ch2_ready_0采样到的信号到底是0还是1呢?
事实上,在当前的时钟沿,ch2_ready_0采样到的值只能是时钟沿左边的值0。从设计的逻辑来讲,ready信号的反馈和当前这一拍的时钟沿,它是在同一拍里边发生的,在同一拍发生的情况,要按照组合逻辑来处理,组合逻辑来处理的话,它是没有是时钟这样一个延时的关系的。(组合逻辑是瞬发的)而现在需要捕捉时钟上升沿右边的这部分值,才能实现:判断在这一时钟沿是ready信号的为高的功能。如果你捕捉的是左边这个值,那么它在红线那一时刻是0,只有到下一个时钟上升沿才是1,而后面有chnl_idle的任务,会使得验证代码延时时间冗余。
一般使用统一延时时钟下降沿。统一延时时钟下降沿其实就是为了捕捉的更准确,方便复用,因为一旦使用时钟的下降沿则不需要关心时钟的周期。当然直接延时1ps、1ns也是可以的,但是这样要考虑时钟周期,若原时钟周期1ns,直接延时2ns,则会出现延时了两个时钟周期,造成错误。
------------------
题外话:路桑对这块delta-cycle的讲解非常精彩
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· .NET Core 中如何实现缓存的预热?
· 三行代码完成国际化适配,妙~啊~
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?