Uso del código VHDL para diseñar un JK Flip Flop

2

Estoy usando el quartus II para diseñar un JK Flip Flop. Sin embargo, mis resultados muestran resultados desconocidos. ¿Por qué es?

Circuito de diseño previsto:

Código VHDL:

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

entity JKFlipFlopGate is
    port(
        J,K,Clk : in std_logic;             --JK Flip-Flop gate input 1 & 2
        Q,Qbar : out std_logic              --JK Flip-Flop gate output
    );
end JKFlipFlopGate;

architecture result of JKFlipFlopGate is        
signal out1,out2,out3,out4 : std_logic;

begin
    out1    <= NOT(J AND Clk AND out4);                 
    out2    <= NOT(K AND Clk AND out3); 
    out3    <= out1 NAND out4;
    out4    <= out2 NAND out3; 
    Q       <= out3;
    Qbar    <= out4;    
end result;
    
pregunta beginner

3 respuestas

-1

Si desea usar el reloj, tiene que escribir el proceso, que es sensible en algún borde del reloj. EDITAR: también debe inicializar out3 y out4:

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

entity JKFlipFlopGate is
    port(
        J,K,Clk : in std_logic;        --JK Flip-Flop gate input 1 & 2
        Q,Qbar : out std_logic         --JK Flip-Flop gate output
    );
end JKFlipFlopGate;

architecture result of JKFlipFlopGate is        
signal out1,out2: std_logic;
signal out3 : std_logic := '0'; -- Need proper initialization
signal out4 : std_logic := '0'; -- Need proper initialization

begin

    process(clk)

    begin
       if(rising_edge(clk)) then
           out1    <= NOT(J AND out4);
           out2    <= NOT(K AND out3); 
       end if;
    end process

    out3    <= out1 NAND out4;
    out4    <= out2 NAND out3; 
    Q       <= out3;
    Qbar    <= out4;    

end result;

De esta manera debería funcionar (pero no lo probé)

    
respondido por el Staszek
4

Para empezar, la forma convencional de diseñar un flip flop JK en VHDL se vería así:

signal Q_s : std_logic;

process(clk)
begin
  if (rising_edge(clk)) then
    if (J = '1' and K = '1') then
      Q_s <= not Q_s;
    elsif(J = '1') then
      Q_s <= '1';
    elsif(K = '1') then
      Q_s <= '0';
    end if;
  end if;
end process;

Q <= Q_s;
Qbar <= not Q_s;

Aquí estamos haciendo que se infiera un registro, con un comportamiento equivalente a un flip-flop JK. Tenga en cuenta que con este código, si afirma J y K juntos, antes de afirmar individualmente, entonces en la simulación, la salida Q será indefinida. Si el estado inicial no importa por cualquier motivo, puede inicializarlo en la definición usando signal Q_s : std_logic := '0'; ( '1' sería igualmente válido). Si el estado inicial es importante, debe agregar una cláusula de restablecimiento específica para establecer este estado.

Volviendo a su pregunta real, en realidad no hay ningún problema con su código; se sintetizará correctamente y funcionará "correctamente", pero no dará los resultados esperados en la simulación. Puede implementar su JK flip flop de manera que ambos simulen correctamente y se puedan sintetizar con el resultado que coincida exactamente con su diagrama de circuito. Para empezar, aquí hay un banco de pruebas simple:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity tb is
end tb;

architecture a of tb is
  constant CLK_PERIOD : time      := 100 ns;
  signal J            : std_logic := '0';
  signal K            : std_logic := '0';
  signal Clk          : std_logic := '0';
  signal Q            : std_logic;
  signal Qbar         : std_logic;
begin
  Clk <= not Clk after CLK_PERIOD / 2;

  uut : entity work.JKFlipFlopGate
    port map(
      J    => J,
      K    => K,
      Clk  => Clk,
      Q    => Q,
      Qbar => Qbar
    );

  process
  begin
    wait for CLK_PERIOD;
    J <= '1';
    wait for CLK_PERIOD;
    J <= '0';
    wait for CLK_PERIOD;
    k <= '1';
    wait for CLK_PERIOD;
    K <= '0';
    wait for CLK_PERIOD;
    J <= '1';
    k <= '1';
    wait for CLK_PERIOD;
    J <= '0';
    k <= '0';
    wait;
  end process;

