Für die Klartextausgabe eines Bytes ist 0-255 auf einem Display intuitiver, als nur 00-FF anzuzeigen. 100 (dez) sagt einen Dezimalisten mehr als 64 (hex). Hier eine Methode, wie ein 8-Bit-Vektor in eine 3-stellige BCD-Zahl umgewandelt wird. In einem ROM mit 12 Bit*256 Worte werden die drei Nibbles eingetragen, und anschliessend einfach über den Index ausgegeben.
data ist der Eingangsvektor, dig100, dig10 und dig1 sind die drei BCD-Digits.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity BCD_ROM is
Port ( clk : in STD_LOGIC;
data : in STD_LOGIC_VECTOR (7 downto 0);
dig1 : out STD_LOGIC_VECTOR (3 downto 0);
dig10 : out STD_LOGIC_VECTOR (3 downto 0);
dig100 : out STD_LOGIC_VECTOR (3 downto 0));
end BCD_ROM;
architecture Behavioral of BCD_ROM is
subtype SLV12 is std_logic_vector (11 downto 0);
type Rom128x8 is array (0 to 255) of SLV12;
constant BCDRom : Rom128x8 := (
x"000", x"001", x"002", x"003", x"004", x"005", x"006", x"007", x"008", x"009",
x"010", x"011", x"012", x"013", x"014", x"015", x"016", x"017", x"018", x"019",
x"020", x"021", x"022", x"023", x"024", x"025", x"026", x"027", x"028", x"029",
:
x"220", x"221", x"222", x"223", x"224", x"225", x"226", x"227", x"228", x"229",
x"230", x"231", x"232", x"233", x"234", x"235", x"236", x"237", x"238", x"239",
x"240", x"241", x"242", x"243", x"244", x"245", x"246", x"247", x"248", x"249",
x"250", x"251", x"252", x"253", x"254", x"255" );
signal digits : std_logic_vector (11 downto 0);
signal addr : std_logic_vector (7 downto 0);
begin
-- BROM
process begin
wait until rising_edge(clk);
addr <= data;
end process;
digits <= BCDRom(to_integer(unsigned(addr)));
dig1 <= digits (3 downto 0);
dig10 <= digits (7 downto 4);
dig100 <= digits(11 downto 8);
end Behavioral;
Weil im obigen Beispiel die Adresse getaktet ist, wird ein BROM synthetisiert.
Sind die BRAMs schon alle verwendet, lassen wir den Takt weg:
begin
-- Distributed ROM braucht 54 Slices
digits <= BCDRom(to_integer(unsigned(data)));
dig1 <= digits (3 downto 0);
dig10 <= digits (7 downto 4);
dig100 <= digits(11 downto 8);
end Behavioral;
Statt der BRAMs wird jetzt distributed RAM verwendet, was sich im Verbrauch von 54 Slices niederschlägt.
Auch in einem CPLD lässt sich diese Umwandlung problemlos einsetzen. In einem XC9572XL CPLD werden für die Byte-nach-BCD Umwandlung gerade mal ein drittel der Ressourcen verbraucht:
Macrocells Pterms Registers Pins Function Block Inputs
15/72 (21%) 130/360 (37%) 0/72 (0%) 20/34 (59%) 36/216 (17%)
Hier der Code mit der kompletten Tabelle:...
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity BCD_ROM is
Port ( --clk : in STD_LOGIC;
data : in STD_LOGIC_VECTOR (7 downto 0);
dig1 : out STD_LOGIC_VECTOR (3 downto 0);
dig10 : out STD_LOGIC_VECTOR (3 downto 0);
dig100 : out STD_LOGIC_VECTOR (3 downto 0));
end BCD_ROM;
architecture Behavioral of BCD_ROM is
subtype SLV12 is std_logic_vector (11 downto 0);
type Rom128x8 is array (0 to 255) of SLV12;
constant BCDRom : Rom128x8 := (
x"000", x"001", x"002", x"003", x"004", x"005", x"006", x"007", x"008", x"009",
x"010", x"011", x"012", x"013", x"014", x"015", x"016", x"017", x"018", x"019",
x"020", x"021", x"022", x"023", x"024", x"025", x"026", x"027", x"028", x"029",
x"030", x"031", x"032", x"033", x"034", x"035", x"036", x"037", x"038", x"039",
x"040", x"041", x"042", x"043", x"044", x"045", x"046", x"047", x"048", x"049",
x"050", x"051", x"052", x"053", x"054", x"055", x"056", x"057", x"058", x"059",
x"060", x"061", x"062", x"063", x"064", x"065", x"066", x"067", x"068", x"069",
x"070", x"071", x"072", x"073", x"074", x"075", x"076", x"077", x"078", x"079",
x"080", x"081", x"082", x"083", x"084", x"085", x"086", x"087", x"088", x"089",
x"090", x"091", x"092", x"093", x"094", x"095", x"096", x"097", x"098", x"099",
x"100", x"101", x"102", x"103", x"104", x"105", x"106", x"107", x"108", x"109",
x"110", x"111", x"112", x"113", x"114", x"115", x"116", x"117", x"118", x"119",
x"120", x"121", x"122", x"123", x"124", x"125", x"126", x"127", x"128", x"129",
x"130", x"131", x"132", x"133", x"134", x"135", x"136", x"137", x"138", x"139",
x"140", x"141", x"142", x"143", x"144", x"145", x"146", x"147", x"148", x"149",
x"150", x"151", x"152", x"153", x"154", x"155", x"156", x"157", x"158", x"159",
x"160", x"161", x"162", x"163", x"164", x"165", x"166", x"167", x"168", x"169",
x"170", x"171", x"172", x"173", x"174", x"175", x"176", x"177", x"178", x"179",
x"180", x"181", x"182", x"183", x"184", x"185", x"186", x"187", x"188", x"189",
x"190", x"191", x"192", x"193", x"194", x"195", x"196", x"197", x"198", x"199",
x"200", x"201", x"202", x"203", x"204", x"205", x"206", x"207", x"208", x"209",
x"210", x"211", x"212", x"213", x"214", x"215", x"216", x"217", x"218", x"219",
x"220", x"221", x"222", x"223", x"224", x"225", x"226", x"227", x"228", x"229",
x"230", x"231", x"232", x"233", x"234", x"235", x"236", x"237", x"238", x"239",
x"240", x"241", x"242", x"243", x"244", x"245", x"246", x"247", x"248", x"249",
x"250", x"251", x"252", x"253", x"254", x"255" );
signal digits : std_logic_vector (11 downto 0);
-- signal addr : std_logic_vector (7 downto 0);
begin
-- so gibt es ein BROM
process begin
wait until rising_edge(clk);
addr <= data;
end process;
digits <= BCDRom(to_integer(unsigned(addr)));
-- das ist ein Distributed ROM, Platzbedarf 54 Slices
digits <= BCDRom(to_integer(unsigned(data)));
dig1 <= digits (3 downto 0);
dig10 <= digits (7 downto 4);
dig100 <= digits(11 downto 8);
end Behavioral;