2. Verilog基础语法(上):模块结构、数据类型、运算符、assign语句

各位同学,咱们今天开始啃Verilog的硬骨头。说实话,很多初学者一上来就被语法吓住了。其实没那么玄乎,你把它想象成画电路图的另一种方式就行。我当年刚学的时候,也是对着书本发懵,后来发现——说白了,Verilog就是在描述硬件长什么样、怎么连。

2.1 模块结构——Verilog的骨架

每个Verilog设计,都是从module开始,到endmodule结束。这就像盖房子先搭框架。模块就是你的电路单元,可以是一个与门,也可以是一个完整的电机驱动核。

module pwm_generator(
    input  wire       clk,
    input  wire       rst_n,
    input  wire [7:0] duty_cycle,
    output reg        pwm_out
);
    // 内部逻辑写在这里
endmodule

注意看,端口声明有三种:inputoutputinout。我在项目中遇到过新手把inout当普通输出用,结果仿真死活不对。双向口要慎用,除非你真的很清楚自己在干什么。

核心要点:模块就是硬件单元。一个模块对应一块电路。别想着用模块去实现复杂的软件算法,那是CPU干的事。

2.2 数据类型——线网与寄存器

Verilog里最常用的两种数据类型:wirereg。嗯,这里要注意,很多人一开始搞混它们。

  • wire:物理连线。它不存储值,只是传递驱动源的值。比如把A门的输出连到B门的输入。
  • reg:寄存器。它能保持上一次赋的值,直到被再次赋值。但注意,reg不一定会综合成触发器,也可能只是连线。

我建议你这样记:在always块里赋值的变量,用reg;在assign语句里赋值的,用wire。这个规则在99%的情况下都适用。

个人经验:我曾经在写SPI接口时,把wire类型误写成reg,结果综合工具报了一大堆警告。排查了半天才发现是类型搞错了。从那以后,我习惯在声明时就明确标注用途。

2.3 运算符——硬件的数学

Verilog的运算符跟C语言很像,但有些细节完全不同。你想想看,C语言里a = b + c是瞬间完成的,但在硬件里,加法器是有延迟的。

运算符类别 符号 说明
算术 + - * / % 乘除法综合出来面积大,慎用
位运算 & | ~ ^ 直接对应逻辑门
归约运算 & | ^ ~^ 单目运算符,对向量所有位操作
逻辑运算 && || ! 结果只有0或1
移位 << >> 左移补0,右移补0
拼接 { } 把多个信号拼成一个向量

举个例子,归约运算符很多人不常用,但其实很实用。比如你想检查一个8位总线是否全为0:

wire all_zero;
assign all_zero = ~|data_bus;  // 归约或,再取反

这比写data_bus == 8'b0更节省资源。我在做电机电流采样时,经常用归约运算快速判断过流状态。

避坑指南:我曾经在计算PWM占空比时,直接用*做乘法,结果综合出来的乘法器占了大半个FPGA。后来改用移位加加法,面积直接降了70%。记住:硬件里乘除法很贵,能不用就不用。

2.4 assign语句——连续赋值

assign是Verilog里最直观的语句。它描述的是组合逻辑,只要右边表达式有变化,左边立刻更新。说白了,就是一根导线,只不过这根导线可以带点逻辑。

// 一个简单的比较器
assign led_on = (counter > threshold) ? 1'b1 : 1'b0;

// 电机方向控制
assign motor_dir = (speed_ref > speed_actual) ? 1'b1 : 1'b0;

注意,assign的左边必须是wire类型。如果你试图给reg赋值,综合工具会报错。这个错误我见过太多次了,尤其是从软件转过来的工程师。

另外,多个assign语句是并行执行的,不是顺序执行。这是硬件和软件最本质的区别。你写十个assign,它们同时工作,就像十个独立的逻辑门同时翻转。

实战技巧:在写电机驱动时,我习惯把所有的组合逻辑都用assign实现,只在always块里放时序逻辑。这样代码结构清晰,仿真也容易调试。你试试看,维护起来会轻松很多。

2.5 本章知识体系

下面这张图,是我自己总结的Verilog基础语法脉络。你照着这个思路学,不会乱。

Verilog基础语法 模块结构 数据类型 运算符 端口声明 内部信号 wire类型 reg类型 算术/位运算 归约/拼接 assign连续赋值 组合逻辑描述 并行执行特性

这张图把本章的四个核心知识点串起来了。模块是外壳,数据类型是材料,运算符是工具,assign是施工方法。四者缺一不可。

我的建议:学语法别死记硬背。找个小项目练手,比如写个PWM发生器。边写边查,边查边改。我当年就是这么过来的,三个月后基本语法就烂熟于心了。

好了,这一章的内容就到这里。记住,Verilog不是编程语言,是硬件描述语言。你写的每一行代码,最终都会变成实实在在的电路。带着这个意识去学,事半功倍。

专注资料整理