# Why is this power-on reset generator Verilog module getting optimized out?

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.

• Your design approach is not good. Usually you will have an external reset input to reset/initialize internal registers of your reser generator logic. The logic can generate a multi-cycle synchronous reset from it to reset different modules in the system. Aug 7, 2021 at 8:34
• How does rst_count get reset? Aug 7, 2021 at 10:12
• You could check stackoverflow.com/a/38032139/9609830 - there is a lot of information which might solve your issue. Aug 7, 2021 at 12:15
• @user253751: It doesn't. It starts at at 0 at power on, and counts up. Once o_rst goes low, rst_count stays at the same non-zero value forever. Aug 7, 2021 at 16:05
• @ChristianB.: That link confirms what I am seeing. It says Lattice ignores the initialization value and initializes all FFs to zero. However, it does not explain why Lattice optimizes out the module when the initialization value is missing. Also, HX1K does not have a PLL, so using that to drive reset is not possible. Aug 7, 2021 at 16:10

• Unfortunately, the HX1K does not have any PLLs. It uses an external clock as a crystal. The intent is to initialize some registers to non-zero values since iCEcube does not allow that. I think the right thing to do here is set rst_count = 0` and ignore the warning. Aug 7, 2021 at 23:25