第一章:数字电路基础回顾

各位同学,欢迎来到《可编程逻辑设计快速上手手册》。

我是你们的讲师,一个在FPGA圈子里摸爬滚打十几年的老工程师。今天咱们聊点最基础的,但也是最重要的——数字电路基础。

你可能会想:“都什么年代了,还讲晶体管?” 别急,我见过太多人,上来就写Verilog,结果综合出来一堆莫名其妙的毛刺,查了半天发现是组合逻辑没搞明白。基础不牢,地动山摇。咱们花点时间,把地基夯实了。

核心观点: 数字电路设计的本质,就是用晶体管搭积木。你只有知道积木长什么样,才能搭出漂亮的城堡。

数字电路基础回顾:知识体系 晶体管(开关) 逻辑门(与、或、非、与非、或非) 组合逻辑 输出只取决于当前输入 时序逻辑 输出取决于输入 + 历史状态 同步设计(时钟驱动,避免毛刺)

1.1 从晶体管到逻辑门

数字电路最底层的单元是什么?是晶体管。你可以把它想象成一个水龙头,或者一个开关。

栅极(Gate)就是开关的把手。给栅极加电压,开关就通了,电流能从源极流到漏极。不加电压,开关就断开。就这么简单。

那怎么用开关搭出逻辑门呢?

举个最简单的例子:非门(反相器)。

一个PMOS管在上,一个NMOS管在下。输入是1,上面的PMOS关断,下面的NMOS导通,输出被拉到地,就是0。输入是0,上面的PMOS导通,下面的NMOS关断,输出被拉到电源,就是1。

你看,这不就是取反吗?

我的小经验: 刚开始学的时候,别死记硬背PMOS和NMOS的导通条件。你就记住:PMOS是“高电平关断”,NMOS是“高电平导通”。我在项目中调试一个IO口驱动能力不足的问题,最后发现就是PMOS和NMOS的尺寸比例没调好。嗯,模拟的东西,有时候就是得靠经验。

有了非门,再组合一下,就能得到与非门、或非门。再组合,就能得到与门、或门。再往下,就是加法器、比较器、多路选择器……

说白了,整个数字世界,就是从这一个开关开始的。

1.2 组合逻辑 vs 时序逻辑

这是新手最容易混淆的地方。我当年也犯过傻。

组合逻辑: 输出只取决于当前的输入。输入一变,输出立刻变(当然,有门延迟)。没有记忆功能。

比如一个加法器:你输入1+1,它立刻输出2。你输入2+2,它立刻输出4。它不记得刚才算过什么。

时序逻辑: 输出不仅取决于当前输入,还取决于电路之前的状态。它有记忆功能。

比如一个计数器:你给它一个时钟,它就在0、1、2、3...之间跳。它记得自己现在数到几了。

特性 组合逻辑 时序逻辑
输出依赖 仅当前输入 当前输入 + 历史状态
记忆能力 有(触发器/锁存器)
时钟 不需要 通常需要
典型电路 加法器、译码器、多路选择器 计数器、寄存器、状态机
毛刺风险 高(路径延迟不同) 低(时钟同步采样)

避坑指南: 我曾经在一个项目中,用组合逻辑做了一个复杂的地址译码器。结果因为不同路径的延迟不一样,输出出现了毛刺,导致后面的寄存器误触发。查了整整两天,最后加了一级流水线寄存器才搞定。所以,跨时钟域或者对时序敏感的信号,一定要用寄存器打一拍

1.3 同步设计的基本概念

什么是同步设计?说白了,就是所有时序逻辑都听同一个时钟的指挥。

时钟就像阅兵式上的指挥官。他说“走”,大家就一起迈左脚。他说“停”,大家就一起立正。这样队伍才整齐,不会你撞我、我撞你。

在FPGA里,这个“指挥官”就是全局时钟网络。它负责把时钟信号低抖动、低偏斜地送到每一个触发器。

同步设计的核心规则:

  • 单时钟域: 尽量让整个设计跑在同一个时钟下。如果必须用多个时钟,一定要做跨时钟域处理(比如用双触发器同步器)。
  • 避免组合逻辑反馈: 不要试图用组合逻辑搭一个“锁存器”。这在FPGA里是禁忌,综合工具会给你一堆警告。
  • 寄存器化输出: 模块的输出信号,最好都从寄存器直接出来。这样时序干净,不容易出问题。

一个简单的同步计数器示例(Verilog):

module counter (
    input  wire       clk,    // 时钟
    input  wire       rst_n,  // 异步复位,低有效
    output reg  [3:0] cnt     // 4位计数器
);

    always @(posedge clk or negedge rst_n) begin
        if (!rst_n)
            cnt <= 4'b0;      // 复位到0
        else
            cnt <= cnt + 1'b1; // 每个时钟上升沿加1
    end

endmodule

你看这个代码:always @(posedge clk or negedge rst_n),这就是同步设计的标志。所有赋值都在时钟上升沿发生。你想想看,如果不用时钟,而是用组合逻辑去控制这个计数器,会是什么后果?

嗯,后果就是:计数器的值会在一个时钟周期内跳变多次,完全不可控。

我的习惯: 写代码之前,我会先画一个简单的时序图。把时钟、复位、输入、输出画清楚。这样写出来的代码,基本不会有时序问题。我建议你也试试。

好了,这一章就到这里。数字电路的基础,说白了就是三件事:晶体管怎么当开关,组合逻辑和时序逻辑的区别,以及为什么要听时钟的话。这些东西,你以后写每一行代码都会用到。

记住:同步设计是FPGA的基石。尊重时钟,时钟也会尊重你。


专注资料整理