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

一、前言

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

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

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

Verilog中数据类型繁多,新手只需精通wirereg两种,即可覆盖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
相关推荐
ALINX技术博客1 小时前
ALINX 亮相 2026 WAIC 世界人工智能大会,展示 AI 视觉 FPGA+GPU 异构计算与电子后视镜解决方案
人工智能·ai·fpga·世界人工智能大会·电子后视镜
仲南音15 小时前
Xilinx FPGA——时钟IP核MMCM、PLL
fpga开发
I'm a winner1 天前
基于Xilinx FPGA的LVDS高速串行通信系统(三)--数据训练及握手机制【文末源码】
fpga开发
upper20201 天前
coremark移植坑之-nostartfiles -nostdlib参数
学习·fpga开发·coremark移植·riscv设计
Eloudy2 天前
Vivado 纯命令行构建 FPGA 项目教程
fpga开发
Rambo.xia2 天前
AXI跨时钟域与数据一致性——CDC FIFO深度不够、写后读冒险、多Master仲裁、乱序返回,出了Bug根本查不出来
fpga开发·bug
upper20202 天前
FPGA部署卷积神经网络识别MINST图片
fpga开发·卷积神经网络·minst·minst识别·部署神经网络·神经网络识别图片
你是我的解忧王子2 天前
嵌入式 ADC采样 原始数据分析上层(平均值 波动率 正态分布 线性补偿 系统误差)
fpga开发·数据挖掘·数据分析
Eloudy2 天前
RFSoC 4x2 参考手册
fpga
9527华安3 天前
FPGA纯verilog代码ISP图像处理培训教程,基于IMX214,提供工程源码+视频教程+FPGA开发板
图像处理·fpga开发·isp·imx214·mipi