I am trying to write a Verilog module that generates a power-on reset signal for a few clock cycles. I am synthesizing using Lattice iCEcube2 + Synplify Pro targeting an iCE40 HX1K on the Nandland Go Board.
If I write the the module like this, it is getting optimized out:
`default_nettype none
module reset_generator #(
parameter COUNT_WIDTH = 2
) (
input wire i_clk,
output wire o_rst
);
reg [COUNT_WIDTH:0] rst_count;
assign o_rst = !rst_count[COUNT_WIDTH];
always @(posedge i_clk) begin
if (o_rst == 1) begin
rst_count <= rst_count + 1;
end
end
endmodule
iCEcube2 outputs this warning:
...
@N:CL189 : reset_generator.v(13) | Register bit rst_count[4] is always 1.
@N:CL159 : reset_generator.v(6) | Input i_clk is unused.
...
@N:BN115 : ball_absolute_mv_vga_top.v(19) | Removing instance reset_gen (in view: work.ball_absolute_mv_vga_top(verilog)) of type view:work.reset_generator_4s(verilog) because it does not drive other instances.
...
And I can verify that the o_rst
signal is indeed never set to 1
. I thought all registers were initialized to 0
, so I'm not sure why it thinks rst_count[4] is always 1
.
However, if I explicitly set rst_count
to 0
, like this:
reg [COUNT_WIDTH:0] rst_count = 0;
Now it no longer is getting optimized out and works as expected, but iCEcube2 shows this warning:
@W:FX1039 : reset_generator.v(13) | User-specified initial value defined for instance reset_gen.rst_count[4:0] is being ignored.
This warning also implies that initial values are 0. So why does the first version get optimized out? And why does adding an initial value that gets ignored change the behavior? Is this just a quirk of iCEcube2 and/or Synplify Pro?
EDIT 1: I'm using a power-on reset because Lattice can only initialize registers to zero, and I'd like some to start off with non-zero values.
The o_rst
of this reset_generator
component is hooked up to another component at a higher level like this:
wire w_reset;
reset_generator #(
.COUNT_WIDTH(4)
) reset_gen (
.i_clk(i_clk),
.o_rst(w_reset)
);
ball_absolute ball_absolute (
.clk(i_clk),
.reset(w_reset),
.vsync(o_vga_vsync),
// ...
);
The reason it does this is because ball_absolute
has a pair of X/Y registers for the ball's position on the screen. I'd like the ball to start in the middle of the screen, not at (0, 0)
. And because Lattice can only initialize registers to 0
, I want to use a power-on reset signal to set X/Y to non-zero values.
The full project is actually up on GitHub.
EDIT 2: I also understand that a PLL Lock signal could be used as a power-on reset, but unfortunately the HX1K does not have any PLLs. The Go Board uses an external crystal for the clock.
0
at power on, and counts up. Onceo_rst
goes low,rst_count
stays at the same non-zero value forever. \$\endgroup\$