Verilog入门实战——第2讲:核心语法基础(数据类型+赋值语句)

一、前言

完成开发环境搭建后,掌握Verilog核心语法是编写硬件逻辑的基础。与软件编程语言不同,Verilog语法设计围绕"硬件电路映射"展开,数据类型与赋值语句的选择直接决定电路逻辑的正确性。

本文摒弃复杂理论,只讲新手开发必备的核心知识点,通过代码案例直观呈现语法规则,为后续流程控制、模块设计打下坚实基础。

二、核心数据类型:wire与reg(新手必掌握)

Verilog中数据类型繁多,新手只需精通wire 和reg两种,即可覆盖90%的基础开发场景,二者分别对应不同的硬件电路特性。

1. wire型:线网型数据

  • 核心特性 :表示硬件电路中的"物理连线",无存储功能,值随输入信号实时变化,仅能通过连续赋值(assign)赋值。
  • 适用场景:组合逻辑输出、模块间信号连接、输入端口定义。
  • 定义语法 :wire [位宽-1:0] 变量名;(位宽默认1位,可省略)
  • 示例:
verilog 复制代码
// 定义1位wire变量a,连接输入端口
wire a;
// 定义8位wire变量data,存储8位数据
wire [7:0] data;

2. reg型:寄存器型数据

  • 核心特性 :表示硬件电路中的"存储单元"(如触发器),有记忆功能,值在时钟边沿或条件触发时更新,仅能在过程块(always、initial)中赋值。
  • 适用场景:时序逻辑变量、计数器、状态机状态变量。
  • 定义语法 :reg [位宽-1:0] 变量名;
  • 示例:
verilog 复制代码
// 定义1位reg变量flag,用于标记状态
reg flag;
// 定义4位reg变量cnt,用于十进制计数
reg [3:0] cnt;

3. 核心区别总结(避坑重点)

数据类型 赋值方式 硬件映射 适用逻辑
wire assign连续赋值 物理连线 组合逻辑
reg 过程块赋值(always/initial) 存储单元 时序逻辑

三、赋值语句:3种方式的严格区分

赋值语句是Verilog编写的核心,赋值方式与数据类型强绑定,混用会直接导致编译报错或逻辑错误,新手需严格区分。

1. 连续赋值(assign):专属wire型

  • 语法规则 :assign 目标变量 = 表达式;
  • 核心特点:赋值语句执行不受时间控制,表达式中任意信号变化,目标变量会立即更新,完全贴合组合逻辑"无记忆、实时响应"的特性。
  • 案例:二输入或门(组合逻辑)
verilog 复制代码
module assign_demo(
    input wire a,
    input wire b,
    output wire y
);

// 连续赋值:y随a、b实时变化,a=1或b=1时,y立即为1
assign y = a | b;

endmodule

2. 阻塞赋值(=):专属reg型(组合逻辑过程块)

  • 语法规则 :仅在always过程块中使用,格式为变量 = 表达式;
  • 核心特点:赋值操作"先执行完再继续",同一过程块中,前面的赋值会立即影响后面的语句,类似软件编程语言的赋值逻辑。
  • 适用场景 :always块实现组合逻辑时(如用always写多路选择器)。
  • 案例:二选一选择器(组合逻辑)
verilog 复制代码
module block_assign(
    input wire sel,
    input wire data0,
    input wire data1,
    output reg out  // 过程块赋值,需定义为reg型
);

