【问题标题】:How to 'assign' a value to an output reg in Verilog?如何在 Verilog 中将值“分配”给输出 reg?
【发布时间】:2009-11-27 16:52:53
【问题描述】:

(在此处插入非常基本的问题免责声明)

更具体地说,我有以下声明:

output reg icache_ram_rw

在代码的某些地方,我需要将零值放在此 reg 中。以下是我尝试过的方法和结果:

assign icache_ram_rw = 1'b0;
( declarative lvalue or port sink reg icache_ram_rw must be a wire )

icache_ram_rw <= 1'b0;
( instance gate/name for type "icache_ram_rw" expected - <= read )

到底我该怎么做?!

【问题讨论】:

    标签: verilog


    【解决方案1】:

    从输出声明中删除“reg”,代码应该可以工作(默认为线输出类型)。

    在 Verilog 中,大多数自学成才或学得不好的工程师发现有两件事难以理解:(1) 阻塞 -vs- 非阻塞分配(请参阅我关于此主题的论文:http://www.sunburst-design.com/papers/CummingsSNUG2000SJ_NBA.pdf)和 (2) reg -vs-电线。让我们现在就理清后一个话题。

    左侧 (LHS) 上的任何内容或过程赋值(always、initial、task、function)都必须声明为变量类型(通常是 reg)。该语言中的其他所有内容都是网(通常是电线)。没有例外。真的就是这么简单。我不知道有哪本 Verilog 书能这么简单地说明这一点。

    这是怎么发生的?我问 Verilog 语言的好朋友和发明者 Phil Moorby,“为什么要注册??” Phil 告诉我,当他发明 Verilog 时,还没有综合工具,他认为从 always 块中出来的所有东西都将是一个寄存器。他错了,现在我们被这个“reg”关键字困住了。

    十多年来,我一直试图在 Veirlog 和 SystemVerilog 委员会中改变这一点。我想将所有内容声明为线,第一次使用将确定“线”的行为是否像 reg(来自程序块的第一个分配和最后一个分配获胜)或行为像一个线(第一个分配来自驱动源,例如模块输出或连续分配和多个驱动程序在今天的 Verilog 中得到解决)并且对同一信号进行程序分配和驱动程序分配是非法的。唉,我在委员会中没有足够的票数来成功通过这个提案。

    这是我在自己的代码中最常犯的错误。只需习惯错误消息,例如“非法 LHS 分配”或“非法分配电线”。它们的意思是一样的,你忘了声明你的 regs。

    问候 - Cliff Cummings - Verilog 和 SystemVerilog 大师

    【讨论】:

      【解决方案2】:

      assign 语句用于驱动wires。

      如果您将某些东西声明为reg,那么您必须在过程中为其赋值(alwaysinitial 块)。最佳做法是仅在同一 always 块中设置 regs 的值。例如:

      always @( * ) begin // combo logic block
         if( some_condition ) begin
            icache_ram_rw = 1'b0;
         end else begin
            icache_ram_rw = something_else;
       end
      

      regs 和 wires 之间存在重要区别,您应该仔细阅读。

      我有一种感觉,如果您正在驱动 RAM 信号,您将需要一些时钟逻辑。在这种情况下,您需要如下所示的代码:

      // some parameter definitions to make logic 'read' clearer.
      localparam READ = 1'b0; 
      localparam WRITE = 1'b1;
      
      // standard clocked logic 'template' that synthesis tools recognise.
      always @( posedge clk or negedge resetb )
        if( !resetb ) begin  // asynchronous active low reset
           icache_ram_rw <= READ;
        end else if( some_enable_condition ) begin
           icache_ram_rw <= WRITE;
        end else begin
           icache_ram_rw <= READ;
        end
      

      【讨论】:

      • 感谢您的完整回答!时钟逻辑确实存在于分配中,为了简单起见,我在这里省略了它(事实证明,添加它可能会更好)=D
      【解决方案3】:

      请注意,您还可以在声明 reg 时为其分配初始值,如下所示:

      output reg icache_ram_rw = 1'b0;

      这将确保它从模拟中的零值开始。对于综合,您的结果将取决于综合工具和目标技术(对于 FPGA,您通常可以为硬件分配一个初始值;对于 ASIC,情况并非如此)。

      【讨论】:

        【解决方案4】:
        1. 问题在于,综合后的分配语句将创建端口/引脚,这就是它需要电线作为输出的原因。
        2. 您已经创建了名为 icache_ram_rw 的 reg,现在一个寄存器与 pin right ....
        3. 所以要分配一个寄存器,您需要使用正确的 verilog 格式
        4. verilog 允许使用 always 语句实现相同的功能,创建一个 DFF 并且该 DFF 的输入引脚将是您的 icache_ram_rw ,格式已由其他人提供。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-04-04
          • 1970-01-01
          • 1970-01-01
          • 2019-11-11
          • 2023-03-26
          • 2021-11-27
          相关资源
          最近更新 更多