1. 为什么要了解SV Schedule
- verilog是一个硬件描述语言,而硬件在现实中都是并行执行的,所以verilog描述的组合电路和时序电路都是并行执行的。
- 而仿真器作为运行在CPU上的软件,只是按照SV LRM的仿真调度算法,开始仿真后,将仿真时间串行的一步步的向前推进。
- 因此,实际DUT中同时发生的动作由模拟器建模为一组有序动作,依次执行。如果不能很好地撰写RTL代码和TestBench,那么仿真可能得到不匹配的结果:即DUT为正确,但是仿真却报告错误;或者DUT为错误,但是仿真却报告正确。
- 依照已经非常成熟的Coding规则,可以避免90%~100%由Verilog RTL设计引起的问问题。此外,还需要了解Verilog / SystemVerilog Schedule才能更好地理解规则。
1.1 几个需要遵守的RTL编码规则
- 时序逻辑使用nonblocking assignments(<=)
- Latch 使用 nonblocking assignments (<=)
- always块描述组合逻辑时使用 blocking assignments (=)
- 在同一个always块中混用组合逻辑和时许逻辑时使用nonblocking assignments(<=)
- 在同一个always块中不要混用 (<=) 和 (=)
- 不能在不同的always块中对同一变量进行赋值
- 使用$strob函数来打印使用nonblocking assignments的变量
- 不要使用 #0 延时
2. Verilog的调度
- IEEE Std 1364-2001将 Verilog 事件区域划分为四个有序区域: Active、Inactive、NBA、Postponed。
- Verilog只有module,没有program,故所有的调度都是基于Module模块的
- Active region:
- 执行blocking assignments
- 计算非阻塞赋值的右式(并不会更新左边)
- 连续赋值
- $display()函数
- 评估 Verilog 原语的输入和更新输出
- Inactive region:
- 执行带#0延时的阻塞赋值
- NBA region(Nonblocking Assignments):
- 更新非阻塞赋值的左式(现在才被更新)
- Postponed:
- $monitor
- $strobe
- 下图为Verilog的调度图,将Inactive画叉代表RTL Coding时不要使用#0延时
2.1 continue assignment
- 几个连续赋值的例子
wire mynet ;
assign (strong1, pull0) mynet = enable;
assign {carry_out, sum_out} = ina + inb + carry_in;
assign data = (s == 0) ? bus0 : Zee,
2.2 使用Verilog进行设计和验证时的race
- 下面为一个用verilog写的RTL和Testbench
- DUT中,a和b应该时延后一拍的关系,但是仿真出来,a和b波形居然一致。
- 问题在于DUT和Testbench之间的race,在第一个clk上升沿,a在Test中被赋值为1,DUT中计算NBA的RHS(Right-Hand-Side),a为1。随后在NBA region,DUT中Update LHS,此时b被更新为1。故波形就如上图所示。
- 为了避免该问题,可以在Test中加入#0延时
- 此仿真图得到DUT中a和b有一拍延时关系,符合设计预期。
- 因为在第一个clk上升沿的时候,执行DUT中的RHS时,a还是初始值0,然后到了Inactive region,执行了Test中的 #0,此时Test中的a被赋值为1,然后在NBA region,更新DUT中b的值,b被更新为0,故复位上图波形。
3. 为什么需要SystemVerilog
- 上面已经了解到单纯用Verilog很容易引起DUT和Test之间的race,故引入了SV。SystemVerilog中引入了Program,从而将module和Program的调度分开,达到减少race的目的。
- IEEE Std 1800-2005的更新将 SystemVerilog 的timeslot分为17个有序区域、9个有序区域用于执行 SystemVerilog 语句和8个有序区域用于执行 PLI (Programming language interface)代码。
- 暂时不考虑PLI,删除PLI后的SystemVerilog的时间区域划分如下:
- 大致可以分为4个region:Preponed,Active(Active、Inactive、NBA),Observed,Reactive(Reactive、Re-Inactive、Re-NBA)
- Preponed region :
- 断言的信号采样(只是采样,并没有执行)
- Active region :
- 兼容Verilog调度(for module)
- Observed region:
- 执行断言的计算
- 断言可能还会引起块的计算,会调回到active(module中的断言)或reactive(program中的断言)中去,这也就是图中Observed下个可以往其他区域流转的原因。
- ReActive region :
- 类似Verilog中的调度,只不过是对于Program。(for program)
- Postponed :
- $monitor
- $strobe
3.1 Preponed和Postponed的说明
- Preponed采样的值是该timeslot的最初的值,Postponed采样的值是该timeslot的最后更新了的值。
- 上一个timeslot的Postponed采样到的值和下一个timeslot的Preponed采样到的值相同,只是timeslot不同而已。
3.2 采样Program后的仿真
- 拥有了SV后,那么可以将设计代码写成Module模块,将test代码写成Program模块
- Program中不能再层次化调用任何其他模块(program、module、interface)
- 上面的例子中,当test使用program … endprogram后,不再需要加#0。
4. 参考文献
CummingsSNUG2006Boston_SystemVerilog_Events.pdf
IEEE Standard for SystemVerilog (Revision of IEEE Std 1800-2012)