// always块实现组合逻辑,敏感列表包含所有输入信号
always @(sel or data0 or data1) begin
    if(sel == 1'b1)
        out = data1;  // 阻塞赋值,先执行
    else
        out = data0;  // 受前面赋值影响(本案例无体现,复杂逻辑中需注意)
end

endmodule

3. 非阻塞赋值(<=):专属reg型(时序逻辑过程块)

  • 语法规则 :仅在always过程块中使用,格式为变量 <= 表达式;
  • 核心特点:赋值操作"先暂存,过程块结束后统一执行",同一过程块中,所有赋值语句互不影响,完美贴合时序逻辑"时钟边沿同步更新"的特性。
  • 适用场景 :always块实现时序逻辑时(如计数器、触发器)。
  • 案例:简单D触发器(时序逻辑)
verilog 复制代码
module non_block_assign(
    input wire clk,    // 时钟信号
    input wire rst_n,  // 低电平复位信号
    input wire d,      // 输入数据
    output reg q       // 输出数据,reg型
);

// always块实现时序逻辑,敏感列表为时钟上升沿+复位下降沿
always @(posedge clk or negedge rst_n) begin
    if(rst_n == 1'b0)
        q <= 1'b0;    // 复位,输出0
    else
        q <= d;       // 时钟上升沿,将d的值赋给q,非阻塞赋值
end

endmodule

4. 赋值语句避坑指南

  1. 禁止用assign给reg型变量赋值,禁止在过程块中给wire型变量赋值;
  2. 组合逻辑过程块(always)必须用阻塞赋值(=),时序逻辑过程块(always)必须用非阻塞赋值(<=),禁止混用;
  3. 过程块中,reg型变量必须初始化,避免出现不定态(x)。

四、实操验证:语法混合案例

结合上述知识点,编写一个"带复位的简单计数器",整合wire、reg、阻塞/非阻塞赋值的使用,帮助新手融会贯通。

verilog 复制代码
// 顶层模块:4位二进制计数器(0-15)
module counter_demo(
    input wire clk,      // 时钟输入
    input wire rst_n,    // 低电平复位
    output wire [3:0] out// 计数输出,wire型
);

// 定义reg型变量,存储计数值(时序逻辑,需reg型)
reg [3:0] cnt;

// 时序逻辑:计数器核心,非阻塞赋值
always @(posedge clk or negedge rst_n) begin
    if(rst_n == 1'b0)
        cnt <= 4'b0000;  // 复位,计数值清零
    else
        cnt <= cnt + 1'b1;  // 时钟上升沿,计数值+1
end

// 组合逻辑:将reg型的cnt赋值给wire型的out,连续赋值
assign out = cnt;

endmodule
相关推荐
FPGA小迷弟18 小时前
FPGA 与卫星:从星载硬件到在轨智能的完整技术解析
fpga开发·架构·fpga·1024程序员节·无线电
NamoAmitabha12819 小时前
CPU 内部结构是什么?---deepseek
fpga开发
abc light20 小时前
ARM 裸机开发(6)——时钟树与定时器
arm开发·单片机·fpga开发
156082072191 天前
JFMZQ28DR、JFMZQ68DR、RFsoc XCZU47DR、XCZU48DR 信号处理板
fpga开发·信号处理
XMAIPC_Robot2 天前
-40~85℃宽温实测:RK3588 机器人控制器硬件底座,长时间 SLAM 定位稳定性验证
人工智能·fpga开发·机器人·边缘计算·arm+fpga·rk3588+fpga
樱木花道長2 天前
AMD Ross 深度系列 8:FAQ 七问七答(文末附网盘链接)
人工智能·fpga开发
FPGA小迷弟2 天前
FPGA 与无人机:从飞控实时性到智能载荷的硬件加速实践
人工智能·ai·fpga开发·架构·无人机·ai编程
低慢小uav2 天前
(已解决)Zynq芯片lwip协议栈,使用tcp作为服务器Service,接收大量数据时,长度接收正常,接收对数据校验,校验和异常分析
网络协议·tcp/ip·fpga开发
szxinmai主板定制专家2 天前
ARM+FPGA 数控机床控制器:选 CODESYS SoftMotion CNC,还是基于 LinuxCNC 自研搭建?架构、授权、实时性、量产风险深度对比
arm开发·fpga开发·codesys·数据采集卡·linuxcnc·rk3576
女神下凡2 天前
芯参谋(79):嵌入式学习进阶_(硬件与软件)深入实践指南
arm开发·单片机·嵌入式硬件·学习·fpga开发·设计规范