2
\$\begingroup\$

My application has a bog-standard count-until-a-certain-number-then-reset-the-counter section. My experienced friend tells me that when using actual chips, it's common to increment the counter on the rising edge of the clock and reset the counter on the falling edge. That way the designer has a lot of time to do what needs to be done before the next clock arrives.

But he's never used a CPLD and I wonder if this changes the rules. Or if his information is technically sensible but not practically needed.

My design has something like

always @(posedge clock) begin (increment the clock) end
always @(negedge clock) begin (reset the counter conditionally) end

I'm not trained at all in electrical engineering, I just read and dabble. But I can't let it rest when I don't feel I have a certain (n00b-level) understanding of what's going on.

I just read an example from a university course where the instructor didn't care about when the counter was reset. His design was something like:

always @(posedge clock) begin
    counter = counter + 1;
    if (counter == some_number) counter = 0;
    end

This leads me to believe I'm over-engineering, the instructor is instructing not building an industrial app, or the synthesis process handles such things.

Of course I could try it in the simulator or actually plop it into the CPLD. Eventually this is going to be driving a powerful machine and it's got to work every time. I can't have an edge case where the machine misbehaves.

EDIT - more context. While it may not matter with respect to the answer, I am counting pulses generated by an encoder attached to a rotating spindle. I have to count every one of them, and I can't lose any.

EDIT 2 - example of a loop that increments a counter, then on some condition, changes it.

module slow_count(
    input clk,
    output reg [3:0] count
    );

    reg[19:0] snooze = 0;
    always @(posedge clk) begin
        snooze = snooze + 1;            // Set the counter
        if (snooze == 1000000) begin
            snooze = 0;             // And change it here
            count = count + 1;
            if (count == 10) count = 0;
            end
        end

endmodule
\$\endgroup\$
  • \$\begingroup\$ Incidentally, I think that the code you propose in your second block is not likely to synthesize to what you want...Most synthesis tools won't respect the difference between blocking and non-blocking assignment, they'll just expect you to code so that it doesn't matter. See my answer for how to structure this code so that your synthesis tool will do what you want. \$\endgroup\$ – The Photon Sep 22 '12 at 16:40
  • \$\begingroup\$ 2nd block isn't mine, I have not tried it. Why would it not synthesize, however? \$\endgroup\$ – Tony Ennis Sep 22 '12 at 21:05
  • \$\begingroup\$ let's say some_number is 27. Your instructors codes says, on each clock cycle, first increment the counter, then check if it's equal to 27, and change it, again, if it is. But there's no way to do that in CPLD hardware. What you need to do is check if the old value is 26, and use that to choose whether to make the new value be 0 or counter+1. \$\endgroup\$ – The Photon Sep 22 '12 at 23:55
  • \$\begingroup\$ I was under the impression that using the '=' assignment operator instead of '<=' assignment operator would make that happen. I did have oddities when I used the '<=' inappropriately. \$\endgroup\$ – Tony Ennis Sep 23 '12 at 1:10
  • \$\begingroup\$ In simulation, '=' and '<=' produce different behavior. But in the actual CPLD there's not '=' and '<=' operators, there's actual flipflops, with certain behavior. When you synthesize your design, the tool will try to get as close as possible to what the HDL describes. But in many cases, it can't get a perfect match, so you'll get a physical device that doesn't behave like the HDL simulation. When we talk about designing synthesizable Verilog, we mean writing only code that can be reproduced in the physical hardware. \$\endgroup\$ – The Photon Sep 23 '12 at 22:48
3
\$\begingroup\$

It sounds like you don't have an external reset signal to respond to, you just want to count to some number then go to zero as the next step. You could consider this a mod n counter, where n is one more than the maximum count in your counter.

So I'm not sure what you mean about "losing a signal" while doing the reset. If you had a 3-digit decimal counter and it rolled over from 999 to 000, you wouldn't consider it as "losing a signal", it would just be counting to the next value in mod-1000 arithmetic.

So if you do

always @(posedge clock) begin
    if (counter == some_number) begin
         counter <= 0;
    end
    else begin
        counter <= counter + 1;
    end
end

You'll have a counter that counts continuously in mod-some_number+1 arithmetic. Alternately you could say it counts to some_number, then resets to zero without ever "losing" a clock pulse.

If some_number+1 happens to be a power of 2, you don't even need the reset condition in your code. For example, for a mod-16 counter, you can just use a 4-bit counter, and the synthesized logic will count continuously and repeatedly from 0 to 15.

\$\endgroup\$
  • \$\begingroup\$ The reference to 'losing a signal' was in reference to @matt young's idea of using the next positive transition to reset the counter. I can't do that - that's signal information. The reset needs to occur before it arrives. \$\endgroup\$ – Tony Ennis Sep 22 '12 at 21:02
  • \$\begingroup\$ Yes, it is a mod-n counter. It's working fine. Sadly, the modulus isn't a power of two. \$\endgroup\$ – Tony Ennis Sep 22 '12 at 21:03
2
\$\begingroup\$

If there's no reason to do otherwise, I always clear the counter on the next positive edge, assuming the counter is positive edge triggered. This keeps the time at each value constant, which may be important if the counter shares a clock signal with and controls other blocks, and especially frequency dividers. As always, synchronous operations are your friend. Your university example is good practice in my opinion.

\$\endgroup\$
  • \$\begingroup\$ I can't lose any signals by using the a rising edge to reset the counter. I added a little context to the original post. \$\endgroup\$ – Tony Ennis Sep 22 '12 at 16:19
  • \$\begingroup\$ @TonyEnnis - If you are not having a separate signal to cause the reset of the counter then using a clock event to count the transition state is not losing a clock. \$\endgroup\$ – Michael Karas Sep 22 '12 at 17:04
1
\$\begingroup\$

If you don't need to reset the counter asynchronously, then the counter should simply determine on each clock cycle what the next clock value should be, so everything runs off the same clock edge. If you do need to reset the counter asynchronously, there are a variety of approaches which may be used based upon what is known about the timing of the reset input (most notably, whether there is any possibility that the reset signal might be released near a clock edge, and/or any possibility of "runt" reset pulse).

The most robust way to have a counter reset asynchronously is to have a sequence of three flip flops which are operated by the main clock, and have the first one by asynchronously reset by the master reset input. The data input to the first flop should be high when its output is high and either the second is high or the third is low, or when all three flops are low. The counter itself should not be asynchronously reset, but should instead load itself with an initial value whenever the third flip flop is low. The outputs from the counter should be asynchronously "AND"ed with the "and" of the three flip flops before driving downstream circuitry.

Using such an approach, any proper-length reset will cause the outputs to go low asynchronously. A runt reset pulse may cause the count outputs of the overall circuit to go momentarily unstable, but they will either reset cleanly or will within two cycles revert to the original count sequence. As described, there will be few cycles delay between releasing reset and observing the first count; such a delay may be eliminated by adding some extra logic between the counter and the circuits fed thereby, and by having the counter itself loaded with a non-zero value. Effectively, the first few counts following a reset would be handled by the flip flops rather than the counter. A runt reset pulse may cause those first few counts to appear oddly, but counts after them would be fine.

\$\endgroup\$

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.