学习摘自数字芯片实验室
forever,repeat,while,for和do-while之间有什么区别?
在Verilog-2001中支持forever, repeat,while和for循环语句,do-while结构是在SystemVerilog中引入的。这些语句根本上的不同在于begin-end语句块中执行了多少次循环。
以下总结了这些差异:
forever:forever语句块中的语句会一直执行,没有任何变量来控制它,直到仿真结束。例如:
initial begin
clk= 1 ;
forever begin : clk_block
#(clk_period/2) clk =~clk ;
end end
forever循环不能通过disable语句终止。
repeat:repeat语句块中执行一个固定循环次数的语句。
例如:
integer var1 , i; initial begin
var1 = 8 ;
i = 0 ;
repeat(var1) begin : this_loop
i = i + 1 ;
$display(“i = %0d”,i) ;
end
$finish ; end
var1必须在括号内。由于变量大小是循环执行的次数,所以在进入循环之前需要确定一个固定的常数。 disable语句可用于退出循环
过早。
while:在begin-end语句块中无限地执行语句,表达式变为false。例如:
integer i ; initial begin
i= 8 ;
while(i)begin : this_loop
i= i -1 ;
$display(“i= %0d”,i) ; end
$finish; end
如果while里面的表达式一直为真的话,上面的代码可能最终成为一个无限循环。disable语句可用于提前退出循环。
for:和while循环类似,基于变量的次数执行begin-end里面的语句。
integer i ; initial begin
for(i = 0 ; i < 8 ; i = i +1 ) begin : loop1
$display(“ i = %0d”, i) ;
//i = i+ 1 ;
end
$finish ; end
上面的代码将i的值显示为0,1,2,3,4,5,6,7。
如果for循环里面的表达式一直为真,for循环也会进入无限循环。disable语句可用于提前退出for循环。
在上面的代码中,如果语句“i = i +1”没有被注释,将显示值为0,2,4,6。
for循环的另一个独特功能是它是唯一被综合工具支持的可综合循环语句结构。
for循环中的语句会被复制固定次数。
因此,for循环语句在被逻辑综合工具读取时,应该具有确定的循环次数,因为这是硬件,不是软件。
do-while:执行begin-end里面的,直到表达式为false。
module test_dowhile;
integeri ;
initialbegin
i= 4’d2 ;
do
begin
i++ ;
end
while(I <= 4’d15) ;
$display(“i =%0d ” , i) ; //display i = 16
$finish ;
end endmodule //test_dowhile
strobe是Verilog中定义的一个功能,通过该功能可以在当前仿真事件结束时获得指定线网或变量的仿真数据。在Verilog中,strobe功能通过调用系统函数$strobe实现。
从语法上讲,这个$strobe和$display非常相似。$strobe系统调用的一个例子如下:
always@(negedge system_clock)
$strobe(“Time= %0d,rx_active = %b rx_data = %h”,$time,rx_active,rx_data[7:0]) ;
在功能上,$strobe系统调用在每个用户指定的事件后监视变量变化。
$strobe的形式包括$strobeh(十六进制格式),$strobeo(八进制格式),$strobeb(二进制格式)。
所有这些系统调用都是在标准输出设备上打印结果。
$fstrobe$ fstrobeb, fstrobeh和$fstrobeo可用于打印strobe输出到特定文件。
这些系统函数有一个额外的参数,即文件句柄。例如:
integerfile_handle ;
initial
begin
file_handle = $fopen(“vectors.stb”);
end
always@(negedgesystem_clock)
begin
$fstrobe(file_handle,”Time= %0d,rx_active = %b rx_data =
%h”,$time,rx_active,rx_data[7:0]) ;
end
除了$strobe之外,Verilog还有另外一个系统函数,叫做$monitor,用于监视仿真期间的信号变化。
与$strobe不同,$monitor只在参数列表中变量或表达式的值发生变化时,才会输出显示。
always@(posedge clock)
$strobe(…arguments…) ;
在上面的示例中,$strobe的参数信号的值在时钟信号的每个上升沿打印到标准输出
initial begin
$monitor(“Time = %0d: rx_active = %b,rx_data =%h”,$time,rx_active,rx_data[7:0]) ;
end
在此示例中,每次rx_active和rx_data信号的变化都会通过$ monitor调用打印到标准输出设备
从这个例子中可以清楚地看到,对于一组给定的参数,$monitor应该只在仿真中调用一次。
如果调用$monitor不止一次,然后最近的$monitor调用会覆盖所有以前的$monitor调用。
initial begin
//monitor for receive activity
$monitor(“Time = %0d: rx_active = %b,rx_data =%h”,$time,rx_active,rx_data[7:0]) ;
//monitor for transmit activity
//REPLACES the previous $monitor
$monitor(“Time = %0d: tx_valid = %b ,tx_data=%h”,$time, tx_valid, tx_data [7:0]) ;
end
最后,与$strobe一样,$monitor系统函数也有其他格式:
$monitorh,$monitoro,$monitorb,$fmonitor,$ fmonitorh,$fmonitoro和$fmonitorb。
$ strobe和$ monitor之间的差异总结如下:
$ strobe可在@(posedge clock),@(negedge 时钟),@(any_signal)等仿真事件中直接调用。
可以同时存在多个具有相同或不同的参数的$ strobe调用。
$monitor需要一组给定的参数敏感列表。在任意时间只能有一个$ monitor有效。
每次调用$ monitor都会替换之前的$ monitor调用。