Search code examples
encryptionvhdl

VHDL Condition in if must be static and component instantiation inside if statement


I am implementing a block cipher(SQUARE) which consists of 8 rounds (see below). The cipher must allow two operational modes : encryption and decryption (denoted as mode = 0 or mode = 1 in code).

entity SQUARE is
Port ( mode : in  STD_LOGIC;
       squarein : in  STD_LOGIC_VECTOR (127 downto 0);
       key : in  STD_LOGIC_VECTOR (127 downto 0);
       squareout : out  STD_LOGIC_VECTOR (127 downto 0) 
     );
end SQUARE;

enc : if (mode = '0') generate -- do encryption
   s0 : preround port map(squarein, key, con0, key1, rin1);
   s1 : round port map(rin1, key1, con1, key2, rin2);
   s2 : round port map(rin2, key2, con2, key3, rin3);
   s3 : round port map(rin3, key3, con3, key4, rin4);
   s4 : round port map(rin4, key4, con4, key5, rin5);
   s5 : round port map(rin5, key5, con5, key6, rin6);
   s6 : round port map(rin6, key6, con6, key7, rin7);
   s7 : round port map(rin7, key7, con7, key8, rin8);
   s8 : lastround port map(rin8, key8, squareout);
end generate;

dec : if (mode = '1') generate -- do decryption
   i8 : invround port map(squarein, key8, con7, invkey7, invrin7);
   i7 : invround port map(invrin7, invkey7, con6, invkey6, invrin6);
   i6 : invround port map(invrin6, invkey6, con5, invkey5, invrin5);
   i5 : invround port map(invrin5, invkey5, con4, invkey4, invrin4);
   i4 : invround port map(invrin4, invkey4, con3, invkey3, invrin3);
   i3 : invround port map(invrin3, invkey3, con2, invkey2, invrin2);
   i2 : invround port map(invrin2, invkey2, con1, invkey1, invrin1);
   i1 : invround port map(invrin1, invkey1, con0, invkey0, invrin0);
   i0 : invpreround port map(invrin0, invkey0, squareout);
end generate;

Problem: Compile was successful with warnings (Condition in IF GENERATE must be static). How could I avoid this warning ? Maybe rewriting the code in other fashion ..


Solution

  • As stated by Paebbels, generate cannot be used dynamically. It needs to be constant at compile/synthesis time. what you could do is use a generic instead (using the VHDL-2008 if-else generate construct):

    entity SQUARE is
        generic(mode : std_logic);
        Port ( squarein : in  STD_LOGIC_VECTOR (127 downto 0);
               key : in  STD_LOGIC_VECTOR (127 downto 0);
               squareout : out  STD_LOGIC_VECTOR (127 downto 0) 
        );
    end entity;
    
    architecture structural or SQUARE is
    begin
        enc : if (mode = '0') generate -- do encryption
            s0 : entity work.preround port map(squarein, key, con0, key1, rin1);
            [...]
        else generate
           -- decrypt
           i8 : entity work.invround port map(squarein, key8, con7, invkey7, invrin7);
           [...]
        end generate;
    end architecture;
    

    If you want to change the mode of operation on the fly, you need to generate all the components, and select an output using muxes:

    entity SQUARE is
        Port ( mode : in std_logic;
               squarein : in  STD_LOGIC_VECTOR (127 downto 0);
               key : in  STD_LOGIC_VECTOR (127 downto 0);
               squareout : out  STD_LOGIC_VECTOR (127 downto 0) 
        );
    end entity;
    
    architecture structural or SQUARE is
    begin
        -- encrypt components
        s0 : entity work.preround port map(squarein, key, con0, key1, rin1);
        [...]
        s8 : entity work.lastround port map(rin8, key8, squareout_enc);
        -- decrypt components
        i8 : entity work.invround port map(squarein, key8, con7, invkey7, invrin7);
        [...]
        i0 : entity work.invpreround port map(invrin0, invkey0, squareout_dec);
        -- connect outputs
        squareout <= squareout_enc when mode='0' else squareout_dec;
    end architecture;