¿Cómo puedo implementar un D-latch simple, solo Q, usando VHDL?

Acabo de comenzar VHDL hoy y soy el tipo de persona que solo puede aprender haciendo cosas, así que después de hacer algunas puertas básicas en VHDL, intenté hacer un D-latch simple (sin señal de reloj), pero sin éxito. Recibo todo tipo de errores como in1 no definido, std_logic no definido, etc.

Aquí está mi código:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity dflip is

end dflip;

architecture structural of dflip is

    component AND2
        port (in1, in2:in std_logic; out1: out std_logic);
    end component;

    component OR2
        port (in1, in2:in std_logic; out1: out std_logic);
    end component;

    component NOT1
        port (in1: in std_logic; out1: out std_logic);
    end component;

    signal D, E, E_NOT, Q, OUT_AND1, OUT_AND2: std_logic;

begin   
    U0: NOT1    port map (E, E_NOT);
    U1: AND2    port map (E, D, OUT_AND1);
    U2: AND2    port map (E_NOT, Q, OUT_AND2);
    U3: OR2     port map (OUT_AND1, OUT_AND2, Q);
end structural;


entity NOT1 is
    port (in1: in std_logic; out1: out std_logic);
end NOT1;

architecture behavioral_not of NOT1 is
begin
    out1 <= not in1;
end behavioral_not;


entity AND2 is
    port(in1, in2: in std_logic; out1: out std_logic);
end AND2;

architecture behavioral_and2 of AND2 is
begin

    out1 <= in1 and in2;

end behavioral_and2;


entity OR2 is
    port (in1, in2: in std_logic; out1: out std_logic);
end OR2;

architecture behavioral_or of OR2 is
begin
    out1 <= in1 or in2;
end behavioral_or;

Lo hice estructural, porque no pude hacer que funcionara como conductual, porque parece que no puedo usar declaraciones if si escribo conductual (tiene sentido). El problema es con esa salida Q que debe conectarse nuevamente a la entrada de una puerta AND.

Entonces, ¿cómo hago esto?

El código entre 'ARQUITECTURA... COMIENZO' y 'FIN...' es concurrente. El simulador vuelve a evaluar cada línea como 'U0: NOT port map' cada vez que ocurre un evento (por ejemplo, una transición) en una de las entradas. El orden del código es irrelevante. Las partes secuenciales (como el código imperativo 'tradicional') deben estar dentro de las declaraciones PROCESS. A diferencia del código C, no hay problema con 'usar una variable antes de asignarla', siempre que la señal se asigne en alguna parte.

Respuestas (4)

Los pestillos y flip-flop no se pueden modelar con puertas lógicas en VHDL, ¡esto es solo para simuladores analógicos! La lógica de retroalimentación no es un buen augurio para el simulador VHDL. Además, ningún sintetizador lo reconocería como un latch/flip-flop.

Para instanciar un latch/flip-flop, puede instanciar las primitivas de su proveedor o usar este código genérico:

LATCH: process(en, d)
begin
    if en = '1' then
        q <= d;
    end if;
end process LATCH;

DFF_ASYNC: process(rst, clk)
begin
    if rst = '1' then
        q <= '0';
    elsif rising_edge(clk) then
        q <= d;
    end if;
end process DFF_ASYNC;

DFF_SYNC: process(clk)
begin
    if rising_edge(clk) then
        if rst = '1' then
             q <= '0';
        else
             q <= d;
        end if;
    end if;
end process DFF_SYNC;

Use puertas lógicas solo para circuitos combinacionales. Si desea un desafío, puede ser mejor simular la lógica ALU que los elementos sincrónicos. Como nota final, tenga en cuenta que el uso de puertas lógicas para diseñar circuitos está reservado para los masoquistas, la mayoría de los diseñadores de VHDL usan construcciones de nivel superior que son más fáciles de leer y depurar.

Actualizar

Aparentemente, los pestillos se pueden simular en VHDL usando puertas lógicas (gracias @David Koontz). ¡Mira su respuesta para ver cómo!

¡Muchas gracias! ¿Por construcciones de nivel superior te refieres al uso de modelos de comportamiento?
Me refiero a RTL (nivel de transferencia de registro). Es un modelo en el que describe los registros (usando mi código de muestra) y cómo están conectados. Como ejemplo, un sumador tendría registros x, y y s y la declaración s <= x + y encerrada en una declaración de borde ascendente. Considero código VHDL conductual que no es sintetizable.

Es posible generar un modelo de puerta estructural de un pestillo D en VHDL. Saque una página del diseño de PLD donde encontramos que requiere un término de consenso:

library ieee;
use ieee.std_logic_1164.all;

entity not1 is
    port ( 
        in1:    in  std_logic;
        outp:   out std_logic
    );
end entity;

