Actualmente estoy aprendiendo VHDL. Como ejercicio decidí implementar algunos de los chips de la serie 7400. A continuación se muestra el 74153 y, al probarlo con ghdl/gtkwave, parece funcionar.
Pero estoy seguro de que esta implementación es ingenua (muchas repeticiones, uso de señales extra retrasadas (*_d), etc.). ¿Cuál sería la forma limpia de implementar dicho dispositivo?
--
-- 74153 implementation
-- Dual 4-Line to 1-Line
--
library ieee;
use ieee.std_logic_1164.all;
entity TTL_74153 is
port(
c0, c1, c2, c3: in std_logic_vector(1 downto 0);
sel: in std_logic_vector(1 downto 0);
g: in std_logic_vector(1 downto 0);
y: out std_logic_vector(1 downto 0));
end TTL_74153;
architecture behav of TTL_74153 is
signal c0_d, c1_d, c2_d, c3_d: std_logic_vector(1 downto 0);
signal sel_d, g_d: std_logic_vector(1 downto 0);
begin
-- delays
c0_d <= c0 after 11 ns;
c1_d <= c1 after 11 ns;
c2_d <= c2 after 11 ns;
c3_d <= c3 after 11 ns;
sel_d <= sel after 20 ns;
g_d <= g after 18 ns;
-- logic
y(0) <= '0' when g_d(0) = '1' else
c0_d(0) when sel_d = "00" else
c1_d(0) when sel_d = "01" else
c2_d(0) when sel_d = "10" else
c3_d(0) when sel_d = "11";
y(1) <= '0' when g_d(0) = '1' else
c0_d(1) when sel_d = "00" else
c1_d(1) when sel_d = "01" else
c2_d(1) when sel_d = "10" else
c3_d(1) when sel_d = "11";
end behav;
Los retrasos como "esperar" y "después" no son sintetizables. Dicho esto, la forma en que separas la ruta de datos de entrada y salida parece extraña. Yo haría algo como esto:
-- -- Implementación 74153 -- Dual de 4 líneas a 1 línea --
library ieee;
use ieee.std_logic_1164.all;
entity TTL_74153 is
port(
c0, c1, c2, c3: in std_logic_vector(1 downto 0);
sel: in std_logic_vector(1 downto 0);
g: in std_logic_vector(1 downto 0);
y: out std_logic_vector(1 downto 0));
end TTL_74153;
architecture behav of TTL_74153 is
signal mux_out: std_logic_vector(1 downto 0);
begin
-- logic
-- the vector indices aren't necessary, but i prefer them
mux_out(1 downto 0) <= c0(1 downto 0) when sel = "00" else
c1(1 downto 0) when sel = "01" else
c2(1 downto 0) when sel = "10" else
c3(1 downto 0) when sel = "11" else
"00";
y= "00" when g(0) = '1' else mux_out;
end behav;
Usando la función to_integer
en ieee.numeric_std
el paquete, la parte lógica se puede reducir aún más.
Creo que la forma correcta de modelar el retraso de propagación en VHDL es usando el modelo de retraso de transporte .
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity TTL_74153 is
port(
c0, c1: in std_logic_vector(3 downto 0);
sel, g: in std_logic_vector(1 downto 0);
y: out std_logic_vector(1 downto 0));
end TTL_74153;
architecture behav of TTL_74153 is
signal sel_d, g_d: std_logic_vector(1 downto 0);
begin
-- delays
sel_d <= transport sel after 9 ns;
g_d <= transport g after 7 ns;
-- logic
y <= transport (not g_d) and (c1(to_integer(unsigned(sel_d))) & c0(to_integer(unsigned(sel_d)))) after 11 ns;
end behav;
svens
sel_d
, pero está bien como está.