Manejo de un bus de datos bidireccional multiplexado en VHDL

0

Ok, soy un principiante autodidacta que juega con un FPGA y VHDL. He implementado exitosamente una serie de proyectos usando I / O pero solo unidireccional. Los pins están dentro o fuera, pero no inout.

Ahora quiero conectar con un dispositivo externo que tenga un bus de datos bidireccional de 8 bits. Para complicar aún más las cosas, este bus bidireccional se multiplexa con el bus de dirección.

En la parte baja del ciclo de reloj del dispositivo, siempre emitirá los 8 bits superiores de una dirección de 24 bits en el bus de datos. Los 16 bits más bajos no son válidos en ese momento. En la parte alta del ciclo, eliminará los datos o los leerá. Hay una señal activa de activación de escritura baja (RW) para indicar la dirección. Los 16 bits inferiores del bus de datos también son válidos en este momento.

El FPGA está generando el reloj para el dispositivo, así que tengo acceso a la señal del reloj. También me gustaría separar los datos en dos buses de 8 bits para usarlos internamente, uno para leer y otro para escribir.

Por lo tanto, debo configurar los pines para que ingresen y enganchen la parte superior de la dirección durante el período de baja del reloj, y luego durante el período de alta del reloj, debo configurar los pines para que ingresen o salgan y se tripliquen cuando sea apropiado, dependiendo de La señal RW. Así que, básicamente, una versión VHDL del siguiente esquema.

simular este circuito : esquema creado usando CircuitLab

Proporcionaría algunos VHDL que he probado, pero no estoy seguro de cuál de los 20 intentos diferentes de publicación.

Ah, y si alguien tiene algún consejo sobre cómo manejar correctamente las señales de entrada externas simuladas durante la simulación, eso también sería útil. Estoy trabajando con ISim, que es parte de Xilinx ISE.

Actualizar:

Gracias a @Humpawumpa, creo que tengo esto resuelto. Parece que mi problema estaba manejando incorrectamente el estado de alta impedancia del pin de entrada, y además de eso, debido a mi comprensión errónea de cuándo y dónde establecer la impedancia alta, también estaba configurando mi estímulo de simulación, todo mal. p>

Este es el código que se me ocurrió al incorporar la respuesta de Humpawumpa y se ve bien en el simulador. ¡Hurra!

    entity addressDemux is
    port
    (
        phi2 : in std_logic;
        rw : in std_logic;
        data_io : inout std_logic_vector(7 downto 0);
        addr_low_in : in std_logic_vector(15 downto 0);

        addr_hi_p : out std_logic_vector(7 downto 0);
        input_p : out std_logic_vector(7 downto 0);
        output_p: in std_logic_vector(7 downto 0);
        addr_full_p : out std_logic_vector(23 downto 0)
    );
end addressDemux;

architecture struct of addressDemux is

    signal addr_hi : std_logic_vector(7 downto 0);
    signal input : std_logic_vector(7 downto 0) := (others => '0');
    signal output : std_logic_vector(7 downto 0);
    signal addr_low : std_logic_vector(15 downto 0) := (others => '0');

begin

    addr_hi <= data_io when phi2 = '0';
    data_io <= output when phi2 = '1' and rw = '0' else (others => 'Z');
    input <= data_io when phi2 = '1' and rw = '1';
    addr_low <= addr_low_in when phi2 = '1';

    addr_hi_p <= addr_hi;
    addr_full_p(23 downto 16) <= addr_hi;
    addr_full_p(15 downto 0) <= addr_low;
    input_p <= input;
    output <= output_p;

end struct;

Básicamente, lo que me estaba fallando era configurar el inout pin data_io a alta impedancia. Al provenir de una configuración de fondo de desarrollo de software data_io a 'Z' en el período de alta del reloj y luego leer los datos me confundió. En la configuración del software, una variable con algún valor no le da un valor diferente cuando lo lee. Así que pensé que si lo configuraba en "Z", mi entrada sería "Z" cuando lo leí. Todo es código correcto, jaja. Hay mucho que desaprender, supongo.

    
pregunta Brad S

2 respuestas

3

Si tienes un inout -pin que usas como entrada (mientras lees) establece su output en tri-state.

Aquí hay un ejemplo simplificado

ENTITY inout IS
port (
  wr_en : IN STD_LOGIC;
  data_io : INOUT STD_LOGIC_VECTOR(7 DOWNTO 0)
);
END inout;

ARCHITECTURE struct OF inout IS
  SIGNAL input : STD_LOGIC_VECTOR(7 DOWNTO 0);
  SIGNAL output : STD_LOGIC_VECTOR(7 DOWNTO 0);
BEGIN
  data_io <= output WHEN wr_en = '1' ELSE 'Z';
  input <= data_io WHEN wr_en = '0' ELSE (OTHERS => '0');
END ARCHITECTURE struct;

Editar: Como lo indica correctamente Oldfart, la asignación para el vector input puede ser incondicional input <= data_io . Lo dejo condicional en el código de ejemplo, como ocurre normalmente cuando se escribe en el puerto, los datos entrantes (en bucle) no son de interés / no son válidos.

    
respondido por el Humpawumpa
0

Visualmente, con los nombres de señal @Humpawumpa utilizados:

    
respondido por el CapnJJ

Lea otras preguntas en las etiquetas