architecture foo of not1 is

begin
    outp <= not in1;
end architecture;

library ieee;
use ieee.std_logic_1164.all;

entity and2 is 
    port (
        in1:    in  std_logic;
        in2:    in  std_logic;
        outp:   out std_logic
    );
end entity;

architecture foo of and2 is

begin
    outp <= in1 and in2;
end architecture;

library ieee;
use ieee.std_logic_1164.all;

entity or3 is 
    port (
        in1:    in  std_logic;
        in2:    in  std_logic;
        in3:    in  std_logic;
        outp:   out std_logic
    );
end entity;

architecture foo of or3 is

begin
    outp <= in1 or in2 or in3;
end architecture;

library ieee;
use ieee.std_logic_1164.all;

entity dlatch is
    port (
        d:  in  std_logic;
        en: in  std_logic;
        q:  out std_logic
    );
end entity;

architecture fum of dlatch is

    signal not_en:      std_logic;
    signal w1, w2, w3:  std_logic;
    signal q_int:       std_logic;

    component not1 is
        port (
        in1:    in  std_logic;
        outp:   out std_logic
        );
    end component;

    component and2 is
        port (
        in1:    in  std_logic;
        in2:    in  std_logic;
        outp:   out std_logic
        );
    end component;    

    component or3 is
        port (
        in1:    in  std_logic;
        in2:    in  std_logic;
        in3:    in  std_logic;
        outp:   out std_logic
        );
    end component;

begin
U0:
    not1 
        port map (
        in1 => en,
        outp => not_en
        );
U1:
    and2
        port map (
        in1 => q_int,
        in2 => not_en,
        outp => w1
        );

U2:
    and2
        port map (
        in1 => d,
        in2 =>  en,
        outp => w2 
        );

U3: -- consensus term
    and2
        port map (
        in1 =>  d,
        in2 => q_int,
        outp => w3
        );

U4:
    or3
        port map (
            in1 => w1,
            in2 => w2,
            in3 => w3,
            outp => q_int
        );

    q <= q_int;

end architecture;

library ieee;
use ieee.std_logic_1164.all;

entity dlatch_tb is
end entity;

architecture test of dlatch_tb is
    signal d:   std_logic := '0';
    signal en:  std_logic := '0';
    signal q:   std_logic;

    component dlatch is
        port (
            d:  in  std_logic;
            en: in  std_logic;
            q:  out std_logic
        );
    end component;

begin
DUT:
    dlatch
        port map (
            d => d,
            en => en,
            q => q
        );
STIM:
    process
    begin
        wait for 10 ns;
        en <= '1';
        wait for 10 ns;
        en <= '0';
        wait for 10 ns;
        d <= '1';
        wait for 10 ns;
        en <= '1';
        wait for 10 ns;
        en <= '0';
        wait for 10 ns;
        wait;
    end process;
end architecture;

La arquitectura estructural que utiliza puertas instanciadas produce:

dlatch_tb estructural.png (se puede hacer clic)

Los pestillos y flip-flop no se pueden modelar con puertas lógicas en VHDL, ¡esto es solo para simuladores analógicos!

La moraleja de la historia es que no siempre se puede separar la opinión del conocimiento o la experiencia en las respuestas aquí. Este pequeño dato se puede encontrar en Principios y prácticas de diseño digital , 3.ª edición de John F. Wakerly, 8.2.6 Registros y pestillos en ABEL y PLD , al menos el diseño digital se convierte en un arte perdido. Solía ​​ser de conocimiento común cuando el diseño digital estaba dominado por PLD (PAL).

Sin el término de consenso, la salida oscilará. Hay otras formas de detener la oscilación causada por el retraso del ciclo delta a través de not1. Esta es una de al menos dos formas en que un diseño estructural puede simularse e implementarse.

Y, por supuesto, la gran pregunta es cuántos diseñadores digitales reales se necesitan en el mundo de hoy. El conocimiento y la experiencia provienen de la resolución de problemas del mundo real y, como señala la respuesta aceptada, indirectamente, no es necesario saber que hay una respuesta en VHDL.

Para aquellos con una necesidad real de diseño digital con elementos estructurales, podría ser útil buscar en Google la lógica de riesgo y/o el término de consenso junto con el diseño digital .

Este en particular me viene a la mente porque una vez fue una pregunta de entrevista para un trabajo de diseño digital en VHDL en una era de herramientas de síntesis más primitivas y simulaciones más lentas, lo que significa que la experiencia en diseño digital contaba más.

Si observa la parte de la carne y las papas del pestillo logrado con tres compuertas AND y una compuerta OR. Vemos que esto también se llama pestillo Earle :

Pestillo Earle

