少于 1 分钟阅读 次阅读

在 FPGA 设计中(主要使用 Verilog/VHDL 等 HDL),regwire是两种最基础的数据类型,它们的核心区别在于语义、赋值方式和硬件实现

特性 wire (线网) reg (寄存器)
本质 连线 (物理导线) 存储单元 (触发器或锁存器) 或 连线
语义 表示电路模块间的物理连接 表示一个存储数据的变量
驱动源 必须被连续驱动 (赋值源) 可以在特定时刻被赋值 (过程块内)
赋值方式 只能用于连续赋值 (assign) 或模块端口连接 只能用于过程赋值 (always, initial)
值保持 无记忆性:值随驱动源实时变化 有记忆性:值保持到下次赋值 (除非在组合逻辑中)
硬件对应 导线、门电路输出 触发器(FF)、锁存器(Latch)、组合逻辑内部节点
默认值 z (高阻态) x (不定态)
典型应用场景 模块间连接、组合逻辑输出、门电路输入/输出 时序逻辑状态存储、过程块中的临时变量、组合逻辑输出

详细解释

  1. wire (线网):

    • 本质: 代表硬件中的物理连接线。它用于连接不同的硬件元件(如门、模块实例、reg变量等)。
    • 驱动: wire 必须有一个持续的驱动源。这个驱动源可以是:
      • 一个模块的输出端口。
      • 一个assign连续赋值语句。
      • 另一个wirereg的输出(在连接时)。
    • 行为: wire的值由其驱动源实时决定。驱动源的值一改变,wire的值立即跟着改变。它没有记忆能力
    • 硬件实现: 综合后通常对应 FPGA 内部的布线资源(导线)或查找表(LUT) 的输出。
    • 使用场景:
      • 连接模块的输入输出端口。
      • 在组合逻辑中,用于连接各个逻辑门或作为assign语句的目标。
      • 作为子模块实例化时的连线。
  2. reg (寄存器):

    • 本质: 代表一个存储数据的变量。这个名字容易引起误解,因为它不一定综合成物理寄存器(触发器或锁存器)。
    • 驱动: reg只能在过程块 (always, initial) 内部被赋值。过程块中的赋值是过程赋值
    • 行为:
      • 在时序逻辑 (always @(posedge clk) 中: reg通常综合成触发器(Flip-Flop)。它只在时钟边沿采样输入,并在下一个边沿前保持其值,具有记忆性
      • 在组合逻辑 (always @(*)) 中: reg综合成存储元件,而是综合成组合逻辑电路的内部节点或输出。它的值由输入决定,没有记忆性(行为类似wire,但语法要求用reg)。
      • initial块中: 主要用于仿真初始化。
    • 硬件实现:
      • 在时序逻辑中:主要对应触发器(FF)
      • 在组合逻辑中:对应查找表(LUT) 的输出或内部节点(本质是连线)。
      • 如果代码描述不完善(如always块中未给所有分支赋值),可能综合出锁存器(Latch)(通常应避免)。
    • 使用场景:
      • always @(posedge clk)块中定义计数器、状态机状态等需要记忆的变量(综合成 FF)。
      • always @(*)块中定义组合逻辑的输出或中间变量(综合成组合逻辑)。
      • 在仿真中用于存储测试激励或结果。

关键区别总结

  1. 赋值方式: 这是最根本的语法区别。
    • wire 只能在 assign 语句或模块端口连接中被赋值(连续赋值)。
    • reg 只能在 alwaysinitial 块中被赋值(过程赋值)。
  2. 语义/行为:
    • wire 表示连接,值由驱动源连续驱动无记忆性
    • reg 表示存储单元(或组合逻辑节点),其值在过程块中被赋值,在时序逻辑中具有记忆性(保持到下次赋值)。
  3. 硬件映射:
    • wire 最终映射到连线或组合逻辑输出。
    • reg 的映射取决于上下文:
      • 在边沿触发的always块中 -> 触发器(FF)
      • 在电平敏感的always块中且描述不完整 -> 锁存器(Latch) (通常不希望)。
      • 在组合逻辑always @(*)块中 -> 组合逻辑(本质也是连线或 LUT 输出)。

简单记忆与使用建议

  • 连线就用 wire 当你要连接两个东西(模块端口、assign语句的左右两边)时,用wire
  • 过程赋值就用 reg 当你要在alwaysinitial块里写赋值语句 (=, <=) 时,被赋值的变量必须声明为reg
  • 组合逻辑输出: 即使是一个纯组合逻辑的输出(没有记忆性),只要它是在always @(*)块中被赋值的,也必须声明为reg。这是 Verilog 语法规定,不代表它真的是寄存器。
  • 时序逻辑状态: 需要在时钟边沿之间保持的值,必须在边沿触发的always块中声明为reg,它会被综合成触发器。

标签:

分类:

更新时间:

留下评论