0
\$\begingroup\$

I am implementing a seconds counter on the Altera DE-1 Educational Board powered by the old Cyclone 2 FPGA. My plan is to make a 'down-clocker' that takes the on-board 50 MHz clock and produces a 1 Hz clock signal (referred to as the 'pulse'), which will then be used to drive the normal counter. The down clocker module is as follows:

module downClockerTest(pulse, clk, reset);
    output reg pulse;
    reg [25:0] count;
    input clk, reset;

    always @(posedge clk or negedge reset) begin
        if(~reset) begin
            count <= 26'h0;
            pulse <= 1'd0;
        end
        else if(count == 26'd49999999)
            count <= 26'd0;
        else begin
            count <= count + 26'h1;
            pulse <= (count > 26'd24999999);
        end
    end
endmodule

With the following RTL: RTL of the down counter with a register at end

Notice that the output 'pulse' is registered. This design works fine; the counter counts as it should. However, if I try and remove the register at end by attempting to drive the 'pulse' output by a single assign statement, the seconds-counter seems to begin jumping by 1 and then 4 in 1 second, indicating 5 pos-edges from the down-clocker, where there should only be one.

The slightly modded down-clocker is as follows:

module downClockerTest(pulse, clk, reset);
    output pulse;
    reg [25:0] count;
    input clk, reset;

    assign pulse = (count > 26'd24999999);  // The counter seems to increment by 1 and then 4 in quick succession (1 second).

    always @(posedge clk or negedge reset) begin
        if(~reset) begin
            count <= 26'h0;
        end
        else if(count == 26'd49999999)
            count <= 26'd0;
        else begin
            count <= count + 26'h1;
        end
    end
endmodule

The changed RTL without the register is: RTL of down-clocker without register

Why is it that the down-clocker only works right when there is a register at the end? Is the register performing some king of 'debouncing'? Does 'bouncing' occur in non-mechanical switching circuits as well? What could be the possible reason from an electronics point of view?

It might be prudent to add that the TimeQuest Timing analysis fails in both cases with critical warning: 'Timing Requirements are not met'. But still, one works where other does not.

I am guessing this bizarre behavior has to do with a race condition caused when a sequence of bits drastically changes its 1's and 0's after an increment. For instance, 110111 becoming 111000 after increment-by-1. Since there is no telling which of the flip-flops - storing the individual bit positions in the sequence - will update their values first, the number (read: bit sequence) might fluctuate for an instant before attaining a stable value. There might exist numbers (bit-sequences) that, while tending towards their stable values, fluctuate through the value being compared (24999999, in our case) and cause the comparator to output Logic-HI. A register at the end would certainly solve this issue. However, all this is guess work, with bases in little experimentation. Any learned opinion would be welcome.

\$\endgroup\$
2
\$\begingroup\$

When you use the async assign for the pulse, you will see the influence of unequal delays in the comparator as glitches in the output. Registering the compare signal hides this, allowing everything to settle down before the next clock edge. (This is guaranteed by the place-route tool if it says the path meets timing.)

If, down the road, you have some reason you need to asynchronous-decode a set of counter outputs, and you want it to be glitch-free, there is an answer: use Gray-code counting. Gray codes guarantee that only one signal at a time changes state, so it avoids the multiple-path race condition that leads to the glitching.

\$\endgroup\$
4
\$\begingroup\$

Yes, there is "bouncing" — but in this context, we call them "glitches". The comparator (count > 26'd24999999) represents a rather large amount of combinatorial logic, and there's no chance that all paths through this logic (and the associated FPGA interconnect) will have exactly the same delay. Therefore, the output pulse will experience one or more glitches before it settles down.

If you are using pulse directly as a clock to other logic, that logic will experience extra clock edges.

\$\endgroup\$
  • \$\begingroup\$ Thanks Dave. Please read the final paragraph of my edited question and see what you think. Also, where could I learn more about these glitches? \$\endgroup\$ – Kraken Jul 15 at 16:34
0
\$\begingroup\$

Comparators are relatively complex logic, with long carry chains.

I'd recommend something like this:

module downClockerTest(pulse, clk, reset);
    output reg pulse;
    reg [24:0] count;
    input clk, reset;

    always @(posedge clk or negedge reset) begin
        if(~reset) begin
            count <= 25'h0;
            pulse <= 1'd0;
        end
        else if(count == 25'd24999999) begin
            count <= 25'd0;
            pulse <= ~pulse;
        end
        else begin
            count <= count + 1;
        end
    end
endmodule

Instead of counting to 50,000,000 and using a comparator to set the pulse value, I just count to 25,000,000 and toggle pulse whenever I reach full count.

\$\endgroup\$
  • \$\begingroup\$ This certainly is a better (and my very initial) solution. However, the intent of my question is to figure out 'why' the problem is occurring, not what the better solution is. \$\endgroup\$ – Kraken Jul 15 at 16:32
  • 1
    \$\begingroup\$ @Kraken, I think Dave gave a very good answer to that part of the question. \$\endgroup\$ – The Photon Jul 15 at 16:47

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.