一、Verilog 初探:从历史到第一个程序

大家好,我是你们的 FPGA 讲师。今天咱们聊聊 Verilog 这门语言。

说实话,我刚开始接触 Verilog 时,也觉得它不过就是另一种编程语言。但后来发现,完全不是那么回事。它描述的是硬件,是实实在在的电路。你写下的每一行代码,最终都会变成芯片上的门电路。这种感觉,很奇妙。

1.1 Verilog 的历史与用途

Verilog 诞生于 1984 年,由 Gateway Design Automation 公司开发。后来被 Cadence 收购,再后来成了 IEEE 标准(1364)。

为什么学它?说白了,数字芯片设计离不开它。从 FPGA 原型验证到 ASIC 流片,Verilog 都是主流语言之一。我参与过的项目里,从通信基带到图像处理,几乎都用 Verilog 描述核心逻辑。

它的主要用途包括:

  • 数字电路建模:描述组合逻辑和时序逻辑
  • 仿真验证:在电脑上跑仿真,看波形对不对
  • 综合实现:把代码变成真实的门级网表
  • FPGA 开发:Xilinx、Intel 的芯片都用它编程
我的经验:刚入行时,我总觉得仿真差不多就行了。直到有一次,仿真通过了,但综合后时序不满足,板子跑不起来。嗯,从那以后,我再也不敢轻视仿真和综合的差异了。

1.2 模块化设计思想

Verilog 的核心思想是什么?模块化。

你想想看,一个复杂的数字系统,比如一个 CPU,有成千上万个门。如果全写在一个文件里,谁也看不懂。所以,我们把系统拆成一个个小模块。每个模块负责一个功能,模块之间通过端口连接。

这样做的好处很明显:

  • 可复用:写好的模块,下次还能用
  • 可维护:改一个模块,不影响其他模块
  • 可分工:团队里每人负责一个模块

我习惯把模块比作乐高积木。每个积木有固定的接口,拼在一起就成了大系统。你不需要知道积木内部怎么做的,只要知道它怎么拼就行。

1.3 第一个 Verilog 程序:半加器

好了,咱们直接上手写代码。第一个程序,我选半加器。为什么?因为它简单,但包含了 Verilog 模块的全部要素。

半加器做什么?两个二进制位相加,输出和(Sum)与进位(Carry)。

真值表如下:

A B Sum Carry
0 0 0 0
0 1 1 0
1 0 1 0
1 1 0 1

逻辑表达式很简单:

  • Sum = A XOR B
  • Carry = A AND B

现在,用 Verilog 实现它:

module half_adder (
    input  wire a,      // 输入 a
    input  wire b,      // 输入 b
    output wire sum,    // 和
    output wire carry   // 进位
);

    // 组合逻辑描述
    assign sum   = a ^ b;   // 异或
    assign carry = a & b;   // 与

endmodule

你看,一个完整的 Verilog 模块包含:

  • 模块声明:module half_adder
  • 端口定义:input 和 output
  • 内部逻辑:assign 语句
  • 结束标志:endmodule
注意:Verilog 是并行执行的。上面两行 assign 语句是同时执行的,不是顺序执行。这和 C 语言完全不同。我刚开始写时,总习惯按顺序思考,结果仿真老出错。后来才明白,硬件里所有逻辑是同时工作的。

1.4 仿真与综合概念

写完了代码,然后呢?你得验证它对不对。这就用到仿真了。

仿真,就是在电脑上模拟电路的行为。你给输入信号,看输出是不是你想要的。我用的是 ModelSim 或 VCS。写个 testbench,给 a 和 b 赋值,看 sum 和 carry 对不对。

举个例子,半加器的 testbench:

module tb_half_adder;
    reg  a, b;
    wire sum, carry;

    half_adder uut (
        .a(a),
        .b(b),
        .sum(sum),
        .carry(carry)
    );

    initial begin
        a = 0; b = 0; #10;
        a = 0; b = 1; #10;
        a = 1; b = 0; #10;
        a = 1; b = 1; #10;
        $finish;
    end

endmodule

仿真通过后,下一步是综合。综合把 Verilog 代码转换成门级网表,也就是真实的逻辑门(与门、或门、触发器)。

我曾经犯过一个错:仿真通过了,但综合时报错,说代码不可综合。比如用了 #10 延时,仿真能用,但综合工具不认识。所以,写代码时就要想着:这代码能变成电路吗?

避坑指南:不是所有 Verilog 语法都能综合。比如 initial 块、#delay、force 等,只能用于仿真。写可综合代码时,要时刻问自己:这行代码对应什么硬件?

1.5 本章知识体系

下面这张图,帮你理清本章的核心逻辑:

Verilog 初探 历史与用途 1984年诞生 FPGA/ASIC 设计 模块化设计 可复用、可维护 端口连接 第一个程序 半加器 assign 语句 仿真与综合 仿真验证功能 综合生成电路 核心:从代码到硬件的思维转变

这张图展示了本章的四个核心知识点。它们环环相扣:先了解背景,再掌握设计思想,然后动手写代码,最后验证和实现。每一步都不可或缺。

我的建议:初学者最容易犯的错,就是把 Verilog 当 C 语言写。记住,你是在设计电路,不是在写软件。每写一行代码,想想它对应什么门电路。这个习惯,会让你少走很多弯路。

好了,这一章就到这里。代码不多,但概念很重要。下一章,咱们会深入 Verilog 的语法细节,包括数据类型、运算符、模块例化等。到时候,我会分享更多实战中的小技巧。

可可精品资料库