Olesen Larsen
Olesen Larsen

Reputation: 55

Two counters - overflow handling in both directions

I am designing a system where I have 2 18-bit counters and I want to keep track of the difference of these two by subtracting them.

The inputs:

A   : in    unsigned(18 downto 0); -- Counter 1
B   : in    unsigned(18 downto 0); -- Counter 2

The variables I use to convert to signed numbers with an extra bit:

variable As : signed(19 downto 0);
variable Bs : signed(19 downto 0);
variable Ys : signed(19 downto 0);

The subtraction in a process which is performed on every rising edge on the clock:

As := signed('0' & A);             -- The two stored values are converted to signed number signals. 
Bs := signed('0' & B);
Ys := As - Bs;                     -- The difference is calculated.

The sign is important because I need to know which one is leading or lagging the other.

This works as far as the counters are not wrapped around, which leads to my question: How can I handle this in VHDL, when I also need to know the direction of the wraps (the counters can also count down)?

I am already thinking of a solution which includes a lot of big comparators to detect the wraps, but there might be a more "low cost" solution in terms of logic elements?

Note: The counters are modulo 409600, so 409599 will be the max value. They are incremental but do also have an asynchronous load, so in one clock they can vary up to +- 205 counts because the load value to each of the counters is value+205 or value-205.

Thank you for guiding me in the right direction :)

Upvotes: 1

Views: 292

Answers (1)

Morten Zilmer
Morten Zilmer

Reputation: 15924

The below does not handle modulo different from 2 ** N, but may give you some ideas.

For dist as the shorted distance between a and b, and a_ahead if a = b + dist (with wrapping):

  signal a_sub_b : unsigned(a'range);
  signal a_ahead : std_logic;
  signal dist    : unsigned(a'range);
begin
  a_sub_b <= a - b;
  a_ahead <= not a_sub_b(a_sub_b'left);
  dist    <= a_sub_b when (a_ahead = '1') else (to_unsigned(0, a_sub_b'length) - a_sub_b);

Upvotes: 1

Related Questions