我有这个顶层模块实例化两个模块:
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和电线类型非常困惑。如果有人解释这里出了什么问题以及原因,我会很高兴的。感谢。
答案 0 :(得分:2)
如果您的工作流程允许您使用SystemVerilog,那么这些都可以变为logic
而不是reg
或wire
,您的问题就会消失。
您可以稍后阅读更多内容,但现在使用wire
进行连接或作为assign语句的一部分。如果要在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 ;
REGS
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
答案 1 :(得分:0)
您可以将regs视为粘性,而导线只是连接两个点(如物理线)。这并不一定意味着reg将始终合成到触发器,但reg将保持其先前的值,直到分配更新的值。另一方面,电线是无记忆的。
一般来说,模块的输出往往是regs,模块之间的互连往往是连线。这是因为生成适当输出的逻辑往往被封装在模块中,因此实例化模块可以只传递输出。当然,在更复杂的系统中,如果模块嵌套在模块中,这将不适用。但这个概念保持不变 - 如果您只是想将数据从一个模块传递到另一个模块,请使用电线。如果您需要数据“粘性”,请使用reg。
总而言之,使romaddra
成为reg而非电汇的原因是什么?
答案 2 :(得分:0)
在顶层,只需声明总线并在实例化中使用这些总线。想想reg并指定为驱动程序,你不需要驱动程序,你想要一根电线,因此使用'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
);