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;