PDA

View Full Version : gray counter and compare value


Olaf
04-28-2007, 03:55 PM
Hi,

I'm using the gray counter at comp.lang.vhdl FAQ 4.2.29, extended with a
reset.

Anyway, I would like use it as a water level counter. Therefore I need
to compare the counter value against one top value to hit an action. The
top value is in hex/bin format.

Here the question: Does exist a VHDL convert function to en-/decode the
hex into gray code? How does it look? Since the mentioned Gray Code
Counter Model has a generic size, it should be also generic.

I would know only a non-generic solution using a LUT ROM.

Thanks
Olaf

KJ
04-28-2007, 09:00 PM
"Olaf" <[email protected]> wrote in message news:[email protected]...
> Hi,
>
> I'm using the gray counter at comp.lang.vhdl FAQ 4.2.29, extended with a
> reset.
>
> Anyway, I would like use it as a water level counter. Therefore I need
> to compare the counter value against one top value to hit an action. The
> top value is in hex/bin format.
>
> Here the question: Does exist a VHDL convert function to en-/decode the
> hex into gray code? How does it look? Since the mentioned Gray Code
> Counter Model has a generic size, it should be also generic.
>
> I would know only a non-generic solution using a LUT ROM.
>
Since this 'top value' is a constant it can be computed using a VHDL
function. What you need to do is create a function (calling it
'Compute_Top' for purposes of this discussion) where you pass it a parameter
that is the number of bits in your gray code counter. This function would
return the value that you would then use to compare against. Below is some
pseudo code to use as a general guide to follow.

entity My_Entity generic(nBits: natural) is
-- list your ports
end My_Entity;

architecture RTL of My_Entity is
function Compute_Top(nBits: natural) return std_ulogic_vector is
variable Gray_Code_Value: std_ulogic_vector(nBits - 1 downto 0) :=
(others => '0'); -- Assuming you want to start here
begin
for i in 0 to 2**nBits - 1 loop
Gray_Code_Value := -- Put your code to update to the next gray
code value here
end loop;
return(std_ulogic_vector(Gray_Code_Value));
end function Compute_Top;

constant TOP_VALUE: std_ulogic_vector(nBits - 1 downto 0) :=
Compute_Top(nBits);
signal Gray_Code_Counter: std_ulogic_vector(nBits - 1 downto 0);
begin
.....
if (Gray_Code_Counter = TOP_VALUE) then
-- do whatever it is you want to do here when the gray code counter
reaches max
.....

The above code is fairly straightforward, but when 'nBits' get large, you
might notice that it takes quite a while for the top value to get computed
(even though it is only done once). A faster way to compute the 'top' value
is to run the gray code counter logic in reverse. That way instead of
looping through 2**n - 1 times to get your constant, you simply run once
through computing what the previous gray code would be which is the code
that would be preceeding "0" which would be the 'top' value.

Kevin Jennings

Mirko Liss
04-28-2007, 09:41 PM
Olaf:
> Here the question: Does exist a VHDL convert function to en-/decode the
> hex into gray code? How does it look? Since the mentioned Gray Code
> Counter Model has a generic size, it should be also generic.


The gray code of the number x is:

x XOR (x shift_right 1)


You can get the inverse gray code by applying this formula repeatedly.
With 64bit words, you need to apply it 63 times. That's simple and
easily adjustable to another word size, but rather slow.

This version of the inverse gray code of 64 bit code works somewhat
faster:

x := x XOR (x shift_right 1);
x := x XOR (x shift_right 2);
x := x XOR (x shift_right 4);
x := x XOR (x shift_right 8);
x := x XOR (x shift_right 16);
x := x XOR (x shift_right 32);

These statements can be reordered as you like.

Olaf
04-29-2007, 05:13 PM
Hi,

thanks for your replay. Would this function do the job (untested)?

function hex2gray (signal hex : in std_logic_vector) return
std_logic_vector is
constant WIDTH : integer := hex'length;
variable x : unsigned(hex'range) := unsigned(hex);
begin

assert (WIDTH > 1) and (WIDTH < integer'high)
report "Invalid Bit Size"
severity failure;

for n in 0 to WIDTH-1 loop
x := x XOR shift_right(x, 2**n);
end loop;

return std_logic_vector(x);

end function hex2gray;

Thanks
Olaf

Ahmed Samieh
04-30-2007, 04:03 PM
On Apr 29, 7:13 pm, Olaf <[email protected]> wrote:
> Hi,
>
> thanks for your replay. Would this function do the job (untested)?
>
> function hex2gray (signal hex : in std_logic_vector) return
> std_logic_vector is
> constant WIDTH : integer := hex'length;
> variable x : unsigned(hex'range) := unsigned(hex);
> begin
>
> assert (WIDTH > 1) and (WIDTH < integer'high)
> report "Invalid Bit Size"
> severity failure;
>
> for n in 0 to WIDTH-1 loop
> x := x XOR shift_right(x, 2**n);
> end loop;
>
> return std_logic_vector(x);
>
> end function hex2gray;
>
> Thanks
> Olaf

this function will do it (tested) :

FUNCTION hex2gray(hex : std_logic_vector)
RETURN std_logic_vector IS
VARIABLE x : unsigned(hex'RANGE) := unsigned(hex);
BEGIN
x := x XOR shift_right(x,1);
RETURN std_logic_vector(x);
END FUNCTION hex2gray;

look at http://en.wikipedia.org/wiki/Gray_code

Ahmed Samieh