FPGA模块设计
在编写verilog时reg和wire有什么区别?什么时间用?
wire是线,与assign绑定使用,组合电路
- 元件例化时的输出必须是wire
reg与begin..end,always,initial绑定使用,时序电路
- 上一级输出,对下一级未知,本质还是wire
详情见 https://blog.csdn.net/u011816009/article/details/104228223
···
一、代码逐行中文翻译
`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已占用写深度(存储有效数据个数)
关键字释义
reg:寄存器类型,测试激励用,只能在initial/always块内部赋值,用来给DUT(FIFO模块)提供输入信号wire:线网类型,模块输出信号,用于接收FIFO内部输出的结果,不能用=直接赋值[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是顶层仿真文件,没有外部端口,信号类型完全区分驱动方和接收方:
-
给FIFO输入的激励信号(clk,rst,we,re,di)→ 必须用 reg
- 原因:激励由
initial/always时钟块主动产生,只有reg类型能在过程块中赋值; - 错误:写成wire会报仿真语法报错,无法生成时钟、复位、写入数据。
- 原因:激励由
-
接收FIFO输出的信号(dout,empty,full,wrusedw)→ 必须用 wire
- 原因:信号由FIFO模块内部驱动,tb只做“被动读取观测”;
- 错误:写成reg会出现多驱动冲突,仿真值全为X未知态。
3. 位宽数值要求([12:0] / [7:0])
- 位宽必须是非负整数,格式
[高位:低位],高位≥低位 - 数据位宽匹配:
- 写入输入di是8位,FIFO内部存储单元、读出dout也必须8位,位宽不匹配会截断/补零,数据出错;
- wrusedw是FIFO深度计数,13位最多计数
2^13=8192个数据,对应FIFO最大深度8192;如果FIFO深度更大,需要加宽位宽。
- 数值取值:所有二进制总线信号只能存0/1,无负数;如需有符号数,用
reg signed [7:0]显式声明。
4. 综合&仿真额外约束
- 综合(下载到FPGA芯片):
- wire仅做连线,不能保存状态;reg会生成实际寄存器触发器,占用FPGA触发器资源;
- 顶层FPGA芯片IO引脚:输入引脚对应input,输出引脚对应output,不能混用reg/wire。
- 仿真仅tb特有:
- 只有reg能产生激励,wire只能观测子模块输出,不能颠倒。
三、最简总结
- TB仿真文件:
主动产生信号(输入激励)→ reg;被动接收模块输出 → wire - 功能设计模块:
外部输入 input;组合输出 output wire;时序寄存器输出 output reg - 位宽:输入输出总线位宽必须一一对应,计数位宽根据FIFO最大深度计算,位宽不足会计数溢出。
浙公网安备 33010602011771号