end a;

El problema con la simulación de su código tal como está, es que dado que todas sus señales outx no están inicializadas, todo el circuito se encuentra en un estado desconocido, con varias señales que tienen el valor 'U' en el punto en que comienza la simulación. . Al agregar la inicialización, las definiciones de la señal outx parecen:

signal out1 : std_logic := '1';
signal out2 : std_logic := '1';
signal out3 : std_logic := '0';
signal out4 : std_logic := '1';

Tenga en cuenta que estos valores de inicialización solo afectan a la simulación; ya que su código no describe ningún elemento síncrono (más bien, una función combinatoria con comportamiento similar a un elemento síncrono), no tienen impacto en el diseño sintetizado, ya sea que su cadena de herramientas los admita o no.

La simulación de este diseño actualizado funciona correctamente cuando J o K están configurados en '1' . Sin embargo, cuando ambos se establecen altos, hay una condición de carrera y el circuito oscila. Esto coincide con el comportamiento del circuito real cuando el pulso del reloj permanece alto después de que la salida Q ha cambiado. Como no hay retrasos en la descripción, esta oscilación tendrá lugar en los ciclos delta de simulación y se alcanzará el límite de iteración de la simulación. Podemos verlos más fácilmente incorporando un retardo de puerta bruto en el diseño:

entity JKFlipFlopGate is
    generic(
        GATE_DELAY : time := 0 ns   -- Default needed for synth
    );
    port(
        J, K, Clk : in  std_logic;
        Q, Qbar   : out std_logic
    );
end JKFlipFlopGate;

architecture result of JKFlipFlopGate is
    signal out1 : std_logic := '0';
    signal out2 : std_logic := '0';
    signal out3 : std_logic := '1';
    signal out4 : std_logic := '0';

begin
    out1 <= not(J AND Clk AND out4) after GATE_DELAY;
    out2 <= not(K AND Clk AND out3) after GATE_DELAY;
    out3 <= out1 nand out4 after GATE_DELAY;
    out4 <= out2 nand out3 after GATE_DELAY;
    Q    <= out3;
    Qbar <= out4;
end result;

Normalmente, diría que no debe usar las cláusulas after en el código que se implementará en hardware real, pero esto es solo un ejercicio, y estas cláusulas se ignoran por síntesis. La simulación agrega lo siguiente:

constant GATE_DELAY : time := 1 ns;

Y la instanciación uut se convierte en:

  uut : entity work.JKFlipFlopGate
    generic map(
      GATE_DELAY => GATE_DELAY
    )
    port map(
      J    => J,
      K    => K,
      Clk  => Clk,
      Q    => Q,
      Qbar => Qbar
    );

Ahora puede ver las oscilaciones que resultan de un pulso de reloj demasiado largo en la forma de onda de la simulación:

Podemosreducirfácilmenteelanchodelpulsodelrelojparaeliminarestasoscilacionesalagregarunanuevaseñalde'pulso',derivadadelreloj:

signalClk_pulse:std_logic:='0';

Tengaencuentaqueesteesuncódigosolodesimulación,porloquepuedeusarlosvaloresinicialescomodesee.Acontinuación,unprocesoparaderivarelpulsodereloj:

process(Clk)beginif(rising_edge(Clk))thenClk_pulse<='1','0'after2*GATE_DELAY;endif;endprocess;

Y,porúltimo,enlainstanciaciónuut,Clk=>Clk,seconvierteenClk=>Clk_pulse,.

Contodosestoscambiosrealizados,eldiseñosimulaelcomportamientocorrectoyaúnsetransformacorrectamenteenelcircuitodediseñooriginal:

    
respondido por el scary_jeff
1

Una simulación VHDL como esta nunca funcionará sin una señal de reinicio. Al comienzo de la simulación, el valor de Q y Qbar es desconocido y, dado que se devuelven a la entrada, la condición desconocida se propaga a través de todas las puertas

    
respondido por el Claudio Avi Chami

Lea otras preguntas en las etiquetas