Verilog 语句块提供了将两条或更多条语句组成语法结构上相当于一条一句的机制。主要包括两种类型:顺序块和并行块。
顺序块用关键字 begin
和 end
来表示。
顺序块中的语句是一条条执行的。当然,非阻塞赋值除外。
顺序块中每条语句的时延总是与其前面语句执行的时间相关。
在本节之前的仿真中,initial
块中的阻塞赋值,都是顺序块的实例。
并行块有关键字 fork
和 join
来表示。
并行块中的语句是并行执行的,即便是阻塞形式的赋值。
并行块中每条语句的时延都是与块语句开始执行的时间相关。
顺序块与并行块的区别显而易见,下面用仿真说明。
仿真代码如下:
`timescale 1ns/1ns
module test ;
reg [3:0] ai_sequen, bi_sequen ;
reg [3:0] ai_paral, bi_paral ;
reg [3:0] ai_nonblk, bi_nonblk ;
//============================================================//
//(1)Sequence block
initial begin
#5 ai_sequen = 4'd5 ; //at 5ns
#5 bi_sequen = 4'd8 ; //at 10ns
end
//(2)fork block
initial fork
#5 ai_paral = 4'd5 ; //at 5ns
#5 bi_paral = 4'd8 ; //at 5ns
join
//(3)non-block block
initial fork
#5 ai_nonblk <= 4'd5 ; //at 5ns
#5 bi_nonblk <= 4'd8 ; //at 5ns
join
endmodule
仿真结果如下:
如图所示,顺序块顺序执行,第 10ns 时,信号 bi_sequen
才赋值为 8。
而并行块,ai_paral
与 bi_paral
的赋值是同时执行的,所以均在 5ns 时被赋值。
而非阻塞赋值,也能达到和并行块同等的赋值效果。
顺序块和并行块还可以嵌套使用。
仿真代码如下:
`timescale 1ns/1ns
module test ;
reg [3:0] ai_sequen2, bi_sequen2 ;
reg [3:0] ai_paral2, bi_paral2 ;
initial begin
ai_sequen2 = 4'd5 ; //at 0ns
fork
#10 ai_paral2 = 4'd5 ; //at 10ns
#15 bi_paral2 = 4'd8 ; //at 15ns
join
#20 bi_sequen2 = 4'd8 ; //at 35ns
end
endmodule
仿真结果如下:
并行块语句块内是并行执行,所以信号 ai_paral2
和信号 bi_paral2
分别在 10ns, 15ns 时被赋值。而并行块中最长的执行时间为 15ns,所以顺序块中的信号 bi_sequen2
在 35ns 时被赋值。
我们可以给块语句结构命名。
命名的块中可以声明局部变量,通过层次名引用的方法对变量进行访问。
仿真代码如下:
`timescale 1ns/1ns
module test;
initial begin: w3cschool //命名模块名字为w3cschool,分号不能少
integer i ; //此变量可以通过test.w3cschool.i 被其他模块使用
i = 0 ;
forever begin
#10 i = i + 10 ;
end
end
reg stop_flag ;
initial stop_flag = 1'b0 ;
always begin : detect_stop
if ( test.w3cschool.i == 100) begin //i累加10次,即100ns时停止仿真
$display("Now you can stop the simulation!!!");
stop_flag = 1'b1 ;
end
#10 ;
end
endmodule
仿真结果如下:
命名的块也可以被禁用,用关键字 disable
来表示。
disable
可以终止命名块的执行,可以用来从循环中退出、处理错误等。
与 C 语言中 break
类似,但是 break
只能退出当前所在循环,而 disable
可以禁用设计中任何一个命名的块。
仿真代码如下:
`timescale 1ns/1ns
module test;
initial begin: w3cschool_d //命名模块名字为w3cschool_d
integer i_d ;
i_d = 0 ;
while(i_d<=100) begin: w3cschool_d2
# 10 ;
if (i_d >= 50) begin //累加5次停止累加
disable w3cschool_d3.clk_gen ;//stop 外部block: clk_gen
disable w3cschool_d2 ; //stop 当前block: w3cschool_d2
end
i_d = i_d + 10 ;
end
end
reg clk ;
initial begin: w3cschool_d3
while (1) begin: clk_gen //时钟产生模块
clk=1 ; #10 ;
clk=0 ; #10 ;
end
end
endmodule
仿真结果如下:
由图可知,信号 i_d
累加到 50 以后,便不再累加,以后 clk
时钟也不再产生。
可见,disable
退出了当前的 while
块。
需要说明的是,disable
在 always
或 forever
块中使用时只能退出当前回合,下一次语句还是会在 always
或 forever
中执行。因为 always
块和 forever
块是一直执行的,此时的 disable
有点类似 C 语言中的 continue
功能。
点击这里下载源码