Verilog 初学笔记--顺序操作 和 并行操作的一点思考(参考黑金教程:Verilog HDL那些事 建模篇)
Verilog 是一门建模语言,而不是一门编程语言。同众多的编程语言相比,他最大的特点是并行性。即Verilog 不但能描述串行操作,也能描述并行操作。如果理解了Verilog 的并行设计原则,则设计的系统不但层次分明,且易于理解和维护。
如对于编程入门的流水灯,假设满足以下功能:三个LED灯,在三个时钟周期内分别输出高电平,如下图波形:在三个时钟周期内LED0,LED1,LED2轮流输出高电平。
如果用C语言编程,可能会这样:
While(1) {
LED=001;delay(1);
LED=010;delay(1);
LED=100;delay(1);
}
可以看出,思考的过程是:
1:亮第一个灯,延时;
2:亮第二个灯,延时;
3:亮第三个灯,延时;
4:执行第一步
可以看出是典型的顺序操作,1执行完才能执行2,依次类推。
如果用并行的思想设计:
进程1:第一个时钟周期LED0亮,后两个时钟周期LED0灭
进程2:第二个时钟周期LED1亮,第一个时钟周期和第三个时钟周期LED1灭
进程3:第三个时钟周期LED2亮,第一个时钟周期和第二个时钟周期LED2灭
其中进程1,2,3并行执行,互不影响。
在Verilog 语言中,既可以用并行的思想设计,也可以用串行的思想设计。
串行设计
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 module flash(
2 clk,rst_n,out
3 );
4 input clk,rst_n;
5 output [2:0] out;
6
7 //the block of count
8 reg [1:0] cnt;
9 always @(posedge clk,negedge rst_n)
10 if(!rst_n)
11 cnt<=2'b0;
12 else if(cnt==2'b10)
13 cnt<=2'b0;
14 else
15 cnt<=cnt+1'b1;
16
17 //the block of output
18 reg [2:0] rOut;
19 always @(posedge clk,negedge rst_n)
20 if(!rst_n)
21 rOut<=3'b000;
22 else if(cnt<2'b1)
23 rOut<=3'b001;
24 else if(cnt>=2'b1 && cnt<2'b10)
25 rOut<=3'b010;
26 else
27 rOut<=3'b100;
28
29 assign out=rOut;
30 endmodule
其中以下代码体现了串行的设计思想,在第一个延时内亮第一个灯,然后在第二个延时内亮第二个灯,最后在第三个延时内亮第三个灯。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 else if(cnt<2'b1)
2
3 rOut<=3'b001;
4
5 else if(cnt>=2'b1 && cnt<2'b10)
6
7 rOut<=3'b010;
8
9 else
10
11 rOut<=3'b100;
生成的RTL视图:
虽然生成的RTL视图看出三个比较器类似并行,但是还是一种串行的设计思想。应为这三个亮灯的过程是有顺序关系的,并不是并行互不影响的。从LessThan0可以看出第一个延时的判断结果影响是第二个延时判断结果的输入选择信号:只有第一个延时完成后,才开始第二个延时。这是典型的顺序操作的思想。
并行设计:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 module flash(
2 clk,rst_n,out
3 );
4 input clk,rst_n;
5 output [2:0] out;
6
7 //the block of count
8 reg [1:0] cnt;
9 always @(posedge clk,negedge rst_n)
10 if(!rst_n)
11 cnt<=2'd0;
12 else if(cnt==2'd2)
13 cnt<=2'd0;
14 else
15 cnt<=cnt+1'd1;
16 //the block of output led0;
17 reg rOut0;
18 always @(posedge clk,negedge rst_n)
19 if(!rst_n)
20 rOut0<=1'b0;
21 else if(cnt<2'b1)
22 rOut0<=1'b1;
23 else
24 rOut0<=1'b0;
25 //the block of output led1;
26 reg rOut1;
27 always @(posedge clk,negedge rst_n)
28 if(!rst_n)
29 rOut1<=1'b0;
30 else if(cnt>=2'b1 && cnt<2'b10)
31 rOut1<=1'b1;
32 else
33 rOut1<=1'b0;
34 //the block of output led2;
35 reg rOut2;
36 always @(posedge clk,negedge rst_n)
37 if(!rst_n)
38 rOut2<=1'b0;
39 else if(cnt==2'b10)
40 rOut2<=1'b1;
41 else
42 rOut2<=1'b0;
43 assign out={rOut2,rOut1,rOut0};
44 endmodule
上述代码中的输出led0,led1,led2的三段always 代码体现了设计的并行思想。在Verilog语言中,always块是并行操作的,互不影响。
生成的RTL视图:
上述RTL视图可以看出,各个always 块的延时判断语句互不影响,直接连到输出,体现了并行设计的思想。同串行设计相比,判断输出端的组合逻辑简单,RTL视图清晰,易于理解,且RTL代码易于维护。
通过对比可以发现,并行设计在并不大量消耗资源且满足功能的前提下,能够更好的描述系统。
这里要特别注意的一点是:在Verilog 语言中强调代码的简洁性是没有意义的,如何能够更加形象的对系统的建模才是设计者需要关心的。