FPGA线上课程平台|最全栈的FPGA学习平台|FPGA工程师认证培训
登录
首页-技术文章/快讯-技术分享-正文

从零开始学Verilog:数据类型与运算符详解

二牛学FPGA二牛学FPGA
技术分享
1小时前
0
0
2

Quick Start:最短路径跑通 Verilog 数据类型与运算符

本小节通过一个最小测试用例,帮助你快速验证 Verilog 常用数据类型运算符的基本用法。你只需要一个仿真器(如 ModelSim、Vivado Simulator 或 Icarus Verilog),无需硬件板卡。

  • 步骤 1:准备环境。安装任一仿真器,推荐 Vivado 2023.1(自带 xsim)或 Icarus Verilog 12.0(开源,免费)。确保 iverilog 和 vvp 命令可用。
  • 步骤 2:创建工程目录。新建文件夹 verilog_basics,在其中创建文件 data_types_tb.v(测试平台)。
  • 步骤 3:编写测试平台代码。复制以下完整代码到 data_types_tb.v
`timescale 1ns / 1ps

module data_types_tb;
    // 1. 线网类型 (wire)
    wire [7:0] sum;
    
    // 2. 寄存器类型 (reg)
    reg [7:0] a, b;
    reg [3:0] sel;
    reg clk, rst_n;
    
    // 3. 整数类型 (integer)
    integer i;
    
    // 4. 时间类型 (time)
    time sim_time;
    
    // 测试用例
    initial begin
        $display("=== Verilog Data Types & Operators Demo ===");
        
        // 初始化
        a = 8'd10;   // 十进制 10
        b = 8'h0F;   // 十六进制 15
        sel = 4'b1010; // 二进制 1010 (十进制 10)
        
        // 算术运算符: + - * / %
        $display("a + b = %d", a + b);
        $display("a - b = %d", a - b);
        $display("a * b = %d", a * b);
        $display("a / b = %d (integer division)", a / b);
        $display("a %% b = %d", a % b);
        
        // 位运算符: & | ^ ~
        $display("a & b = %b", a & b);
        $display("a | b = %b", a | b);
        $display("a ^ b = %b", a ^ b);
        
        // 逻辑运算符: && || !
        $display("a && b = %b", a && b);
        $display("a || b = %b", a || b);
        $display("!a = %b", !a);
        
        // 关系运算符: > >= <  b = %b", a > b);
        $display("a == b = %b", a == b);
        $display("a != b = %b", a != b);
        
        // 移位运算符: <>
        $display("a << 2 = %d", a <> 2 = %d", a >> 2);
        
        // 拼接运算符: { }
        $display("{a, b} = %h", {a, b});
        $display("{4{a[7]}, a} = %b", {4{a[7]}, a});
        
        // 条件运算符: ? :
        $display("sel == 0 ? a : b = %d", sel == 0 ? a : b);
        
        // 循环与时间
        for (i = 0; i < 4; i = i + 1) begin
            sim_time = $time;
            $display("Loop iteration %0d at time %0t", i, sim_time);
        end
        
        $finish;
    end
    
    // 连续赋值 (wire 驱动)
    assign sum = a + b;
    
    // 监控
    initial begin
        $monitor("At time %0t: a=%d, b=%d, sum=%d", $time, a, b, sum);
    end

endmodule
  • 步骤 4:编译与仿真
    若使用 Icarus Verilog:
    iverilog -o data_types_tb.vvp data_types_tb.v
    vvp data_types_tb.vvp

    若使用 Vivado:在 Tcl Console 执行 xsc data_types_tb.v 然后 xsim data_types_tb
  • 步骤 5:观察输出。终端应打印类似以下内容(具体数值因运算而异):
    === Verilog Data Types & Operators Demo ===
    a + b = 25
    a - b = -5 (补码表示)
    a * b = 150
    a / b = 0 (整数除法,10/15=0)
    a % b = 10
    a & b = 00001010
    a | b = 00001111
    a ^ b = 00000101
    a && b = 1
    a || b = 1
    !a = 0
    a > b = 0
    a == b = 0
    a != b = 1
    a << 2 = 40
    a >> 2 = 2
    {a, b} = 0A0F
    {4{a[7]}, a} = 0000000000001010
    sel == 0 ? a : b = 15
    Loop iteration 0 at time 0
    Loop iteration 1 at time 0
    Loop iteration 2 at time 0
    Loop iteration 3 at time 0
    At time 0: a=10, b=15, sum=25
  • 步骤 6:验收点。确认所有运算符输出正确,特别是整数除法和取模的行为(截断)。若输出与预期不符,检查变量位宽(8 位)和数值表示(无符号)。

前置条件与环境

项目 / 推荐值说明替代方案
仿真器Icarus Verilog 12.0 或 Vivado 2023.1ModelSim SE-64 10.7、Verilator 5.0(仅支持可综合语法)
操作系统Linux (Ubuntu 22.04) 或 Windows 10/11macOS (需自行编译 Icarus)
文本编辑器VS Code + Verilog-HDL/SystemVerilog 扩展Vim、Sublime Text、Notepad++
基础知识了解二进制、十六进制、补码表示数字电路基础(与或非门)
工程结构单文件测试平台(.v)多文件工程(模块 + 测试平台)
仿真时间尺度`timescale 1ns / 1ps其他时间单位(如 1ns/100ps)
约束文件本练习不需要上板时需要 .xdc

