欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2022-07-14 22:40:07
...

前言

所谓的块语句,无非就是一组语句,例如在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

其执行示意图如下:

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

位于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

很好理解,如下图:

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

语句:

#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

交个朋友