2. Verilog基础(一):模块与端口、数据类型(wire/reg)、连续赋值(assign)、基础门级建模
好,咱们正式开始写代码了。
Verilog 这玩意儿,说白了就是描述数字电路的硬件语言。你写的每一行代码,最终都会变成芯片上实实在在的晶体管和连线。我刚开始学的时候,总把它当软件写,结果综合出来的电路乱七八糟。后来才明白——你得用电路的思维去写它。
2.1 模块与端口——芯片的“黑盒子”
模块(module)是 Verilog 最基本的构建单元。你可以把它想象成一个黑盒子,有输入、有输出,内部实现具体的功能。
module adder (
input [3:0] a, // 4位输入
input [3:0] b, // 4位输入
output [4:0] sum // 5位输出(考虑进位)
);
assign sum = a + b;
endmodule
端口方向有三种:input、output、inout。我个人习惯把输入写在前面,输出写在后面,这样结构清晰。
命名规范建议:端口名用有意义的英文单词,比如
clk、rst_n、data_in。别用 a1、b2 这种,三个月后你自己都看不懂。
2.2 数据类型——wire 和 reg 的区别
这是新手最容易搞混的地方。我面试的时候,十个人里有八个说不清楚。
| 类型 | 本质 | 赋值方式 | 默认值 | 典型用途 |
|---|---|---|---|---|
wire |
物理连线 | 连续赋值(assign)或模块端口连接 | 高阻态(z) | 组合逻辑输出、模块间连线 |
reg |
存储单元 | 过程赋值(always 块内) | 不定态(x) | 时序逻辑、寄存器、状态机 |
记住一个口诀:wire 是线,reg 是寄存器。但注意——reg 不一定会综合成寄存器。如果你在 always 块里写组合逻辑,reg 综合出来还是连线。
我曾经踩过的坑:在 always 块里给 wire 赋值,编译直接报错。反过来,用 assign 给 reg 赋值也不行。类型用错了,工具会毫不留情地给你一堆 error。
2.3 连续赋值(assign)——组合逻辑的“直通车”
assign 是组合逻辑的核心。它的意思是:右边信号一变,左边立刻更新。
wire [7:0] a, b;
wire [8:0] sum;
wire carry;
assign {carry, sum} = a + b; // 拼接操作,carry是进位
assign 的左边必须是 wire 类型。右边可以是任何表达式。你想想看,这就像用导线直接把两个加法器的输出连到总线上——没有延迟,没有时钟,纯组合逻辑。
实用技巧:用
assign 写简单的逻辑判断,比用 always 块更简洁。比如:
assign data_valid = (data_count > 0) && !fifo_empty;
2.4 基础门级建模——从晶体管到逻辑门
Verilog 支持直接调用基本门单元:and、or、nand、nor、xor、xnor、not、buf。
module basic_gates (
input a, b,
output y1, y2, y3
);
and (y1, a, b); // y1 = a & b
or (y2, a, b); // y2 = a | b
xor (y3, a, b); // y3 = a ^ b
endmodule
门级建模的语法是:门类型 (输出, 输入1, 输入2, ...)。第一个端口永远是输出,后面全是输入。
说实话,现在做数字芯片设计,很少有人手写门级网表了。综合工具会帮你把 RTL 代码映射到标准单元库。但理解门级建模有两个好处:
- 写 testbench 时,偶尔需要模拟简单的门延迟
- 做 FPGA 原型验证时,某些特殊接口需要手动例化 I/O 缓冲器
我的经验:门级建模在 ASIC 设计里主要用于后仿真的网表调试。有一次芯片回来功能不对,我就是在门级网表里追信号,发现一个 buffer 被优化掉了——这就是门级建模的价值。
2.5 本章知识体系
下面这张图把本章的核心概念串起来了:
2.6 避坑指南
最后,分享几个我当年踩过的坑:
- wire 默认值是 z,不是 0。 如果你忘了给 wire 赋值,仿真里看到的就是高阻态。我曾经因为这个查了整整一天。
- reg 默认值是 x。 在仿真里,未初始化的 reg 会传播不定态。所以复位逻辑一定要写清楚。
- assign 不能写在 always 块里。 这是语法错误,工具会直接报错。
- 门级建模的端口顺序不能错。 第一个必须是输出,后面是输入。顺序错了,综合出来的电路跟你想要的天差地别。
一句话总结:模块是骨架,端口是接口,wire 和 reg 是血肉,assign 是组合逻辑的直通车,门级建模是底层视角。把这几个概念吃透,Verilog 就算入门了。