目标与验收标准

  • 功能点:掌握 Verilog 四种基本数据类型(wire、reg、integer、time)的声明与赋值。熟练使用算术、位、逻辑、关系、移位、拼接、条件运算符,并理解其行为差异。
  • 性能指标:无(纯仿真练习)。
  • 资源 / Fmax:无。
  • 关键波形 / 日志验收方式
    – 仿真终端打印所有运算符结果,与手动计算一致。
    – 整数除法结果截断(如 10/15=0)。
    – 取模结果符号与被除数相同(如 -10 % 3 = -1)。
    – 拼接与复制运算符正确生成宽位向量。

实施步骤

阶段一:工程结构与数据类型声明

创建测试平台模块 data_types_tb,内部声明所有需要的数据类型。注意:wire 用于连续赋值驱动(如 assign sum = a + b;),reg 用于过程块(initialalways)内赋值。integer 默认 32 位有符号,time 默认 64 位无符号。

`timescale 1ns / 1ps

module data_types_tb;
    // wire: 线网,用于连续赋值或模块端口连接
    wire [7:0] sum;
    
    // reg: 寄存器,用于过程赋值 (initial/always)
    reg [7:0] a, b;
    reg [3:0] sel;
    reg clk, rst_n;
    
    // integer: 32位有符号整数,常用于循环计数
    integer i;
    
    // time: 64位无符号,存储仿真时间
    time sim_time;
    
    // 连续赋值驱动 wire
    assign sum = a + b;
    
    // ... 后续代码

常见坑与排查

  • 坑 1:wire 不能在 initial/always 中赋值。如果试图在 initial 里写 sum = a + b;,编译器报错。修复:将 sum 改为 reg 或在 initial 外使用 assign。
  • 坑 2:位宽不匹配。例如 reg [3:0] c; 赋值为 8'hFF,高位被截断(c=4'hF)。检查赋值时位宽是否一致,或使用 $display 观察实际值。

阶段二:运算符使用与行为验证

initial 块中依次测试各类运算符。重点注意:

  • 算术运算符+ - * / %。整数除法结果向零取整(截断)。取模结果符号与被除数相同(Verilog-2001 标准)。
  • 位运算符& | ^ ~。按位操作,结果位宽与操作数最大位宽相同。若操作数位宽不同,短者高位补 0。
  • 逻辑运算符&& || !。将操作数视为布尔值(非 0 即 1),结果仅为 1 位。
  • 关系运算符> >= < <= == !=。返回 1 位布尔值。注意:===!== 用于全等比较(包含 x 和 z),本练习未涉及。
  • 移位运算符<>。逻辑移位,空位补 0。算术移位 <<>> 保留符号位(用于有符号数)。
  • 拼接与复制{a, b} 将两个向量拼接;{4{a[7]}, a} 复制 a[7] 四次再拼接 a。
  • 条件运算符条件 ? 表达式1 : 表达式2。类似于 if-else,但用于表达式内。
initial begin
        $display("=== Verilog Data Types &amp; Operators Demo ===");
        
        // 初始化
        a = 8'd10;   // 十进制 10
        b = 8'h0F;   // 十六进制 15
        sel = 4'b1010; // 二进制 1010 (十进制 10)
        
        // 算术运算符
        $display("a + b = %d", a + b);
        $display("a - b = %d", a - b);
        $display("a * b = %d", a * b);
        $display("a / b = %d (integer division)", a / b);
        $display("a %% b = %d", a % b);
        
        // 位运算符
        $display("a &amp; b = %b", a &amp; b);
        $display("a | b = %b", a | b);
        $display("a ^ b = %b", a ^ b);
        
        // 逻辑运算符
        $display("a &amp;&amp; b = %b", a &amp;&amp; b);
        $display("a || b = %b", a || b);
        $display("!a = %b", !a);
        
        // 关系运算符
        $display("a &gt; b = %b", a &gt; b);
        $display("a == b = %b", a == b);
        $display("a != b = %b", a != b);
        
        // 移位运算符
        $display("a &lt;&lt; 2 = %d&quot;, a &lt;&gt; 2 = %d", a &gt;&gt; 2);
        
        // 拼接运算符
        $display("{a, b} = %h", {a, b});
        $display("{4{a[7]}, a} = %b", {4{a[7]}, a});
        
        // 条件运算符
        $display("sel == 0 ? a : b = %d", sel == 0 ? a : b);
        
        // 循环与时间
        for (i = 0; i &lt; 4; i = i + 1) begin
            sim_time = $time;
            $display(&quot;Loop iteration %0d at time %0t&quot;, i, sim_time);
        end
        
        $finish;
    end

常见坑与排查

  • 坑 3:整数除法结果意外为 0。例如 10/15=0 是符合 Verilog 整数除法定义的(向零取整)。若需要浮点除法,使用 $itor 或系统函数。
  • 坑 4:取模结果符号错误。Verilog-2001 规定 % 结果符号与被除数相同。例如 -10 % 3 结果为 -1(不是 2)。若需数学模运算,需自行处理。
  • 坑 5:逻辑运算符与位运算符混淆。例如 a && b 将 a 和 b 视为布尔值(非 0 即 1),而 a & b 按位与。对于单比特信号,两者结果相同;但对于多比特,结果不同。

阶段三:仿真监控与验证

使用 $monitor 系统任务持续跟踪变量变化。注意 $monitor 在任意被监控变量变化时自动打印,适用于调试。

// 监控
    initial begin
        $monitor("At time %0t: a=%d, b=%d, sum=%d", $time, a, b, sum);
    end

常见坑与排查

  • 坑 6:$monitor 只触发一次。若变量在仿真中不再变化,$monitor 只打印一次。若需定时打印,使用 $display 配合 #延迟
  • 坑 7:时间显示为 0。因为所有操作在 time 0 的 initial 块内完成,没有延迟。若要观察时间推进,可在赋值之间加入 #10 延迟。

原理与设计说明

Verilog 的数据类型和运算符设计背后有硬件描述语言的独特考量:

  • wire 与 reg 的区分:wire 代表物理连线(连续驱动),reg 代表存储单元(过程赋值)。这一区分源于硬件描述语言需要明确描述组合逻辑(wire + assign)和时序逻辑(reg + always)。在 SystemVerilog 中,logic 类型统一了两者,但理解原始区分有助于阅读遗留代码。
  • 整数除法截断 vs 浮点:硬件中除法器通常只输出整数商和余数。Verilog 的整数除法直接映射到硬件行为,避免隐含的浮点运算(硬件成本高)。若需浮点,需使用 IP 核或手动实现。
  • 位宽与符号的 trade-off:无符号运算(默认)适合地址、计数器;有符号运算(signed 声明或 $signed() 转换)适合算法。错误使用符号会导致比较或移位结果错误。例如,a >> 2 对于有符号负数会补符号位(算术移位),但 Verilog 默认是逻辑移位(补 0),需显式使用 >>>
  • 拼接运算符的效率:拼接 {} 在综合时会生成多路选择器和连线,位宽越大资源越多。对于固定模式(如 {8{1'b0}}),综合器会优化为常数。

验证与结果

以下为使用 Icarus Verilog 12.0 在 Ubuntu 22.04 上的典型输出(部分行已省略重复):

运算符输入 (a=10, b=15)输出说明
+10 + 1525无符号加法
-10 - 15245
标签:
本文原创,作者:二牛学FPGA,其版权均为FPGA线上课程平台|最全栈的FPGA学习平台|FPGA工程师认证培训所有。
如需转载,请注明出处:https://z.shaonianxue.cn/39243.html
二牛学FPGA

二牛学FPGA

初级工程师
这家伙真懒,几个字都不愿写!
79618.18W3.96W3.67W
分享:
成电国芯FPGA赛事课即将上线
从零开始学Verilog:数据类型与运算符详解
从零开始学Verilog:数据类型与运算符详解上一篇
基于FPGA的数字滤波器设计:从选题到上板验证的完整指南下一篇
基于FPGA的数字滤波器设计:从选题到上板验证的完整指南
相关文章
总数:822
FPGA原型验证平台在嵌入式AI SoC软硬件协同开发中的实施指南

FPGA原型验证平台在嵌入式AI SoC软硬件协同开发中的实施指南

在嵌入式AISoC的开发流程中,FPGA原型验证平台是连接算法探索与硬…
技术分享
8天前
0
0
20
0
FPGA是什么?(科普必看)

FPGA是什么?(科普必看)

经常被很多同学问到“FPGA是什么”,作为一名即将来成电少年学接受FPG…
技术分享, 行业资讯
3年前
1
1
973
1
FPGA在边缘AI的落地:从TensorFlow Lite到FPGA推理引擎的部署流程

FPGA在边缘AI的落地:从TensorFlow Lite到FPGA推理引擎的部署流程

本文旨在为工程师提供一套从TensorFlowLite模型到FPGA推…
技术分享
8天前
0
0
27
0
评论表单游客 您好,欢迎参与讨论。
加载中…
评论列表
总数:0
FPGA线上课程平台|最全栈的FPGA学习平台|FPGA工程师认证培训
没有相关内容