Verilog初级教程(13)Verilog中的块语句

前言

所谓的块语句,无非就是一组语句,例如在initial或者always中,使用begin…end或者fork…join包裹的语句,都可以称为块语句。块语句有两种:

  • 串行语句
  • 并行语句
    下面分别介绍。

正文

串行语句

语句使用begin和end关键字进行包装,并将按照给定的顺序,一个接一个地依次执行。
延迟值相对于前一条语句的执行时间进行处理。在块内的所有语句执行完毕后,控制权可以传递到其他地方。

例如:

module design0;
	reg [31:0] data;

	// "initial" block starts at time 0
	initial begin

		// After 10 time units, data becomes 0xfe
		#10   data = 8'hfe;
		$display ("[Time=%0t] data=0x%0h", $time, data);

		// After 20 time units, data becomes 0x11
		#20   data = 8'h11;
		$display ("[Time=%0t] data=0x%0h", $time, data);
	end
endmodule

如上例,第一条语句从begin处开始,经过10个单位的延迟,执行第一条语句;
在经过20个时间单位的延迟,执行第二条语句。这就是串行执行的语句。

上述仿真log文件为:

[Time=10] data=0xfe
[Time=30] data=0x11

并行语句

并行块可以并发执行语句,延迟控制可以用来提供赋值的时间顺序。通过将语句包装在fork和join关键字中来并行启动。
例如:

initial begin
	#10   data = 8'hfe;
	fork
	   #20 data = 8'h11;
	   #10 data = 8'h00;
	join
end

其执行示意图如下:

并行语句执行示意图

位于fork…join中的语句是并行语句块,里面的每一条语句(使用分号或者begin…end分割)都并行执行,例如上例中的fork…join内部的语句,即使:

#20 data = 8'h11;

位于前面,但是它是要在语句:

#10 data = 8'h00;

后面执行。

上图也很明显地说明了,fork开始,10个时间单位时,执行:

#10 data = 8'h00;

在过10个时间单位执行:

#20 data = 8'h11;

这就是并行执行。

并行块内包含串行块的情况

上面举了这个例子:

initial begin
	#10   data = 8'hfe;
	fork
	   #20 data = 8'h11;
	   #10 data = 8'h00;
	join
end

在上面的例子中,fork-join块将在以10个时间单位执行语句后启动。在这个块中的语句将被并行执行,第一个被启动的语句将是数据被赋值为8’h00的语句,因为延迟是在fork-join启动后的10个时间单位。再过10个时间单位后,第一条语句将被启动,数据将得到8’h11的值。

我们上面也说了,并行块内的每一条语句都并行执行,我们对这里的每一条语句进行说明,使用begin…end包裹的语句块也属于一条语句,即块语句。
而begin…end中的语句是串行执行的,因此就存在并行中包含串行的情况,如下例:

initial begin
	#10 data = 8'hfe;
	fork
		#10 data = 8'h11;
		begin
			#20 data = 8'h00;
			#30 data = 8'haa;
		end
	join
end

很好理解,如下图:

并行包含串行的情况

语句:

#10 data = 8'h11;

与:

begin
			#20 data = 8'h00;
			#30 data = 8'haa;
		end

是并行的关系。

fork开始后的10个时间单位执行语句:

#10 data = 8'h11;

begin
			#20 data = 8'h00;
			#30 data = 8'haa;
		end

因为块本身(块内的第一条语句)与其他语句一同并行启动;
之后块内部的语句串行执行:
也就是说fork后的20个时间单位执行:

//begin
			#20 data = 8'h00;
	//		#30 data = 8'haa;
		//end

不言而喻,在过30个时间单位,也就是fork后的50时间单位执行:

//begin
		//	#20 data = 8'h00;
			#30 data = 8'haa;
	//	end

注:这里强调的都是fork后的时间点,而不是initial begin后的,如果强调initial后的,需要算上第一条语句的10个时间单位。

块名称

顺串行块和并行块都可以通过在关键字begin和fork后面添加:name_of_block来命名。这样,就可以在disable语句中引用该块。

例如:

begin : name_seq
	[statements]
end

fork : name_fork
	[statements]
join

往期文章回顾

Verilog初级教程(12)Verilog中的generate块

Verilog初级教程(11)Verilog中的initial块

Verilog初级教程(10)Verilog的always块

Verilog初级教程(9)Verilog的运算符

Verilog初级教程(8)Verilog中的assign语句

Verilog初级教程(7)Verilog模块例化以及悬空端口的处理

Verilog初级教程(6)Verilog模块与端口

Verilog初级教程(5)Verilog中的多维数组和存储器

Verilog初级教程(4)Verilog中的标量与向量

Verilog初级教程(3)Verilog 数据类型

Verilog初级教程(2)Verilog HDL的初级语法

Verilog初级教程(1)认识 Verilog HDL

芯片设计抽象层及其设计风格

Verilog以及VHDL所倡导的的代码准则

FPGA/ASIC初学者应该学习Verilog还是VHDL?

  • 个人微信公众号: FPGA LAB

交个朋友

猜你喜欢

转载自blog.csdn.net/Reborn_Lee/article/details/107427568