3
\$\begingroup\$

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.

\$\endgroup\$
  • 1
    \$\begingroup\$ Since nobody's answered, I'll suggest a troubleshooting check: What happens if you make the limit 4,194,304? \$\endgroup\$ – The Photon Jul 31 '16 at 16:17
  • \$\begingroup\$ I would try different divider values between 6E6 and 5E6. The hex values are 5B8D80 and 4C4B40. What about experimenting with hex values instead of decimal? Try smaller changes, 6E6 - 1 and -2 -4 -8 -128 -256. Use 16 bit values instead of 32 bit and cascade two dividers with the values of 3000 and 2000. The product is 6E6. Next try with 2500 and 2000. Define and output with the signal of the first divider and connect to an oscillograph. \$\endgroup\$ – Uwe Aug 2 '16 at 10:21
  • \$\begingroup\$ I added a table to the question. For both 3000*2000 and 2500*2000 cascades LED1 stays on permanently. Unfortunately I don't have an oscillograph. \$\endgroup\$ – Maxim Aug 2 '16 at 15:30
1
\$\begingroup\$

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.

\$\endgroup\$
  • \$\begingroup\$ Thanks. While your suggestion (counting downwards) works, the 'icetime' utility (clifford.at/icestorm) reports 131.50MHz for the circuit in question. The chip's clock has only 12Mhz, so is it not supposed to work? Shouldn't a timing analysis tool account for the phenomenon you describe? \$\endgroup\$ – Maxim Aug 4 '16 at 13:36
1
\$\begingroup\$

My guess is your synthesizer is treating assign out_clk = cnt == 0; as pure combinational logic. Since the logic and routing is different for every max clock value, this could skew the parasitic delay. Thereby the out_clk pulse could be too short or unstable to trigger a change state.

A general guild-line is to keep a derived clocks clean and glitch free.

One option is to make out_clk a flop.

initial begin
  cnt <= 0;
  state <= 0;
  out_clk <= 0;
end
always @(posedge clk) begin
  cnt <= cnt >= 6000000 ? 0 : cnt + 1;
  out_clk <= cnt == 0;
end
always @(posedge out_clk) begin
  state <= ~state;
end

Or since you don't really need a derived clock; just use one always block:

initial begin
  cnt <= 0;
  state <= 0;
end
always @(posedge clk) begin
  cnt <= cnt >= 6000000 ? 0 : cnt + 1;
  if (cnt == 0) begin 
    state <= ~state;
  end
end

As a final note, check your synthesis log file for warnings. Sometimes timing issues are reported as warnings and not errors. Always try to resolve warnings, and if you cannot, understand what they are.

\$\endgroup\$
  • \$\begingroup\$ Thanks! The suggestion "works" in the sense that it indeed manages to produce a blinking LED for the problematic values. However, as I'm quite the beginner with FPGAs, I don't fully understand the reasons behind it. If possible, a pointer to an explanation with more context would be much appreciated. (In particular I find it confusing that the synthesizer doesn't report any warnings. Is this a limitation of the language or the synthesizer? Would it be different with VHDL?) \$\endgroup\$ – Maxim Aug 2 '16 at 19:39
  • \$\begingroup\$ Synthesizer try to make the gate equivalent of your RTL (from Verilog, VHDL, or other HDL); it does not have much knowledge on deign quality. A lot of textbooks on digital design and focus more on minimum number of gates/transistors than reliability. For example many textbooks teach daisy-chain counters, which is optimal for area/gate-count, but at high-speeds is glitch because the clk2q delay cascades. There are several Verilog/SystemVerilog resources listed on my profile. I think this paper somewhat explains your issue \$\endgroup\$ – Greg Aug 3 '16 at 0:00
  • \$\begingroup\$ Interesting. I noticed that replacing "cnt == 0" with "cnt <= 1" also solves the issue, which appears to be consistent with your explanations. But is reliability really something that needs to be determined by experiment? How is this practical for larger designs? It seems surprising that it can go wrong even for such a small circuit. \$\endgroup\$ – Maxim Aug 3 '16 at 5:13
  • \$\begingroup\$ @Maxim, keep in mind that the Free toolchain is fairly new and experimental. The manufacturer's tools do static timing analysis using data collected from production devices. \$\endgroup\$ – mng Aug 4 '16 at 4:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.