FPGA基础 -- Verilog行为级建模之alawys语句

发布于:2025-06-20 ⋅ 阅读:(14) ⋅ 点赞:(0)

Verilog 中的 always 语句块,这是行为级建模的核心结构之一,在 RTL 级设计中广泛用于时序逻辑组合逻辑的建模。


一、什么是 always 语句?

✅ 定义:

always 语句用于描述可综合的硬件行为逻辑,表示一个**“事件驱动”的过程块**,当敏感列表中某个信号发生变化时,always 块会立即触发执行。


二、基本语法格式

always @(sensitivity_list)
    begin
        // 过程性代码
    end

sensitivity_list 是触发该块执行的信号列表。


三、分类:三种常见 always 使用方式

类型 敏感列表 用途 典型应用
时序逻辑 posedge clk / negedge rst_n 同步逻辑 寄存器建模、状态机
组合逻辑 (*) 或所有组合信号列出 无时序行为 算术逻辑单元(ALU)
异步逻辑 posedge clk or negedge rst 异步复位结构 上电初始化控制

四、时序逻辑建模(推荐使用方式)

4.1 同步复位寄存器建模:

always @(posedge clk) begin
    if (!rst_n)
        q <= 0;
    else
        q <= d;
end

✅ 非阻塞赋值 <=,确保“并行硬件”的表达。

4.2 异步复位建模:

always @(posedge clk or negedge rst_n) begin
    if (!rst_n)
        q <= 0;
    else
        q <= d;
end

posedge clk or negedge rst_n:表示 rst_n 变化时立即响应。


五、组合逻辑建模

推荐使用 always @(*)

always @(*) begin
    case (sel)
        2'b00: y = a;
        2'b01: y = b;
        default: y = 0;
    endcase
end

✅ 使用 = 阻塞赋值。
✅ 确保对每个输出都完全赋值,否则综合工具会推断出 latch(锁存器)!


六、敏感列表详解

✅ 常见写法对比:

写法 解释 建议
always @(a or b or c) 显式列出每个信号 ✅ 可控但冗长
always @(*) 隐式敏感列表,表示所有用到的组合信号 ✅ 推荐用于组合逻辑
always @(posedge clk) 上升沿触发(时序逻辑) ✅ 推荐用于寄存器

七、阻塞/非阻塞赋值回顾(重点)

场景 使用赋值类型 示例
时序逻辑(同步时钟) 非阻塞 <= q <= d;
组合逻辑 阻塞 = y = a + b;

⚠️ 错误示例:混用赋值类型

always @(posedge clk) begin
    a = b;   // ❌ 错误:阻塞赋值在时序逻辑中易引发竞态
    c <= a;  // 实际 c 得到的是旧值,不是当前周期的 b
end

八、综合注意事项(总结)

误用 影响 修正建议
@(*) 中漏掉信号 可能漏更新,综合错误 使用 @(*) 自动推导
混用 =<= 引起竞态与不符合意图 遵循赋值语义规则
不完全赋值 可能推断 latch 加默认路径 / default 分支
变量多处被赋值 冲突或竞态 避免变量在多个 always 中赋值

九、典型设计范式:分离时序与组合逻辑

// 状态寄存器
always @(posedge clk or negedge rst_n)
    if (!rst_n) state <= IDLE;
    else        state <= next_state;

// 下一状态逻辑
always @(*) begin
    case (state)
        IDLE:      if (start) next_state = RUN;
        RUN:       if (done)  next_state = IDLE;
        default:             next_state = IDLE;
    endcase
end

✅ 这是 FSM 设计的推荐结构:组合逻辑决定 next_state,时序逻辑更新 state。


十、仿真辅助结构(testbench 中的 always

always #5 clk = ~clk;  // 每 5ns 翻转一次
  • 通常用于生成仿真用时钟;
  • 非综合代码,仅用于 initial 或 testbench。

十一、拓展:SystemVerilog 中的 always_ff / always_comb

类型 SystemVerilog 替代 特点
时序逻辑 always_ff 自动检查敏感列表,防止误用
组合逻辑 always_comb 自动推导敏感列表

✅ 更强语义检查,更安全可维护,但需要 SystemVerilog 工具支持。


十二、实战示例总结:组合 + 寄存器 + 状态机

// 组合逻辑:计数器是否达到最大值
always @(*) begin
    done = (cnt == 15);
end

// 时序逻辑:计数器累加
always @(posedge clk or negedge rst_n) begin
    if (!rst_n)
        cnt <= 0;
    else if (en)
        cnt <= cnt + 1;
end

小结

内容 核心要点
语义 always 块是硬件中的过程行为
时序建模 使用 posedge clk + 非阻塞赋值
组合建模 使用 @(*) + 阻塞赋值,完整赋值
综合约束 不可在综合逻辑中使用 #延迟
推荐实践 将时序逻辑与组合逻辑分离建模,提高可读性与综合效果

网站公告

今日签到

点亮在社区的每一天
去签到