理解 Verilog always 块:语法与敏感列表
always 块是 Verilog 中的 过程 块之一。always 块内语句按顺序执行。
语法
always @ (event) [statement]
always @ (event) begin [multiple statements] end
always 块在特定事件执行。事件由敏感列表定义。
什么是敏感列表?
敏感 列表定义 always 块何时执行,指定在 @ 运算符后的括号 ( ) 内。列表可包含一个或一组信号,其值变化将触发 always 块执行。
下面代码中,always 块内所有语句在信号 a 或 b 值变化时执行。
// 当 "a" 或 "b" 值变化时执行 always 块
always @ (a or b) begin
[statements]
end
always 块用途
always 块可用于实现组合或时序元件。时序元件如触发器在提供时钟和复位时激活。组合块在输入值变化时激活。这些硬件块并发独立工作,连接关系决定数据流。为建模此行为,always 块作为持续过程,当敏感列表内信号激活时触发并执行动作。
下例中,always 块在信号 clk 每个上升沿执行。
// 在信号 "clk" 上升沿执行 always 块
always @ (posedge clk) begin
[statements]
end
无敏感列表会怎样?
always 块在整个仿真期间持续重复。敏感列表带来时序感:敏感列表中任一信号变化触发 always 块。若 always 块内无时序控制语句,仿真将因零延迟无限循环而挂起!
示例
下例 always 块尝试翻转 clk 值。语句每 0 时间单位执行一次。因语句无延迟,将永远在 0 时间单位循环执行,仿真挂起!
// always 块在时间 0 启动
// 但何时重复?无时间控制,故停留在 0 时间单位重复,陷入循环,仿真挂起!
always clk = ~clk;
即使敏感列表为空,也应有其他形式时间延迟。仿真时间由 always 结构内延迟语句推进,如下所示。现时钟翻转每 10 时间单位执行一次。
always #10 clk = ~clk;
注意: 显式延迟不可综合为逻辑门!
因此真实 Verilog 设计代码总需要敏感列表。
时序元件设计示例
下面代码定义模块 tff,接受数据输入、时钟和低电平有效复位。输出在时钟上升沿发现 d 为 1 时翻转。always 块在 clk 上升沿或 rstn 下降沿触发。
时钟上升沿发生什么?
每个时钟上升沿发生以下事件,对所有上升沿重复:
- 第一个
if检查低电平有效复位rstn值 - 若
rstn为 0,输出q复位为默认值 0 - 若
rstn为 1,复位未施加,遵循默认行为 - 若前一步为假:
- 检查
d值,若为 1 则翻转q值 - 若
d为 0,保持q值
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
复位下降沿发生什么?
rstn 下降沿发生以下事件,每次发生均重复:
- 第一个
if检查rstn值。下降沿时其值为 0。 - 若
rstn为 0,表示复位施加,输出复位为默认值 0 - 不考虑
rstn为 1 的情况,因当前事件是 rstn 下降沿
组合元件设计示例
always 块也可用于组合块设计。例如下面数字电路表示三个逻辑门组合,在信号 o 提供特定输出。
下面代码是包含四个输入端口和单输出端口 o 的 module。always 块在敏感列表中任一信号值变化时触发。输出信号在模块端口列表中声明为 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
信号 o 在 RHS 组合表达式为真时变 1,为假时变 0。
仿真输出
点击查看带仿真示例的幻灯片!
Verilog
- Verilog 入门:数字电路设计完整教程
- 掌握 Verilog 拼接操作:实用指南
- Verilog 核心要点速览
- 深入理解 Verilog 赋值语句:类型、语法与最佳实践
- Verilog阻塞与非阻塞赋值:关键区别详解
- 掌握Verilog函数:高效RTL设计的复用利器
- 理解Verilog任务:函数vs任务、语法与用法全解析
- Verilog 时钟发生器设计与实现指南
- 掌握 Verilog 数学函数:高效硬件设计的利器
- 掌握 Verilog $timeformat:精度控制与显示格式化
- 理解与打印 Verilog 任意作用域下的 Timescale
- 掌握 Verilog 文件 I/O:打开、读取、写入和关闭