2
\$\begingroup\$

I have a question related to the implementation of counters in an FPGA.

I've read that it is better to implement down counters because when implementing up counters you need one additional comparator and one additional adder, so you would use less resources by making a down counter.

Now, I'm confused, because I would also need one comparator and one subtractor when implementing a down counter. Where is the difference between counting up from zero to a certain number and counting down from a certain number to zero?

Are there any benefits to using down counters rather than up counters?

\$\endgroup\$
5
  • 1
    \$\begingroup\$ It's simpler (logic wise) to establish a zero count condition compared to checking a variable value. \$\endgroup\$
    – Andy aka
    Dec 5 '21 at 18:57
  • \$\begingroup\$ Suppose it's an n-bit counter. You have to compare n number of bits in the count for all zeroes if counting down to zero. Or compare n number of bits in the count for the upper limit, if counting up. No advantages whatsoever in terms of LUTs which implement the comparator. \$\endgroup\$
    – Mitu Raj
    Dec 5 '21 at 20:33
  • \$\begingroup\$ One case where a down counter makes life simpler : when you want the range of the counter (e.g. delay timer) to vary. stackoverflow.com/questions/31138152/… \$\endgroup\$ Dec 5 '21 at 21:00
  • \$\begingroup\$ Take the inverted output of a counter and watch what it does. \$\endgroup\$
    – stark
    Dec 5 '21 at 21:45
  • 1
    \$\begingroup\$ This, for me, is premature optimisation - make the code clear and maintainable, and only worry about it when you need to. The toolchain will be very good at finding and optimising counters. As an aside, For a zero count, you don't actually need a comparator at all - have a think about how you might do it. \$\endgroup\$
    – awjlogan
    Dec 6 '21 at 13:22
6
\$\begingroup\$

I've read that it is better to implement down counter because when implementing up counter you need one additional comparator and one additional adder so you would use less resources by making down counter.

Since FPGAs don't contain counters and comparators, but LUTs, this approach doesn't tell us anything!

However, I think you might be missing some context: the idea is that a downcounter always stops at 0, which is a really easy value to detect. What differs depending on how "far" you want the thing to count is the value that's loaded on reset. And loading a value once every reset is less complicated than comparing all bits of your value against the counter limit.

That being said: I've seen many up-counters in actual FPGA HDL designs. It's really not like a comparator would be expensive – honestly, for example, a series-7 Xilinx FPGA has 6-input LUTs, so for counting to something with up to 18 bits, you can do it with 3 LUTs, all of which you find in a single slice(m). It doesn't get any combinatorially "flatter" in hardware, so honestly, this might be optimizing the wrong thing: such an FPGA detects "18 zero bits" exactly the same way it detects "0x3CDEF", by feeding it into three 6-bit LUTs.

Your reasoning becomes valid for devices with fewer LUT input bits per slice, i.e., when you need to add combinatorial depth to implement the comparison or start consuming a lot of space for the fast comparator. But even in "simpler" FPGAs, the logic blocks (or whatever what are called "slices" by Xilinx are called by others) often have "carry-over" inputs and outputs, to enable exactly that: putting an array of LUTs next to each other, and combining their output in a highly-clockable way. I don't know, but if I had to take a random guess, summers and counters are exactly the reason these are so common.

\$\endgroup\$
6
  • 1
    \$\begingroup\$ The DSP48 can be configured as a counter. \$\endgroup\$ Dec 5 '21 at 19:10
  • \$\begingroup\$ yep, math slices being used for that is another common trick \$\endgroup\$ Dec 5 '21 at 19:11
  • \$\begingroup\$ But wouldn't I also need to compare my current value with zero? \$\endgroup\$ Dec 5 '21 at 23:18
  • \$\begingroup\$ @Modesty1234 If the top-bit of the counter signals carry, you have just passed zero. \$\endgroup\$ Dec 6 '21 at 10:48
  • \$\begingroup\$ I am very rusty in LUT design, but is there some ready 0-comparator per slice? \$\endgroup\$ Dec 6 '21 at 13:55
4
\$\begingroup\$

Yep, I realized this when I wrote a countdown timer block and then copy-pasted it to turn it into a countup timer block. The countup timer needed me to add another register to latch the input for the final count at the beginning of each cycle since it's usually a bad idea to change that mid-count.

But in-use, the one that is most convenient depends on what you are actually doing. Sure, a countdown timer is simpler to make and is probably best if you're actually counting down a known time interval, but if you're trying to measure an unknown time interval then a count-up timer is probably more convenient.

For example, you might measure how long it takes for one revolution of a motor to complete, and then use that time to predict how long it will take for the next revolution to complete (i.e. you assume two consecutive revolutions will take the exact same or almost the exact same time). You might use this to trigger something to happen halfway through a revolution when you only have one sensor pulse per rotation instead of a full encoder.

In that case, not only is it simpler to think about if you use a count-up timer to measure how long a revolution will take, it is also simpler to transfer that measured time from the count-up timer to a countdown timer that keeps track of where you are in the revolution. You can directly transfer the counts over whereas if you used only used one type of timer for both tasks, you would need to perform subtractions from the maximum possible count (integer'high for VHDL) when transferring the counts.

\$\endgroup\$
1
  • 2
    \$\begingroup\$ oh, nice, haven't thought about latching/output registering needs! \$\endgroup\$ Dec 5 '21 at 19:20
2
\$\begingroup\$

Most toolchains can already optimize a counter to the most efficient implementation when they recognize it. If your does, just go for readable code.

Usually, the best option is to shift the value range so that the end position is marked by the carry-out of the adder, which allows you to remove the entire comparator.

With a 4-LUT, the adder requires three, so the fourth input can be used to reset the counter, the table output then expresses the shifted start value; alternatively, if there are synchronous load/clear inputs on the FF that bypass the LUT, these can also be used.

For example, a counter 0-5 and a comparison against 5 would be expressed as three registers that are initialized to 011 (0), then count upwards 100 (1), 101 (2), 110 (3), 111 (4), 000 (5) with the carry-out triggering the reset logic and whatever other action needs to be taken.

\$\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.