FPGA模块设计

在编写verilog时reg和wire有什么区别?什么时间用?

wire是线,与assign绑定使用,组合电路

  • 元件例化时的输出必须是wire

reg与begin..end,always,initial绑定使用,时序电路

一、代码逐行中文翻译

`timescale 1ns/1ps  // 仿真时间单位1纳秒,仿真精度1皮秒
module fifo_simple_tb;  // 模块名:简单FIFO的仿真测试平台
    reg clk, rst, we, re; // 寄存器型变量:时钟、复位、写使能、读使能
    reg [7:0] di;         // 8位寄存器:FIFO写入输入数据
    wire [7:0] dout;      // 线网型变量:FIFO读出输出数据
    wire empty, full;     // 线网型:空标志、满标志
    wire [12:0] wrusedw;  // 13位线网:FIFO已占用写深度(存储有效数据个数)

关键字释义

  1. reg:寄存器类型,测试激励用,只能在initial/always块内部赋值,用来给DUT(FIFO模块)提供输入信号
  2. wire:线网类型,模块输出信号,用于接收FIFO内部输出的结果,不能用=直接赋值
  3. [N:0]:位宽定义,[7:0]代表8位数据总线,取值范围0~255

二、FPGA中输入、输出信号数值类型(reg/wire)使用要求

1. 模块内部设计(你的FIFO主模块 fifo_simple)

(1)模块端口定义规则

  • 外部输入端口(clk/rst/we/re/di):端口直接定义为 input,底层本质是wire,只能读、不能在模块内持续驱动
  • 外部输出端口(dout/empty/full/wrusedw)
    • 组合逻辑输出:output wire xxx
    • 时序寄存器输出:output reg xxx

(2)内部信号区分

  • wire:组合逻辑连线、模块输出连线,只能用 assign 连续赋值
  • reg:时序逻辑寄存器,仅在always@(时钟/复位)时序块内赋值

2. 仿真Testbench(当前tb文件)特殊规则(重点)

Testbench是顶层仿真文件,没有外部端口,信号类型完全区分驱动方和接收方:

  1. 给FIFO输入的激励信号(clk,rst,we,re,di)→ 必须用 reg

    • 原因:激励由initial/always时钟块主动产生,只有reg类型能在过程块中赋值;
    • 错误:写成wire会报仿真语法报错,无法生成时钟、复位、写入数据。
  2. 接收FIFO输出的信号(dout,empty,full,wrusedw)→ 必须用 wire

    • 原因:信号由FIFO模块内部驱动,tb只做“被动读取观测”;
    • 错误:写成reg会出现多驱动冲突,仿真值全为X未知态。

3. 位宽数值要求([12:0] / [7:0]

  1. 位宽必须是非负整数,格式[高位:低位],高位≥低位
  2. 数据位宽匹配:
    • 写入输入di是8位,FIFO内部存储单元、读出dout也必须8位,位宽不匹配会截断/补零,数据出错;
    • wrusedw是FIFO深度计数,13位最多计数2^13=8192个数据,对应FIFO最大深度8192;如果FIFO深度更大,需要加宽位宽。
  3. 数值取值:所有二进制总线信号只能存0/1,无负数;如需有符号数,用reg signed [7:0]显式声明。

4. 综合&仿真额外约束

  1. 综合(下载到FPGA芯片):
    • wire仅做连线,不能保存状态;reg会生成实际寄存器触发器,占用FPGA触发器资源;
    • 顶层FPGA芯片IO引脚:输入引脚对应input,输出引脚对应output,不能混用reg/wire。
  2. 仿真仅tb特有:
    • 只有reg能产生激励,wire只能观测子模块输出,不能颠倒。

三、最简总结

  1. TB仿真文件:
    主动产生信号(输入激励)→ reg;被动接收模块输出 → wire
  2. 功能设计模块:
    外部输入 input;组合输出 output wire;时序寄存器输出 output reg
  3. 位宽:输入输出总线位宽必须一一对应,计数位宽根据FIFO最大深度计算,位宽不足会计数溢出。
posted @ 2026-07-07 14:20  lll_hhh  阅读(2)  评论(0)    收藏  举报