Veloris.
返回索引
FPGA 2025-10-20

组合逻辑电路和时序逻辑电路

3 分钟
857 words

组合逻辑电路和时序逻辑电路

数字电路根据逻辑功能的不同特点,可以分成两大类:一类叫组合逻辑电路(简称组合电路),另一类叫做时序逻辑电路(简称时序电路)。

1. 组合逻辑电路

  1. 什么是组合逻辑电路

    • 基本概念:组合逻辑电路是指电路当前输出信号只和当前输入信号有关,而与电路之前的状态无关的电路。
    • 电路特点:没有反馈电路,也没有存储电路
    • 电路功能:组合逻辑用来实现一些逻辑运算,比如与、或、非、异或等运算,根据运算的复杂度,其组合逻辑电路的路径延迟不同
    • 电路示例:加法器、减法器、乘法器、除法器、比较器、编码器、解码器、译码器、多路选择器、多路分配器等

典型结构如下图所示:

  1. 组合逻辑电路的Verilog描述

    • always模块的敏感表为电平敏感信号的电路:
    • 用assign语句描述的电路:
  2. 组合逻辑电路的注意事项

    • 注意补全敏感信号列表
    • 避免产生组合逻辑环路
    • 组合逻辑使用阻塞赋值=
  3. 关于组合逻辑环路的核心知识点

  • 组合逻辑环的定义:在纯组合逻辑电路中,信号的传播路径形成了一个闭环回路,即某个信号的输出经过若干级组合逻辑后又反馈到了该信号自身的输入端,形成了自激振荡的路径。

  • 示例:

    // 错误示例1:直接的组合逻辑环路
    module combinational_loop_bad (
        input  wire a,
        input  wire b,
        output wire y
    );
        wire temp;
    
        assign temp = a & y;      // y影响temp
        assign y = temp | b;      // temp影响y
        // 形成环路:y -> temp -> y
    endmodule
    
    // 错误示例2:通过always块形成的组合逻辑环路
    module combo_loop_always_bad (
        input  wire sel,
        input  wire data_in,
        output reg  data_out
    );
        always @(*) begin
            if (sel)
                data_out = data_in;
            else
                data_out = ~data_out;  // 错误!data_out依赖自身
        end
    endmodule
  • 危害:

    • 电路行为不可预测
      • 振荡问题:环路可能导致输出在0和1之间快速振荡,永远无法稳定
      • 亚稳态:输出可能停留在不确定的电平状态,既不是逻辑0也不是逻辑1
      • 延迟敏感:电路行为完全依赖于门延迟,不同工艺、温度、电压下表现完全不同
    • 时序分析失效:
      • 静态时序分析(STA)工具无法分析:环路没有起点和终点,无法计算建立时间和保持时间
      • 综合工具警告或错误:大多数综合工具会报告组合逻辑环路为关键错误
      • 仿真与实际不符:仿真时可能看起来正常,但实际硬件中可能完全失效
    • 功耗问题:
      • 振荡的环路会导致持续的翻转活动,造成严重的动态功耗浪费
      • 在电池供电的系统中尤其致命
  • 实际案例:

    • 代码示例:
    // ❌ 错误做法:
    // 看似简单的锁存功能,实际形成环路
    module latch_bad (
        input  wire enable,
        input  wire data,
        output reg  q
    );
        always @(*) begin
            if (enable)
                q = data;
            // else分支缺失,q保持不变 → 组合逻辑环路!
        end
    endmodule
    
    //问题分析
    //    - 当enable=0时,q未被赋值,保持原值
    //    - 这意味着q的当前值依赖于q的历史值
    //    - 虽然这是典型的锁存器行为,但在组合逻辑always @(*)中形成了环路
    
    // ✅ 正确做法:
    // 方法1:如果确实需要锁存器,应明确使用时序逻辑
    module latch_good (
        input  wire enable,
        input  wire data,
        output reg  q
    );
        always @(*) begin
            if (enable)
                q = data;
            else
                q = q;  // 明确表示保持,但仍是锁存器
        end
        // 注:锁存器本身在同步设计中也应避免
    endmodule
    
    // 方法2:更好的做法是使用触发器(同步设计)
    module register_best (
        input  wire       clk,
        input  wire       rst,
        input  wire       enable,
        input  wire       data,
        output reg        q
    );
        always @(posedge clk) begin
            if (rst)
                q <= 1'b0;
            else if (enable)
                q <= data;
            // enable=0时q保持,但这是寄存器保持,不是组合环路
        end
    endmodule
  • 避免产生组合逻辑环的方法

    • 使用完整的条件分支
    • 使用寄存器代替锁存器
    • 遵循编码规范

2. 时序逻辑电路

  1. 什么是时序逻辑电路

    • 基本概念:时序逻辑电路是指电路当前输出信号不仅和当前输入信号有关,还和电路之前的状态有关的电路。
    • 电路特点:有反馈电路,也有存储电路(D触发器),只有时钟边沿到达时输出才发生变化
  2. 时序逻辑电路的Verilog描述

    • always模块的敏感表为时钟边沿敏感信号的电路:
  3. 时序逻辑电路的注意事项

    • always块中信号需要声明为reg型,且会被综合为寄存器
    • 需要使用非阻塞赋值<=
End of file.