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.
EDIT 3: Clarification on the PLL. Some HX1Ks do have a PLL, but not all of them. From the Notes on page 8 of the iCE40 LP/HX Family Data Sheet: "No PLL available on the 16 WLCSP, 36 ucBGA, 81 csBGA, 84 QFN, and 100 VQFP packages". The Go Board has a 100 VQFP package, so it does not have a PLL.
0at power on, and counts up. Onceo_rstgoes low,rst_countstays at the same non-zero value forever. \$\endgroup\$