Estoy usando quartus II para diseñar un JK Flip Flop. Sin embargo, mis resultados muestran una salida desconocida. ¿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;
Si desea usar el reloj, debe escribir el proceso, que es sensible en algún borde del reloj. EDITAR: también necesita 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é).
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 inferir 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 alguna razón, puede inicializarlo en la definición usando signal Q_s : std_logic := '0';
( '1'
sería igualmente válido). Si el estado inicial importa, debe agregar una cláusula de reinicio específica para establecer este estado.
Volviendo a su pregunta real, en realidad no hay nada malo con su código; sintetizará correctamente y funcionará 'correctamente', pero no dará los resultados esperados bajo simulación. Puede implementar su flip flop JK de una manera que simule correctamente y se pueda 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 de simular su código tal como está es que, dado que todas sus outx
señales no están inicializadas, todo el circuito está 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, sus outx
definiciones de señal se ven así:
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; dado que su código no describe ningún elemento síncrono (más bien, una función combinatoria con un 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 o J
se K
establece 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 se producirá en ciclos delta de simulación, y se alcanzará el límite de iteraciones de la simulación. Podemos verlos más fácilmente incorporando un retardo de puerta rudimentario 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 after
cláusulas en el código que se implementará en hardware real, pero esto es solo un ejercicio, y la síntesis ignora estas cláusulas. La simulación agrega lo siguiente:
constant GATE_DELAY : time := 1 ns;
Y la uut
instanciación 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 simulación:
Podemos acortar fácilmente el ancho del pulso del reloj para deshacernos de estas oscilaciones agregando una nueva señal de 'pulso', derivada del reloj:
signal Clk_pulse : std_logic := '0';
Tenga en cuenta que este es un código solo de simulación, por lo que puede usar los valores iniciales como desee. A continuación, un proceso para derivar el pulso del reloj:
process(Clk)
begin
if (rising_edge(Clk)) then
Clk_pulse <= '1', '0' after 2 * GATE_DELAY;
end if;
end process;
Y, por último, en la uut
creación de instancias, Clk => Clk,
se convierte en Clk => Clk_pulse,
.
Con todos estos cambios realizados, el diseño simula con el comportamiento correcto y todavía se transforma correctamente en el circuito de diseño original:
Una simulación VHDL como esta nunca funcionará sin una señal de reinicio. Al comienzo de la simulación, se desconoce el valor de Q y Qbar y, dado que se retroalimentan a la entrada, la condición desconocida se propaga a través de todas las puertas.
principiante
Staszek
Staszek
miedo_jeff
principiante
Staszek
principiante
TonyM
Staszek
TonyM
Staszek
TonyM
Staszek
JHBonarius