4. 工业控制中的FPGA逻辑设计基础

在工业控制场景中,FPGA 的价值并不只是“跑得快”,而是能把控制逻辑做成确定性的硬件行为:输入变化后经过固定数量的时钟周期产生输出,抖动、毛刺和亚稳态都被约束在可预测范围内。要做到这一点,必须把组合逻辑、时序逻辑、状态机、时钟域交叉(CDC)和同步器这五件事放在同一张设计图上理解。它们不是五个独立知识点,而是一条从“信号进入”到“动作输出”的完整链路。

组合逻辑:把布尔关系直接映射成硬件

组合逻辑的输出只由当前输入决定,没有记忆。工业控制里最常见的组合逻辑是安全联锁、使能条件和译码。例如一台伺服驱动器的使能条件可以写成:drive_en = estop_ok & door_closed & phase_ok & !fault_latch。这段代码综合后就是若干 LUT 和与门,输入一变,输出在传播延迟后立即变化。

组合逻辑的关键风险是毛刺和竞争。当多个输入同时变化、路径延迟不一致时,输出可能出现窄脉冲。如果这个脉冲直接去驱动继电器或作为时钟,就会造成误动作。工程上的做法是:组合逻辑只负责“算条件”,真正驱动执行机构的信号必须经过寄存器打拍。此外,组合逻辑不要形成环路,否则会综合出锁存器或振荡结构。在 Verilog 中,always @(*) 块内所有分支都要给输出赋值,否则会推断出 latch,这在工业控制中通常是不希望出现的。

时序逻辑:用时钟建立确定性节拍

时序逻辑由时钟边沿触发,输出在时钟沿更新。它把组合逻辑的“即时结果”变成“每周期推进一次”的稳定状态。工业控制中常用的同步复位时序逻辑写法如下:

always @(posedge clk) begin
    if (!rst_n)
        state <= IDLE;
    else
        state <= next_state;
end

这里 state 是当前状态,next_state 是组合逻辑算出的下一状态。时钟频率决定了控制周期,例如 50 MHz 时钟对应 20 ns 一个节拍。若一个控制算法需要 10 个节拍完成,则响应时间为 200 ns。这个数字是设计前就要算清楚的,而不是综合后再看。

时序逻辑还要关注建立时间和保持时间。只要组合逻辑路径太长,数据在下一个时钟沿前无法稳定,就会产生时序违例。工业控制中常见的做法是把复杂运算拆成多级流水线,用面积换频率,保证每个周期内的逻辑深度可控。

状态机:把控制流程写成可验证的状态迁移

状态机是工业控制逻辑的核心组织方式。它把“先做什么、再做什么、什么条件下跳转”显式写成状态和迁移条件。以一台自动装配机的送料控制为例,可以定义四个状态:IDLE(等待启动)、FEED(送料)、CLAMP(夹紧)、DONE(完成)。迁移条件包括启动按钮、到位传感器和定时器超时。

推荐使用三段式写法:第一段时序逻辑更新当前状态;第二段组合逻辑计算下一状态;第三段时序逻辑或组合逻辑产生输出。三段式的好处是状态寄存和输出逻辑分离,便于时序分析和形式验证。状态编码可以用二进制、格雷码或独热码。状态少时二进制省资源;状态多且迁移频繁时独热码译码简单、速度更快,但寄存器用量增加。工业控制中状态数量通常不大,二进制或独热码都常见,关键是编码后要保证非法状态能被复位或自动恢复到安全状态。

时钟域交叉:多时钟系统里的真实问题

工业控制板往往不止一个时钟:控制环路可能跑在 50 MHz,通信接口跑在 100 MHz,编码器接口又可能来自外部异步时钟。信号从一个时钟域传到另一个时钟域,就是时钟域交叉。CDC 的核心问题是:源域信号的变化时刻与目的域时钟沿没有固定关系,目的域寄存器可能在信号跳变瞬间采样,进入亚稳态。

亚稳态不是“0 或 1”,而是输出在一段时间内既不是有效高电平也不是有效低电平,随后随机稳定到某一值。如果这个不稳定值直接进入状态机,就可能导致状态跳错、误动作。因此,CDC 必须用同步器处理,不能直接跨域连线。

同步器设计:两级触发器与握手

最常用的同步器是两级触发器同步器,用于单比特电平信号。源域信号先进入目的域的第一级触发器,再经过第二级触发器,第二级输出才允许被目的域逻辑使用。两级触发器的作用是给亚稳态留出一年左右的稳定时间,使其在到达第二级前衰减到有效电平。实际工程中,两级同步器可满足大多数中低速控制信号;若时钟频率很高或信号变化很快,可能需要三级。

对于多比特数据,不能简单地对每一位分别打两拍,因为各位的传播延迟不同,可能在同一时钟沿被采样到不同步的值,导致数据错位。正确做法是使用握手同步或异步 FIFO。握手同步通过 req 和 ack 两个单比特信号跨域,数据在源域保持稳定,直到目的域确认接收。异步 FIFO 则用格雷码指针和双口 RAM 实现多比特数据的安全跨域,适合连续数据流场景。

注意:CDC 路径必须被静态时序分析工具识别并约束。若未设置 set_false_path 或 set_max_delay,工具可能对跨域路径做无意义的时序优化,反而破坏同步器结构。同步器寄存器应加 ASYNC_REG 属性,防止被综合工具优化或合并。
工业控制 FPGA 逻辑设计:从组合逻辑到跨时钟同步 组合逻辑 输入 → LUT/门电路 → 输出 无记忆、即时响应 风险:毛刺、竞争、latch 示例:drive_en = estop_ok & door_closed & phase_ok & !fault_latch 时序逻辑 时钟沿触发,输出稳定 建立/保持时间约束 50 MHz → 20 ns/周期 10 拍 → 200 ns 响应 同步复位:rst_n state <= next_state 状态机 IDLE → FEED → CLAMP → DONE → IDLE 三段式:状态寄存 + 次态组合 + 输出 编码:二进制/独热码 非法状态需恢复安全态 同步器 两级触发器 单比特电平信号 多比特:握手/FIFO ASYNC_REG 属性 set_false_path 约束 防亚稳态传播 时钟域交叉(CDC)与两级同步器信号链 源时钟域 clk_a (50 MHz) 信号源 寄存器 数据在源域保持稳定 req 信号拉高 跨域 异步 目的时钟域 clk_b (100 MHz) 第一级 FF1 第二级 FF2 亚稳态窗口 在此衰减 目的域逻辑 安全使用 ack 握手反馈(多比特数据安全跨域) 单比特电平信号用两级触发器同步;多比特数据用握手或异步 FIFO,禁止逐位打拍

把五件事串成一条设计链

回到工业控制的真实设计:编码器信号进入 FPGA,先经过输入同步器消除外部异步抖动;同步后的信号进入组合逻辑做方向判断和计数使能;计数结果在时序逻辑中每个控制周期更新;状态机根据计数、限位和故障信号决定下一步动作;动作输出再经过输出寄存器打拍,保证无毛刺地驱动功率级。整条链路中,组合逻辑负责“算”,时序逻辑负责“稳”,状态机负责“序”,同步器负责“跨”,CDC 约束负责“验”。

一个可执行的检查顺序是:先确认所有跨时钟域信号是否都有同步器;再检查组合逻辑是否存在环路或未赋值分支;然后确认状态机是否有安全恢复路径;最后看时序报告中的建立时间和保持时间是否收敛。若某一步不满足,不要靠提高时钟频率或增加流水线来掩盖,而应回到结构本身修正。工业控制对确定性的要求,最终都落在这些基础逻辑的严谨实现上。