request信号定义为测试端输出,待测设计端输入。
接口定义:
// interface
这里定义了两个在时钟clk上升沿触发的时钟块tcb和dcb,分别用在两个modport分组中,TESTTCB和DUTDCB。
另外,针对后面说到的两种情形,先定义好4个模块:
// drive signal in clock block
情形一 测试端驱动request信号,通过时钟块向外输出request信号。
测试平台顶层模块如下:
module
在时钟块内的request信号原始波形如图中 /top/arbif/tcb/request。通过时钟块驱动后,DUT端收到的信号波形如图中 /top/arbif/request。
接收端DUT monitor到的输出如下:
注意到在两个时钟周期(上升沿)之间产生的值2丢失了!(因为在第三个时钟周期的上升沿产生了新值3。是这样解释的吗?)
情形二 接收端通过时钟块接收request信号。
测试平台顶层模块如下:
module
request信号输出波形如图中 /top/arbif/request。接收端通过时钟块采样信号波形如图中 /top/arbif/dcb/request。
接收端monitor的结果如下:
第三个时钟周期上升沿采样到的是上升沿到来之前获得接口数据2。只在下一个时钟周期(上升沿)采样到数据3。
怎么理解这种差异?
IEEE Std 1800-2017, Ch.14.3(Clocking block declaration) and Ch.14.4(Input and output skews):
"Unless otherwise specified, the default input skew is 1step and the default output skew is 0. A step is a special time unit whose value is defined in 3.14.3. A 1step input skew allows input signals to sample their steady-state values in the time step immediately before the clock event (i.e., in the preceding Postponed region)."
"Input (or inout) signals are sampled at the designated clock event. If an input skew is specified, then the signal is sampled at skew time units before the clock event. Similarly, output (or inout) signals are driven skew simulation time units after the corresponding clock event. Figure 14-1 shows the basic sample and drive timing for a positive edge clock."
...
"An input skew of 1step indicates that the signal is to be sampled at the end of the previous time step. In other words, the value sampled is always the signal's last value immediately before the corresponding clock edge."
...
"Inputs with explicit #0 skew shall be sampled at the same time as their corresponding clocking event, but to avoid races, they are sampled in the Observed region. Likewise, clocking block outputs with no skew (or explicit #0 skew) shall be driven at the same time as their specified clocking event, in the Re-NBA region."
关于timing region,参阅 IEEE Std for SystemVerilog, Ch.4 Scheduling semantics
因此
情形一,tcb时钟块的request信号做为输出信号,默认output skew为0,即在时钟上升沿时刻的Re-NBA时区驱动,此时request信号已经更新的新值3,故而输出给DUT是3。导致从外部看到中间的值2丢失。
在情形二中,dcb时钟块的request信号做为输入信号,默认input skew是1step,采样的始终是时钟边缘之前的最后的值,即值2。
思考一下,在链接页面有如下截屏(如果没有更新的话)。仿真的结果是否有问题?
SystemVerilog Clocking Blocks Part IIwww.chipverify.comcb_0: input #0 gnt;
cb_1: input #1step gnt;
cb_2: input #1 gnt;
cb_3: input #2 gnt;
以上都是@(posedge clk)
按照标准文档,Figure 14-1,作为input,采样发生在时钟沿之前。
所以,cb_2, cb_3得到的应当是分别提前1,2个时间单位之前的值,即分别是0x9, 0x1。cb_1得到的是当前时钟沿之前的值,即0x3。而特别的,cb_0: input #0 gnt, 则是对应时钟时刻的Observed region的值,得到的是时钟沿后面的值,即0xd。
所以最后的输出应该是:
cb_3.gnt = 0x1
cb_2.gnt = 0x9
cb_1.gnt = 0x3
cb_0.gnt = 0xd
用modelsim跑下来的结果,也的确如此。(使用modelsim仿真时,如果Objects窗口找不到clk信号,可能是因为仿真优化的原因。关掉优化选项 -- 有些事当时搞清楚了,一段时间回头再做,又不知所措。还是写下来吧!)