逻辑在具体实现上是通过2个计数器来控制100ms的计时控制,具体如下:
定义计数器A(取值范围在0~9),计数器B(取值范围0~38399),且计数器B的启动是在计数器A取值为9时才开始,而计数器A的计数条件为模块端口输入的10ms同步信号。
在Netlist仿真中验证这个100ms能量统计时,如果基于Netlist仿真真实的100ms需要很长的时间(以周为时间单位了),为了达到测试的目的,直接将逻辑内部的A计数器Force到目标值的附近(force成8),也即给计数器A一个初始值,然后执行release操作,让逻辑在这个初始值的基础上根据端口输入的10ms同步信号进行累加操作,可以节省很多的仿真时间,在Netlist中计数器的每个Bit都是真实的触发器了,只能对相应的触发器输出端进行Force,这里采用的是Tcl脚本的方式,具体脚本如下(.Q为触发器的输出端):
图 1 Tcl脚本的force操作代码
按照最初的想法,Force这个4bit的寄存器值为8,release之后,逻辑应该在10ms同步信号到来后,将计数器的值加到9,但使用IUS仿真出来的波形却与原本想法不一样,具体波形如下:
图 2 Force操作的仿真波形
从波形上看,force操作成功了,但release之后,所有被Force的信号都恢复成force之前的值,而且经过确认,release的时刻,触发器的输入端没有任何变化(包括没有时钟信号的跳变),环境代码也没有对这些信号进行任何的操作。
发现该问题后,在Netlist中找到了force的相应触发器,发现这是一个由边沿触发时序电路UDP构成的,且寄存器的输出端Q的值,就是dff_s这个UDP电路的输出,如下:(红色框图中的为边沿触发时序电路UDP),
按照在前仿中使用force/release操作的理解,release之后如果没有其他的操作,被force信号应该保持原来的值不变,但是在Netlist仿真中,出现的force/release操作的现象与前仿中的现象完全不一样,我从IUS的用户手册中找到的采用Tcl脚本的方式对force/release的解释:
按照上面的release的解释:release操作将释放force引起的数值变化,并在force操作没有阻塞的时候,将被force的数值修改成原有的值。想要去掉force操作但又需要保持被force的值,可以使用-keepvalue操作。
按照上面一节中得到的IUS对于force/release 的解释,做一个实验,将上面提到的那个寄存器,单独做一个例化,然后按照在Netlist仿真中情况,给定输入信号的取值:
仿真过程:先run 124ns,然后
force reg_1.Q 1’b1;
run 10ns ;
release reg_1.Q
run 100ns
得到的仿真波形如下:
从波形中可以看出,寄存器的输出端Q先被force成1’b1,在release之后,就恢复成被force之前的数值,与IUS 手册中TCl部分对release的解释。
下面使用一下release –keepvalue操作,首先说一下我的对release –keepvalue的理解:应该是去掉了force操作,但信号还是保持在被force的数值,直到有新的逻辑操作改变信号的值,按照这个理解,仍然使用上面的DEMO,做一个实验:
仿真过程:先run 124ns,然后
force reg_1.Q 1’b1;
run 10ns ;
release –keepvalue reg_1.Q
run 100ns
得到的仿真波形如下:
从上面的波形中可以看出,采用release –keepvalue操作出现的现象与我的理解一致。
通过上面的实验,可以解释了在SD6601v100中Netlist仿真中遇到的Force问题,是因为IUS对门级仿真中force/release操作的执行。
在这里因为需要分析这个force的问题,也顺便看了一下Verilog对于边沿触发时序电路UDP的描述,其中有一段解释:“模拟器只有在检测到输入信号发生跳变时才搜索table表得到新的内部状态和输出逻辑值”,所以在门级仿真中需要深入了解,尤其是对由UDP构成的寄存器进行force/release的操作,如果出现了类似我遇到的release后数值恢复的现象,一定要弄清楚是因为UDP自身的行为还是因为仿真器对force/release的处理问题。
另外一个问题关于trigger的问题,
VMM中描述的断言trigger的value来至preponed区域的数据。
force 的原理是通过覆盖将原始驱动的值进行修改
SystemVerilog变量可以是其它数据类型的压缩或非压缩集合。对变量中独立元素的多个赋值被单独地检查。左侧包含了一个分片的赋值被看作是对整个分片的单一赋值。使用过程赋值与连续赋值的混合形式写入一个压缩结构体或压缩数组类型是错误的。因此,一个非压缩结构体或非压缩数组中的一个元素可以过程化赋值,而另一个元素可以进行连续赋值。并且,一个压缩结构体或压缩数组的每一个元素都可以使用单一的连续赋值。
非法赋值:
// 对abc.C的多个连续赋值
assign abc.C = sel ? 8'hhDE : 8'hED; // ???
// 对abc.A的连续和过程赋值的混合
always @(posedge clk)
abc.A[7:4] <= !abc.B[7:4];