vhdldigital-logichardwaredigital-design

Problem while implementing JK-Flip Flop in VHDL


I'm trying to implement JK flip-flop in VHDL, and here is my code:

library ieee;
use ieee.std_logic_1164.all;

entity jk_flip_flop is
port(
    J, K     : in std_logic;
    clk      : in std_logic;
    Q, Q_bar : out std_logic
);
end jk_flip_flop;

architecture behavioral of jk_flip_flop is
begin
   process(J, K, clk)
        variable temp: std_logic;
   begin
        if (clk'event and clk='1') then
             temp:='1' when(J='1' AND K='0') else
                    '0' when(J='0' AND K='1') else
                    NOT temp when(J='1' AND K='1') else
                    temp when(J='0' AND K='0');
              Q <= temp;
              Q_bar <= NOT temp;
         end if;
    end process;
end behavioral;

The error I'm getting from it is:

Error (10500): VHDL syntax error at jk_flip_flop.vhd(18) near text "when";  expecting ";"
Error (10500): VHDL syntax error at jk_flip_flop.vhd(18) near text "else";  expecting ":=", or "<="
Error (10500): VHDL syntax error at jk_flip_flop.vhd(19) near text "else";  expecting ":=", or "<="
Error (10500): VHDL syntax error at jk_flip_flop.vhd(20) near text "else";  expecting ":=", or "<="
Error (10500): VHDL syntax error at jk_flip_flop.vhd(21) near text ";";  expecting ":=", or "<="

What exactly is wrong here? Am I not allowed to use when-else inside a process or is the syntax of when-else statement wrong here?

Also I'm confused whether I need to pass J and K into the process above, or is it enough if I pass only clk, since it should be enough if the new output gets produced at rising edge of the clock pulse.


Solution

  • So your temp := value when ... else ... statement only works outside of a process statement. So you've got three options.

    Option 1

    Upgrade to VHDL 2008, where you can also use this kind of statement in a process.

    Option 2

    Use a global variable to store the next value... something like:

    architecture behavioral of jk_flip_flop is
       signal Q_val: std_logic;
       signal Q_next: std_logic;
    begin
       Q_next <= '1' when(J='1' AND K='0') else
                 '0' when(J='0' AND K='1') else
                 NOT Q_val when(J='1' AND K='1') else
                 Q_val;
       Q <= Q_next;
       Q_bar <= not Q_val;
    
       process(clk)
       begin
            if (clk'event and clk='1') then
                 Q_val := Q_next;
             end if;
        end process;
    end behavioral;
    

    Option 3

    Use ifs instead of when.

    architecture behavioral of jk_flip_flop is
    begin
       process(J, K, clk)
            variable temp: std_logic;
       begin
            if (clk'event and clk='1') then
                 if (J='1' and K='0') then
                   temp := '1';
                 elsif (J='0' AND K='1') then
                   temp := '0';
                 elsif (J='1' AND K='1') then
                   temp := NOT temp;
                 end if;
                 Q <= temp;
                 Q_bar <= NOT temp;
             end if;
        end process;
    end behavioral;
    

    I'm not sure if this will work though... I thought temp would need to be defined at the architecture level for it to have a memory... But I could be wrong about that.

    And on the sensitivity list...

    Also I'm confused whether I need to pass J and K into the process above, or is it enough if I pass only clk, since it should be enough if the new output gets produced at rising edge of the clock pulse.

    You only need to pass clk in.