1. 硬件描述语言:用代码“画”出电路
很多刚接触FPGA的朋友,尤其是从软件编程转过来的,一开始都会有个大大的问号:Verilog看起来和C语言好像啊,是不是学会了C就能轻松上手?我刚开始学的时候也这么想,结果踩了不少坑。今天我就用最直白的方式,跟你聊聊Verilog到底是什么,以及它和软件编程到底有啥本质区别。
你可以把Verilog想象成一种“电路图纸描述语言”。我们平时用Altium Designer或者立创EDA画原理图、PCB,是用图形化的方式告诉工厂:“我要一个这样的电路板”。而Verilog,则是用文本代码的方式,告诉FPGA或者芯片设计工具:“我要一个这样的数字电路”。编译器(在FPGA里我们叫综合工具)会读取你的Verilog代码,然后把它“翻译”成实实在在的逻辑门、触发器、连线等硬件资源,最终在FPGA的硅片上实现出来。
这跟写C程序有根本性的不同。C程序是顺序执行的,CPU一条指令接一条指令地跑。但Verilog描述的硬件是并行工作的。举个例子,你写了一个模块,里面有两个always块,一个描述计数器,一个描述状态机。在真实的硬件里,只要时钟一响,这两个部分是同时在工作的,就像你家里的电灯和电视,一通电就同时亮、同时开,谁也不等谁。理解这种“并行思维”,是跨过Verilog学习第一道坎的关键。
那么,Verilog代码最终变成了什么?对于FPGA开发来说,流程大概是这样的:你写好Verilog代码 -> 综合工具将其转换成由查找表(LUT)、触发器(FF)、布线资源等基本单元构成的网表 -> 布局布线工具把这些单元放到FPGA芯片的具体位置上,并连接好 -> 生成一个比特流(bitstream)文件 -> 下载到FPGA里。这块芯片内部的连接就按照你的代码“重塑”了,变成了你专属的电路。所以,写Verilog,其实就是在“雕刻”FPGA内部的硅片结构。
2. 代码的基石:模块与端口
在Verilog的世界里,一切设计都始于module(模块)。模块是Verilog设计的基本构建块,你可以把它理解为一个黑盒子或者一个集成电路芯片。这个黑盒子有对外连接的引脚(端口),也有内部复杂的电路结构(逻辑描述)。这种层次化的设计思想,能让复杂系统像搭积木一样构建起来。
一个最基本的模块框架长这样:
module my_first_module (
// 端口声明列表
input wire clk, // 输入端口,时钟信号
input wire rst_n, // 输入端口,低电平有效的复位信号
input wire [7:0] data_in, // 输入端口,8位宽的数据总线
output reg [7:0] data_out // 输出端口,8位宽的数据寄存器
);
// 在这里编写模块内部的逻辑
// ...
endmodule
我来拆解一下这个框架的要点:
module和endmodule:这是模块的“书皮”和“封底”,必须成对出现,中间包裹着整个模块的内容。- 模块名:
my_first_module。取名最好有实际意义,比如uart_tx、fifo_ctrl。强烈建议模块名和保存的.v文件名保持一致,虽然Verilog标准不强制,但像Quartus、Vivado这些主流工具都会默认这样要求,能避免很多不必要的麻烦。 - 端口列表:括号里声明了这个黑盒子所有对外的“引脚”。这是模块与外界通信的唯一通道。
- 端口方向:主要有三种:
input:输入信号,信号从模块外部流入内部。对于模块来说,它是只读的。output:输出信号,信号从模块内部产生,流向外部。inout:双向端口,既可以输入也可以输出。常用于I2C、SDRAM数据线等需要双向传输的总线。新手期用得少,但要知道它的存在。
- 端口类型:紧跟在方向后面的
wire或reg。这里有个初学者最容易混淆的规则:input端口只能是wire型。因为输入信号是从外部驱动进来的,模块内部只是接收。output端口可以是wire或reg型。这取决于你在模块内部如何驱动它。如果用assign语句驱动,必须是wire;如果在always块里赋值,必须是reg。inout端口在可综合设计中一般也定义为wire。
在实际项目中,一个复杂的系统就是由多个这样的模块实例化连接而成的。比如一个简单的LED闪烁工程,可能包含一个“时钟分频模块”和一个“LED控制模块”。在顶层模块中,你会像调用函数一样去“实例化”它们,并把它们的端口用“线”连起来。这就像在原理图上放置两个芯片并连线一样。
module top (
input sys_clk,
input sys_rst_n,
output [3:0] led
);
// 定义内部连接线
wire clk_1hz; // 连接两个模块的“导线”
// 实例化分频模块,给它起个名字叫u_clk_div
clk

157

被折叠的 条评论
为什么被折叠?



