0
\$\begingroup\$

What is the most optimum way of making a mod-counter that is not a power of 2? The counter increment is a variable

My approach on a mod-13 counter for example:

wire [3:0] counter_d ;
reg  [3:0] counter_q ;
wire [4:0] counter_plus_increment ;
wire overflow ;

assign counter_plus_increment = counter_q + increment ; //small increments
assign overflow = counter_plus_increment[4] ;
assign counter_d = overflow ? 4'd3 : counter_plus_increment ;

always @ (posedge clk or negedge resetn) begin
  if (!resetn)
     counter_q <= 4'd3 ;
  else
     counter_q <= counter_d ;
end

do you think this is correct? Any better, more efficient suggestions?

\$\endgroup\$

2 Answers 2

1
\$\begingroup\$

I have written thousands of counters which are not a multiple of two. The procedure is always the same:

if (counter==MAX-1)
   counter <= 0;
else
   counter <= counter + 1;

Plus a reset of course.

Your counter does not start at 0 which is not usable in 99.9% of the cases. Also you solution for mod-13 is not generic usable so in my option there is no 'most efficient' way. (Also in what aspect 'most efficient'? Area? Speed? Power? )

In the industry you can't spend your time on optimizations like that unless you really, really need them. Modulo 13 running at 40GHz: Build a shift register with 13 registers, loop the output to the input. Reset with 13'b0000000000001

A different way to count is us count-down.

if (counter==0)
   counter <= MAX-1;
else
   counter <= counter-1;

This makes that the compare logic becomes a big AND gate instead of AND/OR. But the gain in today's logic is neglectable.

\$\endgroup\$
5
  • 1
    \$\begingroup\$ I know it will count its way out of an illegal state of counter >= MAX eventually, but if it's a 32 bit counter implementing MAX=7, that could take some time. However I guess counter==MAX-1 generates much less logic than counter>=MAX-1, is that right? Or are you assuming the reset will always start it in the legal range? \$\endgroup\$
    – Neil_UK
    Jun 17, 2018 at 11:40
  • \$\begingroup\$ @Neil_UK I always reset to zero. Left it out here so they can choose for a sync. or a-scync reset. I also added more text dealing with "the most optimum". I would never use 32 bit for a MAX=7. I sometimes use a count-down: load with 'MAX-1, count down to zero to reduce the compare logic to AND gate. I'll add the latter to the answer'. \$\endgroup\$
    – Oldfart
    Jun 17, 2018 at 11:47
  • \$\begingroup\$ Both of you are assuming counter increments of 1. However, the increment could be any number...and thats what makes the modulo problem interersting \$\endgroup\$
    – frank_010
    Jun 17, 2018 at 12:37
  • \$\begingroup\$ @frank_010 That's a critical detail that you failed to put in your question. If that's important to you, edit the question accordingly. \$\endgroup\$ Jun 17, 2018 at 12:48
  • \$\begingroup\$ @elliot-alderson In the code I gave for my attempt, I had used a variable to denote increments. But anyways, you are correct it should've been explicitly mentioned and I have made the edit. \$\endgroup\$
    – frank_010
    Jun 17, 2018 at 13:17
0
\$\begingroup\$

While Oldfart's counter is straightforward, this is better in some instances

if (counter==0)
   counter <= MAX-1;
else
   counter <= counter - 1;

Which instances?

Testing == 0 will generally generate less logic than equal to an arbitrary N, and is likely to be faster.

When N is variable, especially on a cycle by cycle basis, the propagation delay from clock to == 0 is independent of the N. This may seem quite subtle, but is vital if the divider is part of a fractional N synthesiser. If the propagation delay is N-dependent, then noise will be downconverted to in-band.

A reset may or may not be necessary. If the counter powers up in the illegal range of counter > MAX-1, then it will eventually count its way down to the legal range. If this time is unacceptable in your application, then a reset is necessary. However, if you're going to test this, then a reset is highly advisable anyway.

\$\endgroup\$
4
  • \$\begingroup\$ That's a bit curious. I would think detecting zero requires one gate input per bit, whereas detecting a specific count on a count-up counter requires only one gate input per '1', so guaranteed to be better. Unless the carry logic can be put to double duty(?). \$\endgroup\$ Jun 17, 2018 at 13:02
  • \$\begingroup\$ @SpehroPefhany, essentially you're suggesting testing cnt and val == val instead of cnt == val? \$\endgroup\$
    – ilkkachu
    Jun 17, 2018 at 13:27
  • \$\begingroup\$ Yes, that's correct. Maybe that's an optimization that has to be done manually. \$\endgroup\$ Jun 17, 2018 at 13:30
  • 1
    \$\begingroup\$ Your answer is wrong. Testing against zero creates the most hardware resources, because you have to test all bit of a counter. It requires a N-bit NOR-gate. The method of @SpehroPefhany reduces the number of tested bits to only the ONEs in the test value. The best implementation regarding testing is to count towards -1 and test the sign-bit. That's only one test bit. It needs an init value of MAX-3 compared to the usual MAX-1. \$\endgroup\$
    – Paebbels
    Jun 17, 2018 at 15:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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