Reputation: 55
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
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