Esta imagen tomada de la página 40 de The Microarchitecture of Pipelined and Superscalar Computers , 1999 por Amos R. Omandi. El libro y el enlace del pestillo de Earle nos dicen que podemos incrustar un pestillo de Earle en otras estructuras AND OR (como Carry Look Ahead Adders) y la historia, utilizada en un IBM 360/91 a principios de la década de 1960.

El término de consenso, la puerta AND del medio en la figura anterior, supera el mismo número de retrasos de puertas (o retrasos del ciclo de simulación delta en un modelo de tiempo cero) en la ruta de retroalimentación, conservando un '1' en la salida cuando la entrada también es un '1'.

En el diseño VHDL que se muestra arriba, el not1inversor también proporciona esa retroalimentación perturbadora, al menos en una dirección, si la not1salida hubiera sido utilizada por la dlatch dpuerta AND de entrada (U2), en otras palabras, si el pestillo hubiera sido alimentado externamente not_eny producido ena través de la inversor not1_

El uso para ocultar latches en estructuras AND OR existentes se basa en una gran cantidad de términos que son algo atípicos para los primeros CPLD (PAL), una ventaja que no tenemos en los FPGA actuales, que implementan otras implementaciones de cadena de transporte en cualquier caso. Duplica el número de términos.

Puede eliminar la necesidad de términos de consenso en pestillos y flip flops basados ​​en RS al desequilibrar los retrasos de retroalimentación entre los lados R y S, generalmente agregando retraso (como en un retraso de puerta). Esto afecta los tiempos de preparación y espera.

Gracias por la corrección, como probablemente pueda ver, solo toqué un PAL en clases de lógica, antes de aprender sobre VHDL y FPGA. ¿Sabes si esto se asignaría a un pestillo primitivo en cualquier sintetizador?
No apostaría a que se asignaría a un pestillo primitivo en cualquier lugar. Debería generar un pestillo de trabajo basado en una estructura AND OR de tres términos. La razón principal por la que era bien conocido en PLD/PAL tiene que ver con la escasez de recursos, generalmente no hay razón en un FPGA hoy en día. También puede usar términos de consenso para hacer que funcionen los modelos de chanclas a nivel de puerta. Porque el bloqueo de comportamiento q_int <= (q_int and not en) or (d and en);funciona bien, porque no hay un retraso en el ciclo delta que necesite una cobertura de término de consenso.

Si desea un diseño estructural, la creación de instancias de componentes es el camino a seguir, pero uno realmente no modela el pestillo utilizando el modelado estructural. El comportamiento es más fácil y puede usar la instrucción if para este método. Mira este video-

http://appliedelectronicsengineering.blogspot.com/2015/10/how-to-implement-d-latch-in-vhdl.html

Por favor, resuma parte de la información en el video.

Los pestillos se pueden modelar de muchas maneras en VHDL, incluso con puertas lógicas; y el código VHDL así producido se puede sintetizar (al menos con Synplify Pro).

Los mensajes de error informados,

in1 no definido, std_logic no definido, etc.

indicar que faltan cláusulas de biblioteca y uso en el error. De hecho, básicamente lo único que hice para corregir su código fue agregarlos antes de cada declaración de entidad. Aquí está el código corregido:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity NOT1 is
port (in1: in std_logic; out1: out std_logic);
end;

architecture behavioral_not of NOT1 is
begin
    out1 <= not in1;
end;


library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity AND2 is
port (in1, in2: in std_logic; out1: out std_logic);
end;

architecture behavioral_and2 of AND2 is
begin
    out1 <= in1 and in2;
end;


library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity OR2 is
port (in1, in2: in std_logic; out1: out std_logic);
end;

architecture behavioral_or of OR2 is
begin
    out1 <= in1 or in2;
end;


library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity dflip is
port (D, E: in std_logic; Q: out std_logic);
end;

architecture structural of dflip is
    signal E_NOT, Q_int, OUT_AND1, OUT_AND2: std_logic;
begin   
    U0: entity work.NOT1
    port map (E, E_NOT);
    U1: entity work.AND2
    port map (E, D, OUT_AND1);
    U2: entity work.AND2
    port map (E_NOT, Q_int, OUT_AND2);
    U3: entity work.OR2
    port map (OUT_AND1, OUT_AND2, Q_int);

    Q <= Q_int;
end;

Como beneficio adicional, veamos una implementación más corta del pestillo D desbloqueado, con las mismas puertas, pero sin entidades separadas para cada puerta:

architecture short of dflip is
    signal Q_int: std_logic;
begin
    Q_int <= (D and E) or (not E and Q_int);
    Q <= Q_int;
end;

Tenga en cuenta que, en la práctica, seguramente usaría flip-flops cronometrados activados por flanco en lugar de pestillos. Esos se pueden expresar muy bien con la asignación de señal condicional:

Q <= D when rising_edge(clock) and E = '1';