R
rickman
Guest
I was reading up on Gray codes and figured out a fairly simple algorithm
for counting up or down with Gray codes directly rather than using a
binary counter which is converted to Gray code. It has not been
extensively tested. I don't think it will work for vectors declared
with a "to" range rather than a "downto" range. I should have used
'left and 'right instead of 'high and 'low, but I don't know how to
construct a loop that goes in either direction. I'll need to dig around
to see how that might be done.
I got the idea from a verbal description of a Gray code that defined the
bit to change as the least significant bit that gives even parity with
all the higher bits. They didn't say it just like that, but once I
thought about it I realized that was what they should have said.
Counting down is the same rule, but odd parity. I didn't synthesize it
to see how complex the logic is, but I don't think it should be too bad.
Here is the code. Any suggestions are welcome.
Function CalcGray (cntr : unsigned; UpDwn : std_logic)
return unsigned is
variable CntrHigh : natural := cntr'high;
variable CntrLow : natural := cntr'low;
variable Result : unsigned (cntr'range) := cntr;
variable ParityWord : unsigned (CntrHigh downto CntrLow)
:= (others => '0');
begin
ParityWord(CntrHigh) := Result(CntrHigh);
for i in CntrHigh-1 downto CntrLow loop
ParityWord(i) := ParityWord(i+1) xor Result(i);
end loop;
for i in CntrLow to CntrHigh loop
if ((UpDwn = not ParityWord(i)) or (i = CntrHigh)) then
Result(i) := not Result(i);
exit;
end if;
end loop;
return Result;
end CalcGray;
Function NextGray (cntr : unsigned) return unsigned is
begin
return CalcGray(cntr, '1');
end NextGray;
Function PrevGray (cntr : unsigned) return unsigned is
begin
return CalcGray(cntr, '0');
end PrevGray;
--
Rick C
for counting up or down with Gray codes directly rather than using a
binary counter which is converted to Gray code. It has not been
extensively tested. I don't think it will work for vectors declared
with a "to" range rather than a "downto" range. I should have used
'left and 'right instead of 'high and 'low, but I don't know how to
construct a loop that goes in either direction. I'll need to dig around
to see how that might be done.
I got the idea from a verbal description of a Gray code that defined the
bit to change as the least significant bit that gives even parity with
all the higher bits. They didn't say it just like that, but once I
thought about it I realized that was what they should have said.
Counting down is the same rule, but odd parity. I didn't synthesize it
to see how complex the logic is, but I don't think it should be too bad.
Here is the code. Any suggestions are welcome.
Function CalcGray (cntr : unsigned; UpDwn : std_logic)
return unsigned is
variable CntrHigh : natural := cntr'high;
variable CntrLow : natural := cntr'low;
variable Result : unsigned (cntr'range) := cntr;
variable ParityWord : unsigned (CntrHigh downto CntrLow)
:= (others => '0');
begin
ParityWord(CntrHigh) := Result(CntrHigh);
for i in CntrHigh-1 downto CntrLow loop
ParityWord(i) := ParityWord(i+1) xor Result(i);
end loop;
for i in CntrLow to CntrHigh loop
if ((UpDwn = not ParityWord(i)) or (i = CntrHigh)) then
Result(i) := not Result(i);
exit;
end if;
end loop;
return Result;
end CalcGray;
Function NextGray (cntr : unsigned) return unsigned is
begin
return CalcGray(cntr, '1');
end NextGray;
Function PrevGray (cntr : unsigned) return unsigned is
begin
return CalcGray(cntr, '0');
end PrevGray;
--
Rick C