Der Graycode wird verwendet, wenn asynchron eine Positionsinformation übertragen werden soll (wie z.B. von einem Drehencoder), denn bei der Gray-Codierung wird bei einem Zählschritt zum nächsten immer nur 1 Bit umgeschaltet. Eine weitere Anwendung für den Graycode ist auch die Übertragung des Füllstands eines Fifos (also eigentlich die Position eines Zeigers im Fifo). Auch hier ist von Vorteil, dass die auswertende Logik höchstens um 1 Adressschritt falsch liegt.
Als Beispiel:
Ist die Zählstand des Fifos auf 7 (= binär 0111) und es wird weitergezählt auf 8 (=binär 1000), dann werden bei binärer Übertragung alle Bits umgeschaltet. Bei asynchroner Abtastung könnte jetzt kurzzeitig jede beliebige Kombination von 0000 bis 1111 auftauchen.
Bei einer Übertragung im Graycode sieht der Schritt von 7 nach 8 so aus: 0100 --> 1100. Hier wird also beim asynchronen Abtasten garantiert keine falsche Information generiert, sondern entweder der alte Wert (7) oder der neue Wert (8) erkannt.
Hier sind ein paar Umwandlungsroutinen, deren Grundlagen auf www.wisc-online.com schön erklärt sind.
library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; entity Gray is Port ( gin : in STD_LOGIC_VECTOR (15 downto 0); bout : out STD_LOGIC_VECTOR (15 downto 0); bin : in STD_LOGIC_VECTOR (15 downto 0); gout : out STD_LOGIC_VECTOR (15 downto 0)); end Gray; architecture Behavioral of Gray is signal gi : unsigned(15 downto 0); signal go : unsigned(15 downto 0); signal bi : unsigned(15 downto 0); signal bo : unsigned(15 downto 0); signal bop2 : unsigned(15 downto 0); begin bi <= unsigned(bin); gi <= unsigned(gin); gout <= std_logic_vector(go); bout <= std_logic_vector(bo); -- alternativ bop2; Gray2BinaryPower2: process (gi) variable temp : unsigned(15 downto 0); begin temp := gi; temp := temp xor shift_right(temp,8); temp := temp xor shift_right(temp,4); temp := temp xor shift_right(temp,2); temp := temp xor shift_right(temp,1); bop2 <= temp; end process; Gray2Binary: process (gi) variable temp : unsigned(gi'left downto 0); begin temp := gi; for i in gi'left-1 downto 0 loop temp(i) := gi(i) xor temp(i+1); end loop; bo <= temp; end process; Binary2Gray: process (bi) begin go <= bi xor '0'&bi(bi'left downto 1); end process; end Behavioral;
Die Berechnung über Gray2BinaryPower2 funktioniert nur mit Busbreiten, die eine 2er Potenz sind, also 4, 8, 16... Zudem muß dann die Anzahl der shift-Operationen angepasst werden. Im obigen Beispiel ist eine Busbreite von 16 Bits verwendet, für einen 8 Bit Graycode entfiele der shift_right(temp,8).
Hier gibt es die VHDL-Datei und die passende Testbench gezippt: GrayBinary.zip
Wer sowas für C braucht, sollte mal dort schauen: Graycode-Umwandlung in C