Verilog 实现半加器结构:FPGA 初学实践
为什么从半加器开始?
初学 FPGA 或数字电路时,很多人一上来就想搞图像处理、跑神经网络。结果呢?卡在第一个时钟信号就动不了了。
其实,真正该做的第一件事是:理解组合逻辑的本质。
而半加器,就是通往这个世界的钥匙。
它只做一件简单的事:把两个比特 A 和 B 相加,输出它们的'和'与'进位'。听起来像小学数学题,但它背后藏着三个关键知识点:
- 布尔代数的实际应用(异或、与运算)
- 无状态的组合逻辑行为
- 模块化设计的基本范式
更重要的是,它的结构清晰、验证简单、结果直观——非常适合初学者建立硬件直觉。
半加器的工作原理:不只是公式
我们来看一组真值表:
| A | B | Sum | Carry |
|---|---|---|---|
| 0 | 0 | 0 | 0 |
| 0 | 1 | 1 | 0 |
| 1 | 0 | 1 | 0 |
| 1 | 1 | 0 | 1 |
观察一下:
- 当输入不同(0+1),Sum=1,Carry=0;
- 当输入相同且为 1(1+1),Sum=0,Carry=1 —— 这正是二进制进位!
所以我们可以写出两个表达式:
Sum = A ⊕ B
Carry = A · B
是不是很简洁?但这不是重点。重点是:这些符号如何变成真实世界里的电路?
答案就是——Verilog。
用 Verilog 描述硬件:数据流建模方式
在 FPGA 设计中,我们不'调用函数',而是'搭建电路'。下面这段代码就是在'画一张电路图':
module half_adder (
input wire A,
input wire B,
output wire Sum,
output wire Carry
);
assign Sum = A ^ B; // 异或门出'和'
assign Carry = A & B; // 与门出'进位'
endmodule
关键细节解读:
input wire/output wire:声明端口方向和类型。注意这里都用了wire,因为这是纯组合逻辑输出。assign:连续赋值语句,专用于wire类型。只要 A 或 B 变化,Sum 和 Carry 就立即重新计算。- 没有
always块,没有时钟,也没有寄存器 —— 完全符合组合逻辑特征。
提示:如果你在这里用了
reg并放在always @(*)中赋值,也不是错,但对初学者容易混淆组合/时序逻辑边界。建议从assign开始建立正确直觉。
这段代码经过综合工具(如 Vivado 或 Quartus)处理后,会被映射成 FPGA 内部的 LUT(查找表)资源,物理上等效于一个异或门加一个与门。

