Verilog综合:Reg vs Reg+Wire模块实例化



我是Verilog和FPGA开发的新手,注意到模拟和合成之间存在各种差异。我使用的是带有Quartus II软件的Altera DE1板。

有件事我想不通。我有如下代码来实例化一个模块:

reg [9:0] x0;
initial begin
    x0 = 10'd200;
end
linepro linedrawer1 
     (.CLOCK(I_CLK),
     .RST(reset_drawer),
      .done(drawer_done),
     .x0(x0), 
     .y0(10'd200), 
     .x1(10'd500), 
     .y1(10'd100), 
     .outx(x), 
     .outy(y)); 

正如您所看到的,我正在将一个初始化的reg直接挂接到我的linepro模块的端口。该代码似乎在模拟下工作,但没有正确初始化fpga板上的x0。

为了使此代码正常工作,并正确实例化linepro模块,我进行了以下轻微修改:

reg [9:0] x0reg;
wire [9:0] x0;
assign x0=x0reg;
initial begin
    x0reg = 10'd200;
end
linepro linedrawer1 
     (.CLOCK(I_CLK),
     .RST(reset_drawer),
      .done(drawer_done),
     .x0(x0), 
     .y0(10'd200), 
     .x1(10'd500), 
     .y1(10'd100), 
     .outx(x), 
     .outy(y)); 

在本例中,我将reg分配给一根电线,并将该电线挂接到linepro模块中。

直接使用reg来实例化模块将reg分配给连线并使用该连线来实例化模块之间有什么区别(如果有的话)?一种方法可能有效,而另一种方法则可能无效,原因是什么?

提前感谢您的帮助。

在编写synthetic RTL时,您应该记住实际要实现的逻辑电路是什么。虽然通常初始块是不可合成的,但一些FPGA供应商会允许您指定触发器、锁存器和存储器等存储器元件的通电状态。在这种情况下,x0看起来并不是这些东西中的任何一个——它只是一个应用于linepro模块的一个输入的常量。在这种情况下,您可能只需在端口列表中指定该值,就像您对y0、y1和x1端口所做的那样,这是完全可合成的,而不是使用初始块。

Quartus支持使用";首字母";陈述我怀疑这里的问题是你从来没有真正实现过注册。

我想知道这是否可行:

reg [9:0] x0reg;
initial x0reg = 10'd200;
always @(posedge clk) begin
  x0reg <= x0reg;
end

这应该推断出一个x0reg寄存器,并在配置FPGA时将其初始化为0x200。或者,如果你只是想让reg像电线一样工作:

reg [9:0] x0reg;
always_comb x0_reg = 10'd200;

以上内容应该有效。请注意,always @*在这种情况下不会工作,因为always @*always_comb之间的一个关键区别是always_comb块在模拟开始时被触发,而always @*块只有在输入发生变化时才会被触发(这可能不会在时间零点发生)。(通常,您应该始终使用always_comb,而不要使用always @*。)

最新更新