Verilog中assign和always的关键词详解

First Post:
Last Update:

assign 用于描述组合逻辑

标准定义:

组合逻辑电路在逻辑功能上的特点是任意时刻的输出仅仅取决于该时刻的输入,与电路原来的状态无关.而时序逻辑电路在逻辑功能上的特点是任意时刻的输出不仅取决于当时的输入信号,而且还取决于电路原来的状态,或者说,还与以前的输入有关.

与门、或门、非门、与非门、或非门等逻辑门电路.

大致为编码器,译码器,数据选择器,加法器这些不带寄存器的部件.这一部分内容不进行加粗高亮,防止知识架构的混乱.

always@(敏感事件列表) 用于描述时序逻辑

标准定义:

由多个触发器和多个组合逻辑块组成的网络.常用的有:计数器、复杂的数据流动控制逻辑、运算控制逻辑、指令分析和操作控制逻辑.同步时序逻辑是设计复杂的数字逻辑系统的核心.时序逻辑借助于状态寄存器记住它目前所处的状态.在不同的状态下,即使所有的输入都相同,其输出也不一定相同.

常见的时序逻辑电路有触发器,计数器,寄存器.

引用一篇文章的实验帮助进行理解:

Verilog编程,请把时序逻辑和组合逻辑彻底分开!

以一个同步加法器为例,使用Verilog实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
>module adder(
input clk_sys,
input rst_n,

input a,
input b,

output reg c
);
always @(posedge clk_sys or negedge rst_n) begin
if(!rst_n)
c <= 0;
else
c <= a+b;
end
endmodule

对应的RTL电路是(使用Quartus编译环境):

仔细看上图,发现该电路和Verilog描述的有点区别,Verilog把加法放在时序逻辑里实现,而实际电路却是两个分开的.
我们再用Verilog把上面的电路描述一遍:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
>module adder(
input clk_sys,
input rst_n,

input a,
input b,

output reg c
);

wire c_w;

assign c_w = a + b;

always @(posedge clk_sys or negedge rst_n) begin
if(!rst_n)
c <= 0;
else
c <= c_w;
end
endmodule

然后再编译综合一次,看一下RTL电路:

和描述的完全一致.

得到的结论是:FPGA内部单元电路只有D触发器是时序电路,其余的都是组合电路(如加法器),不存在“同步时序加法器”的单元电路.

所以记住一点,任何需要运算的地方都放在组合电路里实现,任何需要clk同步时序的地方都只包含一个D触发器的延迟操作.

个人理解:

组合逻辑和时序逻辑最主要的区别就是是否有寄存器,时序逻辑需要一个寄存器来进行状态的记录.无需记录状态的逻辑组件也会被编译器直接优化掉的.

D触发器

D触发器是一个具有记忆功能的,具有两个稳定状态的信息存储器件,是构成多种时序电路的最基本逻辑单元,也是数字逻辑电路中一种重要的单元电路。

因此,D触发器在数字系统和计算机中有着广泛的应用。触发器具有两个稳定状态,即”0”和”1”,在一定的外界信号作用下,可以从一个稳定状态翻转到另一个稳定状态。

D触发器有集成触发器和门电路组成的触发器。触发方式有电平触发和边沿触发两种,前者在CP(时钟脉冲)=1时即可触发,后者多在CP的前沿(正跳变0→1)触发。

D触发器的次态取决于触发前D端的状态,即次态=D。因此,它具有置0、置1两种功能。

对于边沿D触发器,由于在CP=1期间电路具有维持阻塞作用,所以在CP=1期间,D端的数据状态变化,不会影响触发器的输出状态。

D触发器应用很广,可用做数字信号的寄存,移位寄存,分频和波形发生器等等。