Verilog系列:TIPS(位选,延迟,索引中的运算符)
本文总结了一些在网上看到了解到的一些问题和技巧,汇总了下分享给大家,希望对有需要的人有用。
1 如果要实现参数化且有具体单位的延时,可使用如下办法:
其中Time unit可以根据具体需要指定为期望的单位(fs、ns、us、ms、s)等,Delay number指定具体需要延迟的时间数字。
2 使用assign传输信号,同时指定了惯性延迟,但是延迟时间大于信号变化的速度,那么如果直接赋值,将会导致输入信号不能传输到输出端,即被过滤掉。那么可以如何实现信号的传递呢?
A DIY一个buf,在其中指定延迟后,仿真指定输入通过的滤除百分比,从而使输入信号可以传递到输出端,可参考之前文章《Verilog系列:【16】惯性延迟和传输延迟》的2.3节。
B 将延迟分成若干小段,然后形成若干个连续的assign赋值语句,如下原来信号宽度小于n的信号sig0,sig0不能传递到sig1,通过将连续赋值语句拆分成若干个小的连续赋值语句组,其中每个小的连续赋值语句的延迟小于sig0信号的最小宽度,那么通过层层延迟传递就可以实现sig0到sig1的传递。因为这种方式可能需要重复写很多相同结构的语句,可以使用generate结构,可参见之前文章《Verilog系列:【2】generate常用用法》。
3 vector的大端和小端位选方式
如果base_expr和width_expr经过位选后超过d本身的位宽,那么读取超出部分将获得不定态表示.
其中base_expr是可以在仿真运行过程中按照需要变化的,但是width_expr是必须是确定的。
【示例】
`timescale 1 ns / 1 ps module top_tb; logic [31:0] d1; logic [0:31] d2; logic [63:0] dw; int sel; initial begin d1 = 32'h12345678; d2 = 32'hFEDCBA98; $display("d1[19:12] is 0x%h",d1[12+:8]); $display("d1[11: 4] is 0x%h",d1[11-:8]); $display("d1[12:19] is 0x%h",d2[12+:8]); $display("d1[ 4:11] is 0x%h",d2[12-:8]); for (sel = 0;sel < 8;sel = sel+ 1) dw[8*sel+:8] = d1[7:0]; $display("dw is 0x%h",dw); end endmodule【仿真结果】
# d1[19:12] is 0x45 # d1[11: 4] is 0x67 # d1[12:19] is 0xcb # d1[ 4:11] is 0xdb # dw is 0x7878787878787878
5电路的功能仿真就是假设电路中某一特定时刻发生的所有事件的延迟时间为零,然而事实并非如此,因为仿真软件是通过不同的高级语言编写的软件,即使在并行语句的仿真执行上也是有先后顺序的,在理想的零延迟条件下,当输入信号发生变化时,并行语句执行的先后次序是无法确定的,而不同的执行次序将会得到不一样的仿真结果,最后将导致错误的仿真结果.这里仿真出现问题的主要原因在于理想的零延迟在软件实现中是不可能存在的.为此实际的仿真工具在仿真时会按照一定的算法(不同的EDA工具处理方式可能不一样)对某一时刻发生的事件按照一定的顺序执行,从而实现并行事件的发生得以正确执行,而这个仿真软件对于所有事件发生的最小分辨时间常被成为delta延迟.这个delta延迟大于零,但是小于任何指定的延时,而指定的延迟在VHDL有两种:固有延迟(惯性延迟)和传输延迟(可参考《Verilog系列:【16】惯性延迟和传输延迟》),这两种延迟与Verilog中描述的一致,在此不再赘述,VHDL中对于两种延迟的实现方式如下图所示: