亿迅智能制造网
工业4.0先进制造技术信息网站!
首页 | 制造技术 | 制造设备 | 工业物联网 | 工业材料 | 设备保养维修 | 工业编程 |
home  MfgRobots >> 亿迅智能制造网 >  >> Industrial programming >> Verilog

理解 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 下降沿触发。

时钟上升沿发生什么?

每个时钟上升沿发生以下事件,对所有上升沿重复:

  1. 第一个 if 检查低电平有效复位 rstn 值
    1. 若 rstn 为 0,输出 q 复位为默认值 0
    2. 若 rstn 为 1,复位未施加,遵循默认行为
  2. 若前一步为假:
    1. 检查 d 值,若为 1 则翻转 q 值
    2. 若 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 下降沿发生以下事件,每次发生均重复:

  1. 第一个 if 检查 rstn 值。下降沿时其值为 0。
    1. 若 rstn 为 0,表示复位施加,输出复位为默认值 0
    2. 不考虑 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

  1. Verilog 入门:数字电路设计完整教程
  2. 掌握 Verilog 拼接操作:实用指南
  3. Verilog 核心要点速览
  4. 深入理解 Verilog 赋值语句:类型、语法与最佳实践
  5. Verilog阻塞与非阻塞赋值:关键区别详解
  6. 掌握Verilog函数:高效RTL设计的复用利器
  7. 理解Verilog任务:函数vs任务、语法与用法全解析
  8. Verilog 时钟发生器设计与实现指南
  9. 掌握 Verilog 数学函数:高效硬件设计的利器
  10. 掌握 Verilog $timeformat:精度控制与显示格式化
  11. 理解与打印 Verilog 任意作用域下的 Timescale
  12. 掌握 Verilog 文件 I/O:打开、读取、写入和关闭