【问题标题】:Verilog module instantiation reg input outputVerilog 模块实例化 reg 输入输出
【发布时间】:2021-11-27 00:03:34
【问题描述】:

在行为建模中实现 Verilog 代码时,我们使用 reg 作为输出。但是,当我必须使用模块实例化并使用电线连接它时,它会在实现时显示错误。有没有其他方法可以使用模块实例化来连接不同模块实例的输出以实现组合逻辑,因为将先前模型的reg 输出连接到电线是非法的?请注意,我必须应用行为建模,因此不允许使用赋值语句。这是一个将两个半加器连接到一个全加器的示例。

module half_adder(input wire a,b,output reg sum,output reg carry);
always@(a or b)
begin
sum = a^b ;
carry= a & b ;
end 
endmodule

module full_adder(input wire a,b,c,output reg sum,output reg carry);
    wire s1,c1,c2;
    half_adder gate1(a,b,s1,c1);
    half_adder gate2(s1,c,sum,c2);
    always@(a or b or c)
    begin
    carry = c1|c2;
    end
endmodule

错误 (10663):full_adder.v(14) 处的 Verilog HDL 端口连接错误: 输出或输入端口“sum”必须连接到结构网络 表达

【问题讨论】:

    标签: verilog


    【解决方案1】:

    您不应该在full_adder 模块中将sum 声明为reg,因为它不是在程序块(例如always)内分配的。 reg 不是“网络”类型。变化:

    module full_adder(input wire a,b,c,output reg sum,output reg carry);
    

    到:

    module full_adder(input wire a,b,c,output sum,output reg carry);
    

    您的敏感度列表也不正确。变化:

    always@(a or b or c)
    

    到:

    always @*
    

    现在,always 块将在分配的 RHS 上的信号发生变化时触发。

    【讨论】:

      【解决方案2】:

      在标准的旧 verilog 中,reg 无法使用模块连接或连续分配连接到 regSystem verilog 允许。因此,其中一种解决方案可能是切换到系统 verilog。

      对于verilog,在half_adder 端口sum 被声明为一个reg。实例 gate2reg 类型的变量连接到 reg 类型的端口。这是非法的。这种类型的分配只能发生在程序(即总是)块内。实例 gate1 通过将端口连接到电线 s1 绕过了这个问题。

      因此,您可以遵循类似的路径。创建另一个线 s2,如下例所示。

      module full_adder(input wire a,b,c,output reg sum,output reg carry);
          wire s1,c1, s2, c2;
      
          half_adder gate1(a,b,s1,c1);
          half_adder gate2(s1,c,s2,c2); // use s2 here
      
          always@*
             carry = c1|c2;
          
          always @*
             sum = s2; // now you can s2 assign to the 'sum' port
        
          endmodule
      

      另一种方法是将“sum”端口声明为wire。可以使用端口连接或连续分配将寄存器连接到线路。

         module full_adder(input wire a,b,c,
            output sum, // declares it as a wire
             output reg carry);
      
        ... 
          half_adder gate2(s1,c,sum,c2); // now it works this way.
      
      

      顺便说一句,不要使用 @(a,b,c)。它总是容易出错,在你的情况下只是错误。它应该是@(c1,c2)。但是使用@*会好很多。

      【讨论】:

      • 是的,这就是我最初所做的,但我认为我错了。也可以将进位和求和端口放在一个始终块下吗?
      • 是的,您可以将它们放在同一个 always 块下。应该没有逻辑上的差异。在理论上,它会减慢模拟速度,因为 c1、c2 和 s2 中的任何事件都会导致重新评估块中的所有语句。跨多个块拆分可以使代码更具可读性,并有助于避免某些类型的错误,但它需要更多的输入。所以,这取决于你。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-19
      • 1970-01-01
      相关资源
      最近更新 更多