0

我有一个实例化两个模块的顶级模块:

fillRam fillRam1(
  .clk(mclk),
  .ramaddrb(ramaddrb),
  .romaddrb(romaddrb),
  .romoutb(romoutbwire),
  .raminb(raminb));

vga vgainst(
  .ck(mclk),
  .HS(HS),
  .VS(VS),
  .outRed(OutRed),
  .outGreen(OutGreen),
  .outBlue(OutBlue),
  .sw(sw),
  .romouta(romoutawire),
  .ramouta(ramoutawire),
  .romaddra(romaddra),
  .ramaddra(ramaddra));

在这个顶部模块中,我还有两个模块可以连接 RAM 和 ROM。

rom rom_instance (
  .clka(mclk), // input clka
  .addra(romaddrawire), // input [14 : 0] addra
  .douta(romouta), // output [7 : 0] douta
  .clkb(ck), // input clkb
  .addrb(romaddrbwire), // input [14 : 0] addrb
  .doutb(romoutb) // output [7 : 0] doutb
);

我想做的是,从 vga 模块获取 romaddra 值,将其提供给 rom_instance,然后获取 romouta 值并将其返回给 vga 模块。我为此声明了两个变量:

reg  [14:0] romaddra;
wire  [14:0] romaddrawire;
reg [7:0] romouta;
wire [7:0] romoutawire;
assign romaddrawire = romaddra;
assign romoutawire = romouta;

在每个时钟周期中,我从 vga 实例中获取 romaddra 值,将其写入 romaddrawire 并将其提供给 ROM 实例。然后我获取 romouta 值,将其写入 romoutawire 并将其返回给 VGA 实例。

我对其他 rom 端口和 ram 端口也有类似的声明。但在所有这些中,我都得到了这个错误。

ERROR:HDLCompilers:102 - "top.v" line 82 Connection to output port 'romaddra' must be a net lvalue

在 vga verilog 代码中:

output reg [14:0] romaddra;

在 rom verilog 中:

output [7 : 0] douta;

我对整个 reg 和 wire 类型感到非常困惑。如果有人解释这里出了什么问题以及原因,我会很高兴。谢谢。

4

3 回答 3

2

如果您的工作流程允许您使用 SystemVerilog,那么这些都可以logic代替regorwire并且您的问题就会消失。

您可以稍后阅读更多内容,但现在使用wirefor 连接或作为分配语句的一部分。reg当您想在块中定义值时使用always

wire a_wire;
wire b_wire;

example_a_module(
  .a( a_wire )
);

example_b_module( 
  .a( a_wire )
);

assign b_wire = ~a_wire ;

注册

reg a_reg;
reg b_reg;

always @* begin
  a_reg = something_else;
end

always @(posedge clk or negedge rst_n) begin
  if (~rst_n) begin
    b_reg <= 1'b0;
  end
  else begin
    b_reg <= something_else;
  end
end

输出端口可以是任何类型,如果您按名称(看起来像您拥有)而不是按顺序连接它们。

输出 a 为线型:

module example_a_module(
  output a
);
endmodule

这里 b 是一个 10 位的 reg 类型:

module example_c_module(
  output reg [9:0] b
);
endmodule
于 2013-01-04T16:45:12.697 回答
0

您可以将 regs 视为粘性,而电线只是连接两个点(如物理电线)。这并不一定意味着 reg 将始终被合成到触发器中,但 reg 将保持其先前的值,直到分配新的值。另一方面,电线是无记忆的。

一般来说,模块的输出往往是regs,模块之间的互连往往是wire。这是因为生成正确输出的逻辑往往被封装在模块中,因此实例化模块可以只传递输出。当然,在更复杂的系统中,如果模块嵌套在模块中,这将不成立。但是这个概念保持不变——如果你只是想将数据从一个模块传递到另一个模块,请使用电线。如果您需要数据“粘性”,请使用 reg。

说了这么多,制作romaddrareg而不是wire的原因是什么?

于 2013-01-04T15:56:13.637 回答
0

在顶层,只需声明总线并在实例化中使用这些总线。将 reg 和 assign 视为驱动程序,您不需要驱动程序,您需要电线,因此使用“电线”。当您执行“wire a=1”时,它实际上是一个分配,它创建了一个驱动程序。最重要的是,当您想要连接时,请仅使用电线,而不是分配或注册。

wire  [14:0] connector_15;
wire  [8:0] connector_9;

fillRam fillRam1(
  .clk(mclk),
  .ramaddrb(ramaddrb),
  .romaddrb(romaddrb),
  .romoutb(romoutbwire),
  .raminb(raminb));

vga vgainst(
  .ck(mclk),
  .HS(HS),
  .VS(VS),
  .outRed(OutRed),
  .outGreen(OutGreen),
  .outBlue(OutBlue),
  .sw(sw),
  .romouta(connector_9),
  .ramouta(ramoutawire),
  .romaddra(connector_15),
  .ramaddra(ramaddra));

rom rom_instance (
  .clka(mclk), // input clka
  .addra(connector_15), // input [14 : 0] addra
  .douta(connector_9), // output [7 : 0] douta
  .clkb(ck), // input clkb
  .addrb(romaddrbwire), // input [14 : 0] addrb
  .doutb(romoutb) // output [7 : 0] doutb
);
于 2013-01-05T01:13:38.680 回答