Sollen Werte z.B. an ein Display oder über eine serielle Schnittstelle ausgegeben werden, dann kann eine hexadezimale Darstellung dieser Werte vorteilhaft sein. Bei der Hexadezimaldarstellung wird nämlich die Position der einzelnen Bits nicht verändert, byteorientierte Werte bleiben in Zweiergruppen beisammen und brauchen immer nur 2 ASCII Zeichen zur Darstellung.
Wenn man einen Binärwert wie "01100011" und "01100100" vergleicht, dann sieht man leicht, dass hier nicht so arg viel anders ist. Die zugehörigen Dezimalwerte 99 und 100 sind da augenscheinlich wesentlich unterschiedlicher: alle Zeichen haben sich geändert und es wird sogar eine zusätzliche Stelle benötigt. In der Hexadezimaldarstellung sieht es dagegen mit x"63" und x"64" wieder wesentlich entspannter aus: es ändert sich nicht die ganze Zahlendarstellung, sondern nur das niederwertigste Nibble.
Hier werden mehrere Lösungsmöglichkeiten für die Umwandlung einer 4 Bit breiten (Binär)zahl in einen ASCII-Wert aufgezeigt.
Der Lösungsansatz bei der Addiererlösung ist folgender:
Wenn di eine Zahl von 0..9 ist, dann addiere eine ASCII-0 dazu.
Wenn di eine Zahl von 10..15 ist, dann subtrahiere 10 und addiere ein ASCII-A dazu.
library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; entity BCD2ASCII is Port ( di : in STD_LOGIC_VECTOR (3 downto 0); do : out STD_LOGIC_VECTOR (7 downto 0)); end BCD2ASCII; -- Direkte Beschreibung als Distributed BROM -- Maximum combinational path delay: 7.276ns -- Number of Slices 3 -- Number of 4 input LUTs 6 architecture Behavioral of BCD2ASCII is type Rom16x8 is array (0 to 15) of std_logic_vector (7 downto 0); constant BCDRom : Rom16x8 := ( std_logic_vector(to_unsigned(character'pos('0'),8)), std_logic_vector(to_unsigned(character'pos('1'),8)), std_logic_vector(to_unsigned(character'pos('2'),8)), std_logic_vector(to_unsigned(character'pos('3'),8)), std_logic_vector(to_unsigned(character'pos('4'),8)), std_logic_vector(to_unsigned(character'pos('5'),8)), std_logic_vector(to_unsigned(character'pos('6'),8)), std_logic_vector(to_unsigned(character'pos('7'),8)), std_logic_vector(to_unsigned(character'pos('8'),8)), std_logic_vector(to_unsigned(character'pos('9'),8)), std_logic_vector(to_unsigned(character'pos('A'),8)), std_logic_vector(to_unsigned(character'pos('B'),8)), std_logic_vector(to_unsigned(character'pos('C'),8)), std_logic_vector(to_unsigned(character'pos('D'),8)), std_logic_vector(to_unsigned(character'pos('E'),8)), std_logic_vector(to_unsigned(character'pos('F'),8))); begin do <= BCDRom(to_integer(unsigned(di))); end Behavioral;
-- Über eine when-else Anweisung --> es wird ein Distributed BROM instatiiert -- Maximum combinational path delay: 7.276ns -- Number of Slices 3 -- Number of 4 input LUTs 6 architecture Behavioral of BCD2ASCII is begin do <= x"30" when di=x"0" else x"31" when di=x"1" else x"32" when di=x"2" else x"33" when di=x"3" else x"34" when di=x"4" else x"35" when di=x"5" else x"36" when di=x"6" else x"37" when di=x"7" else x"38" when di=x"8" else x"39" when di=x"9" else x"41" when di=x"A" else x"42" when di=x"B" else x"43" when di=x"C" else x"44" when di=x"D" else x"45" when di=x"E" else x"46"; end Behavioral;
-- Mit Addierer, die Konstate 10 wird direkt vom ASCII-Wert 'A' abgezogen (selbe Klammerebene) -- Maximum combinational path delay: 7.276ns -- Number of Slices 3 -- Number of 4 input LUTs 6 architecture Behavioral of BCD2ASCII is begin do <= std_logic_vector(resize(unsigned(di),8)+to_unsigned(character'pos('A')-10,8)) when unsigned(di)>9 else std_logic_vector(resize(unsigned(di),8)+to_unsigned(character'pos('0'),8)); end Behavioral; -- Wie vorher, die Konstate 10 wird aber auf einer anderen Klammerebene abgezogen --> ein Subtrahierer wird instatiiert! -- Maximum combinational path delay: 10.471ns -- Number of Slices 6 -- Number of 4 input LUTs 10 --architecture Behavioral of BCD2ASCII is begin do <= std_logic_vector(resize(unsigned(di),8)+to_unsigned(character'pos('A'),8)-10) when unsigned(di)>9 else std_logic_vector(resize(unsigned(di),8)+to_unsigned(character'pos('0'),8)); end Behavioral;
Die ersten 3 Lösungen resultieren in gleichem Ressourcenverbrauch und in
der selben Geschwindigkeit.
Sehr interessant ist aber der Unterschied zwischen der (optisch fast gleichen) 3. und 4. Lösung. Dort wurde nur die Subtraktion der Konstante 10 etwas verlegt, und XST fügt dann in die Hardware einen Subtrahierer ein. Dadurch wird das Design größer und langsamer!