我是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 @*
。)