📅  最后修改于: 2021-01-11 14:43:53             🧑  作者: Mango
在Verilog中,always块是过程块之一。 always块中的语句按顺序执行。
Always块始终执行,与初始块不同,初始块在模拟开始时仅执行一次。 Always块应具有敏感列表或与之相关的延迟
敏感列表是告诉always块何时执行代码块的列表。
句法
Verilog始终阻止以下语法
always @ (event)
[statement]
always @ (event) begin
[multiple statements]
end
例子
保留字always之后的符号@,表示将在符号@后面括号中的条件下触发该块。
always @ (x or y or sel)
begin
m = 0;
if (sel == 0) begin
m = x;
end else begin
m = y;
end
end
在上面的示例中,我们描述了一个2:1多路复用器,输入x和y。 sel是选择输入, m是复用输出。
在任何组合逻辑中,只要输入发生变化,输出就会发生变化。如果将此理论应用于始终块,则只要输入或输出变量发生变化,始终块中的代码就需要执行。
注意:它可以驱动reg和integer数据类型,但不能驱动线数据类型。
Verilog中有两种类型的敏感列表,例如:
下面的代码是相同的2:1多路复用器,但是输出m现在是触发器输出。
always @ (posedge clk )
if (reset == 0) begin
m <= 0;
end
else if (sel == 0) begin
m <= x;
end
else begin
m <= y;
end
注意:Always块在某些特定事件上执行。敏感度列表定义事件。
敏感性列表是一个表达式,它定义了何时执行always块,并在括号()中的@运算符之后指定。该列表可以包含一个或一组信号,其值更改将执行always块。
在下面显示的代码中,每当信号x或y的值更改时,始终执行块中的所有语句。
// execute always block whenever value of "x" or "y" change
always @ (x or y) begin
[statements]
end
需要敏感性清单
在整个模拟过程中,始终块将连续重复。灵敏度列表带来某种定时感,即,只要灵敏度列表中的任何信号发生变化,便会触发始终块。
如果始终块中没有时序控制语句,则由于零延迟无限循环,模拟将挂起。
例如,始终阻止尝试反转信号clk的值。该语句每隔0次执行一次。因此,由于语句中没有延迟,因此它将永远执行。
// always block started at time 0 units
// But when is it supposed to be repeated
// There is no time control, and hence it will stay and
// be repeated at 0-time units only and it continues
// in a loop and simulation will hang
always clk = ~clk;
如果灵敏度列表为空,则应该有其他形式的时间延迟。通过始终构造中的延迟语句可以提高仿真时间。
always #10 clk = ~clk;
现在,每10次单位完成一次时钟反转。这就是为什么真正的Verilog设计代码始终需要敏感度列表的原因。
注意:显式延迟不能合成为逻辑门。
Always模块可用于实现组合或顺序元素。诸如触发器之类的顺序元素在提供时钟并复位后会变为活动状态。
类似地,当一个组合块的输入值之一改变时,该组合块将变为活动状态。这些硬件模块都彼此独立地并发工作。两者之间的联系决定了数据流。
常态块是一个连续过程,当敏感度列表中的信号变为活动状态时,将触发该块并执行某些操作。
在以下示例中,始终块中的所有语句在信号clk的每个上升沿执行
// execute always block at the positive edge of signal "clk"
always @ (posedge clk) begin
[statements]
end
以下代码定义了一个名为tff的模块,该模块接受数据输入,时钟和低电平有效复位。在这里,Always块在clk的上升沿或rstn的下降沿触发。
1.时钟的上升沿
以下事件在时钟的上升沿发生,并在时钟的所有上升沿重复发生。
步骤1:首先,if语句检查低电平有效复位rstn的值。
步骤2:如果上一步为假,则
module tff (input d, clk, rstn, output reg q);
always @ (posedge clk or negedge rstn) begin
if (!rstn)
q <= 0;
else
if (d)
q <= ~q;
else
q <= q;
end
endmodule
2.复位的负沿
以下事件发生在rstn的负边缘。
步骤1:首先,if语句检查低电平有效复位rstn的值。在信号的下降沿,其值为0。
Always块也可以用于组合块的设计中。
例如,下面的数字电路代表三个不同的逻辑门,它们在信号o处提供特定的输出。
下面显示的代码是具有四个输入端口和一个称为o的单个输出端口的模块。每当敏感度列表中的任何信号的值发生变化时,便会始终触发块。
因为在程序块中使用了输出信号,所以在模块端口列表中将其声明为reg类型。程序块中使用的所有信号都应声明为reg类型。
module combo (input a, input b, input c, input d, output reg o);
always @ (a or b or c or d) begin
o <= ~((a & b) | (c^d));
end
endmodule
每当RHS上的组合表达式为真时,信号o就变为1。同样,当RHS为假时,o变为0。