Electronic – Frequency divider works only for some divisors (Verilog on Lattice iCEstick FPGA)

fpgaverilog

I'm trying to build a frequency divider on a Lattice iCEstick using Verilog (with yosys, arachne-pnr, and icepack/iceprog):

 module demo(input clk, output LED1, LED2, LED3, LED4, LED5);

   assign LED1 = state;

   // Generate impulse at lower frequency:                                                                                                                          
   wire out_clk;
   reg [31:0] cnt;
   initial cnt <= 0;
   always @(posedge clk) cnt <= cnt >= 6000000 ? 0 : cnt + 1;
   assign out_clk = cnt == 0;

   // On impulse, toggle state:                                                                                                                                     
   reg state;
   initial state <= 0;
   always @(posedge out_clk) state <= ~state;

endmodule

This works as expected, i.e. the LED on the board blinks about once a second (the clock is 12MHz).

However, when 6000000 ('h5B8D80) is replaced with 5000000 ('h4C4B40) the LED simply stays on permanently. Why is that?

Simulating with Icarus shows the expected state changes, no matter what the divisor is.

Here is a table of experiments with more values:

'h5B8D80 blinking
'h5B8D7f permanently on
'h5B8D7e blinking
'h5B8D7d blinking
'h5B8D7c blinking
'h5B8D78 blinking
'h5B8D70 blinking
'h5B8D60 blinking
'h5B8D40 blinking
'h5B8D00 blinking
'h5B8C80 blinking
'h4C4B40 permanently on
'h400000 blinking

Also, for 'h4C4B40 adding the line "assign LED2 = 1;" makes LED1 (!) blink as expected. This is not the case for 'h5B8D7f.

Altogether, the behaviour seems wildly random.

EDIT For the record, when synthesizing the same design with Lattice's iCEcube2 the problem doesn't occur.

Best Answer

If you use long counters (32 bits) with pretty fast clocks (12 MHz) there might be a problem when using counters without a carry look ahead logic. The ripple carry needs so much time from LSB to MSB that the next clock pulse will be at the input before the ripple carry signal have reached the highest bits of the counter. If the ripple carry have to path a very long way from clock input to MSB, there is no time left when all counter bits are stable at the same moment of time. The comparison of the counter state to the maximum value is not possible anymore. A better aproach is to use a down counter loaded the divison factor each time when counting down to zero. It is much easier to detect the zero state when all counter bits are 0, you invert all bits and feed them to a 32 inputs and gate. Instead of using a very long counter, it is better to use a prescaler dividing by 16 and a counter with only 28 instead of 32 bits. By the way, for a maximum counter value of 6E6, you need only 23 bits, not 32. You might use a prescaler dividing by 8 and a 20 bit counter only.