2
\$\begingroup\$

I'm using quartus II to design a JK Flip Flop. However, my results show unknown output. Why is it?

Intended design circuit:

enter image description here

VHDL code:

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;
\$\endgroup\$
-1
\$\begingroup\$

If you want to use clock, you have to write process, that is sensitive on some clock edge. EDIT: you also need to initalize out3, and 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;

This way it should work (but I didn't test it.)

\$\endgroup\$
  • 4
    \$\begingroup\$ The problem with this answer is that it does not implement the circuit diagram in the question. The diagram shows 4 NAND gates, but this code implements 4 NAND gates and two registers. \$\endgroup\$ – scary_jeff Apr 28 '17 at 8:55
  • 1
    \$\begingroup\$ This implements two DFFs and some combinatorial logic, not the required circuit. Also, never use initial values on signals in synthesizable logic, use a proper reset. That's the difference between 'writing VHDL' and logic circuit design. Downvoting. \$\endgroup\$ – TonyM Apr 28 '17 at 9:13
  • 1
    \$\begingroup\$ Ok, how about this question and first answer? It clearly says, that in some cases it is better to not have reset, but initial values. In our question it was nothing about technology, so there is no reason to downvote if I pick one option from two available, and answered correctly to what was question about. Anyway, thanks for provoking me to make some research and teaching me something new:) \$\endgroup\$ – Staszek Apr 28 '17 at 11:45
  • 1
    \$\begingroup\$ He provided strong argument about logic that does not have built in reset, so it is not 'some people think'. I think you are a little too arrogant saying this. But it is your business. Anyway, thanks for conversation, and tips for the future. \$\endgroup\$ – Staszek Apr 29 '17 at 8:44
  • 2
    \$\begingroup\$ In ultra high speed design you often don't use resets, as resets require routing resources which you need to minimize. You need those resources to achieve minimal timing delay. Xilinx application engineers therefore actually advice to minimize reset use to "only where really required". \$\endgroup\$ – JHBonarius May 2 '17 at 9:21
4
\$\begingroup\$

To start with, the conventional way to design a JK flip flop in VHDL would look like this:

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;

Here we are causing a register to be inferred, with equivalent behavior to a JK flip flop. Note that with this code, if you assert J and K together, before asserting either individually, then in simulation, the output Q will be undefined. If the initial state does not matter for whatever reason, you can initialize it on definition using signal Q_s : std_logic := '0'; ('1' would be equally valid). If the initial state does matter, you should add a specific reset clause to set this state.

Going back to your actual question, there is actually nothing wrong with your code; it will synthesize correctly and work 'properly', but will not give the expected results under simulation. You can implement your JK flip flop in a way that both simulates properly, and can be synthesized with the result matching exactly your circuit diagram. To start with, here's a simple test bench:

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;

The problem with simulating your code as-is, is that since all your outx signals are not initialized, the whole circuit is in an unknown state, with various signals having the value 'U' at the point the simulation starts. Adding initialization, your outx signal definitions then look like:

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

Note that these initialization values only affect the simulation; since your code does not describe any synchronous elements (rather, a combinatorial function with behavior similar to a synchronous element), they have no impact on the synthesized design, whether your tool chain supports them or not.

Simulating this updated design works correctly when either J or K are set to '1'. However, when both are set high, there is a race condition and the circuit oscillates. This matches the behavior of the real circuit when the clock pulse stays high after the output Q has toggled. Since there are no delays in the description, this oscillation will take place in simulation delta cycles, and the simulation iteration limit will be reached. We can see these more easily by incorporating a crude gate delay into the design:

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;

Normally I would say that you should not use after clauses in code that is to be implemented in real hardware, but this is just an exercise, and these clauses are ignored by synthesis. The simulation adds the following:

constant GATE_DELAY : time := 1 ns;

And the uut instantiation becomes:

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

You can now see the oscillations that result from too long a clock pulse in the simulation waveform:

JK oscillations

We can easily shorten the clock pulse width to get rid of these oscillations by adding a new 'pulse' signal, derived from the clock:

signal Clk_pulse    : std_logic := '0';

Note that this is simulation-only code, so you can use initial values however you like. Next, a process to derive the clock pulse:

  process(Clk)
  begin
    if (rising_edge(Clk)) then
      Clk_pulse <= '1', '0' after 2 * GATE_DELAY;
    end if;
  end process;

And lastly in the uut instantiation, Clk => Clk, becomes Clk => Clk_pulse,.

With all these changes made, the design simulates with correct behavior, and is still correctly transformed into the original design circuit:

'pulse' clock

Elaborated circuit

\$\endgroup\$
  • \$\begingroup\$ Good answer. But I would not default the gate delay to 0 ns, or you will have the same issue again. \$\endgroup\$ – JHBonarius May 2 '17 at 9:10
  • \$\begingroup\$ @J.H.Bonarius The default is, as it says, for synthesis. You could add a specification for that generic in your tool, but that would be tool specific. \$\endgroup\$ – scary_jeff May 2 '17 at 9:15
1
\$\begingroup\$

A VHDL simulation like this will never work without a reset signal. At the beginning of the simulation, Q and Qbar value is unknown and since they are fed back to the input, the unknown condition is propagated through all the gates

\$\endgroup\$
  • 1
    \$\begingroup\$ Yes it can. To just need to define initial values. \$\endgroup\$ – JHBonarius May 2 '17 at 9:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.