------------------------------------------------------------
-- Copyright: 2011 Integrated Sytems Laboratory, ETH Zurich
--            http://www.iis.ee.ethz.ch/~sha3
------------------------------------------------------------
-------------------------------------------------------------------------------
-- Title      : The Q round of Groestl
-- Project    : 
-------------------------------------------------------------------------------
-- File       : groestl_q.vhd
-- Author     : Frank K. Guerkaynak  
-- Company    : Integrated Systems Laboratory, ETH Zurich
-- Created    : 2011-08-21
-- Last update: 2011-09-05
-- Platform   : ModelSim (simulation), Synopsys (synthesis)
-- Standard   : VHDL'87
-------------------------------------------------------------------------------
-- Description: 1/8 of the round
-------------------------------------------------------------------------------
-- Copyright (c) 2011 Integrated Systems Laboratory, ETH Zurich
-------------------------------------------------------------------------------
-- Revisions  :
-- Date        Version  Author  Description
-- 2011-08-21  1.0      kgf	Created
-- 2011-09-04  1.1      kgf     Major corrections
-- 2011-09-05  1.2      kgf     Moved the register between Addroundcons and
--                              SubBytes
-------------------------------------------------------------------------------



library ieee;
use ieee.numeric_std.all;
use ieee.std_logic_1164.all;

entity groestl_q is

  port (
    ClkxCI        : in  std_logic;
    RstxRBI       : in  std_logic;
    RndxSI        : in  std_logic_vector(7 downto 0);
    SubRndxSI     : in  integer range 0 to 7;
    InxDI         : in  std_logic_vector(511 downto 0);
    OutxDO        : out std_logic_vector(511 downto 0));

end groestl_q;

architecture rtl of groestl_q is

  component g_mixbytes
    port (
      InxDI  : in  std_logic_vector(63 downto 0);
      OutxDO : out std_logic_vector(7 downto 0));
  end component;

  component groestl_subbytes
    port (
      DxDI : in  std_logic_vector(7 downto 0);
      DxDO : out std_logic_vector(7 downto 0));
  end component;

  type statematrix is array (0 to 7, 0 to 7) of std_logic_vector (7 downto 0);
  type statearray  is array (0 to 7) of std_logic_vector (7 downto 0);
  type incconsttype is array (0 to 7) of integer range 0 to 7;
  type minputtype is array (0 to 7) of std_logic_vector(63 downto 0);

  

-- KGF states
  signal QxDP, QxDN, Q1xD : statematrix;
  signal RQxD : std_logic_vector(63 downto 0);  -- selected column 
  signal SQxD : std_logic_vector(63 downto 0);  -- after Subbytes
  signal MQxD : statearray;       -- after MixBytes
  signal M1xD : minputtype;
  signal QStartxD, QFinxD : std_logic_vector(511 downto 0);
  
  constant INCQ : incconsttype := (1,3,5,7,0,2,4,6);  -- shift amounts for Q

begin  -- rtl



-------------------------------------------------------------------------------
-- New start either a fresh vector or a state round
-------------------------------------------------------------------------------

  QStartxD <= InxDI when RndxSI = "00000000" else QFinxD;
  
  p_new : process (QStartxD, SubRndxSI, RndxSI, Q1xD)
    variable varq : statematrix;
  begin  -- process p_new
     varq := Q1xD;    
     if SubRndxSI = 0 then              -- Add round constant
       varq(0,7) := QStartxD(455 downto 448)  xor x"ff" xor RndxSI;
       varq(1,7) := QStartxD(391 downto 384)  xor x"ef" xor RndxSI;
       varq(2,7) := QStartxD(327 downto 320)  xor x"df" xor RndxSI;
       varq(3,7) := QStartxD(263 downto 256)  xor x"cf" xor RndxSI;
       varq(4,7) := QStartxD(199 downto 192)  xor x"bf" xor RndxSI;
       varq(5,7) := QStartxD(135 downto 128)  xor x"af" xor RndxSI;
       varq(6,7) := QStartxD( 71 downto  64)  xor x"9f" xor RndxSI;
       varq(7,7) := QStartxD(  7 downto   0)  xor x"8f" xor RndxSI;
       for y in 0 to 6 loop
         for x in 0 to 7 loop
           varq(x,y) := QStartxD((((7-x) * 64) + ((7-y) *8) + 7) downto ((7-x) * 64) + ((7-y) *8)) xor x"ff";
         end loop;  -- x
       end loop;  -- y
     end if;

     QxDN <= varq;
  end process p_new;

-------------------------------------------------------------------------------
-- Register is here now QxDP QxDN
-------------------------------------------------------------------------------
  
  

-------------------------------------------------------------------------------
-- Select a vector to operate on. The shift is implicit in here
-------------------------------------------------------------------------------

 p_selq: process (QxDP, SubRndxSI)
 begin  -- process p_selp
   -- we have to change the numbering here, since it is after the register 0
   -- became 1 etc.
   case SubRndxSI is
      when 1      => RQxD <= QxDP(1,0) & QxDP(3,1) & QxDP(5,2) & QxDP(7,3) & QxDP(0,4) & QxDP(2,5) & QxDP(4,6) & QxDP(6,7);
      when 2      => RQxD <= QxDP(2,0) & QxDP(4,1) & QxDP(6,2) & QxDP(0,3) & QxDP(1,4) & QxDP(3,5) & QxDP(5,6) & QxDP(7,7);
      when 3      => RQxD <= QxDP(3,0) & QxDP(5,1) & QxDP(7,2) & QxDP(1,3) & QxDP(2,4) & QxDP(4,5) & QxDP(6,6) & QxDP(0,7);
      when 4      => RQxD <= QxDP(4,0) & QxDP(6,1) & QxDP(0,2) & QxDP(2,3) & QxDP(3,4) & QxDP(5,5) & QxDP(7,6) & QxDP(1,7);
      when 5      => RQxD <= QxDP(5,0) & QxDP(7,1) & QxDP(1,2) & QxDP(3,3) & QxDP(4,4) & QxDP(6,5) & QxDP(0,6) & QxDP(2,7);
      when 6      => RQxD <= QxDP(6,0) & QxDP(0,1) & QxDP(2,2) & QxDP(4,3) & QxDP(5,4) & QxDP(7,5) & QxDP(1,6) & QxDP(3,7);
      when 7      => RQxD <= QxDP(7,0) & QxDP(1,1) & QxDP(3,2) & QxDP(5,3) & QxDP(6,4) & QxDP(0,5) & QxDP(2,6) & QxDP(4,7);
      when others => RQxD <= QxDP(0,0) & QxDP(2,1) & QxDP(4,2) & QxDP(6,3) & QxDP(7,4) & QxDP(1,5) & QxDP(3,6) & QxDP(5,7);
    end case;
 end process p_selq;

-------------------------------------------------------------------------------
-- 8 x Sub bytes on this vector
-------------------------------------------------------------------------------
gen_q_sub: for i in 0 to 7 generate
    i_subbytes: groestl_subbytes  port map (DxDI => RQxD( (i*8) +7 downto i*8),
                                            DxDO => SQxD( (i*8) +7 downto i*8));
end generate gen_q_sub;

-------------------------------------------------------------------------------
-- We have a fixed MixBytes function. Normally the function is shifted, we will
-- shift the input data instead
-------------------------------------------------------------------------------
--   M1xD(0) SQxD;
--   M1xD(1) SQxD( 7 downto  0) & SQxD(63 downto  8);
--   M1xD(2) SQxD(15 downto  0) & SQxD(63 downto 16);
--   M1xD(3) SQxD(23 downto  0) & SQxD(63 downto 24);
--   M1xD(4) SQxD(31 downto  0) & SQxD(63 downto 32);
--   M1xD(5) SQxD(39 downto  0) & SQxD(63 downto 40);
--   M1xD(6) SQxD(47 downto  0) & SQxD(63 downto 48);
--   M1xD(7) SQxD(55 downto  0) & SQxD(63 downto 56);

   M1xD(0) <= SQxD;
   M1xD(1) <= SQxD(55 downto  0) & SQxD(63 downto 56);
   M1xD(2) <= SQxD(47 downto  0) & SQxD(63 downto 48);
   M1xD(3) <= SQxD(39 downto  0) & SQxD(63 downto 40);
   M1xD(4) <= SQxD(31 downto  0) & SQxD(63 downto 32);
   M1xD(5) <= SQxD(23 downto  0) & SQxD(63 downto 24);
   M1xD(6) <= SQxD(15 downto  0) & SQxD(63 downto 16);
   M1xD(7) <= SQxD( 7 downto  0) & SQxD(63 downto  8);



           
   gen_q_mix: for i in 0 to 7 generate
     i_mixbytes: g_mixbytes port map ( InxDI  => M1xD(i),
                                       OutxDO => MQxD(i));
   end generate gen_q_mix;
           

-------------------------------------------------------------------------------
-- Write back Q
-------------------------------------------------------------------------------
  
 p_shiftq: process (QxDP, SubRndxSI, MQxD)
   variable varq : statematrix;
 begin  -- process p_selp
   -- default
   varq := QxDP;                        -- do not shift for the first 7 cycles;
    -- changed the numbering here. This is after the register, SubRndxSI is 1
    -- ahead here
    case SubRndxSI is
      when 1      => varq(1,0) := MQxD(0); varq(3,1) := MQxD(1); varq(5,2) := MQxD(2); varq(7,3) := MQxD(3);
                     varq(0,4) := MQxD(4); varq(2,5) := MQxD(5); varq(4,6) := MQxD(6); varq(6,7) := MQxD(7);
      when 2      => varq(2,0) := MQxD(0); varq(4,1) := MQxD(1); varq(6,2) := MQxD(2); varq(0,3) := MQxD(3);
                     varq(1,4) := MQxD(4); varq(3,5) := MQxD(5); varq(5,6) := MQxD(6); varq(7,7) := MQxD(7);
      when 3      => varq(3,0) := MQxD(0); varq(5,1) := MQxD(1); varq(7,2) := MQxD(2); varq(1,3) := MQxD(3);
                     varq(2,4) := MQxD(4); varq(4,5) := MQxD(5); varq(6,6) := MQxD(6); varq(0,7) := MQxD(7);
      when 4      => varq(4,0) := MQxD(0); varq(6,1) := MQxD(1); varq(0,2) := MQxD(2); varq(2,3) := MQxD(3);
                     varq(3,4) := MQxD(4); varq(5,5) := MQxD(5); varq(7,6) := MQxD(6); varq(1,7) := MQxD(7);
      when 5      => varq(5,0) := MQxD(0); varq(7,1) := MQxD(1); varq(1,2) := MQxD(2); varq(3,3) := MQxD(3);
                     varq(4,4) := MQxD(4); varq(6,5) := MQxD(5); varq(0,6) := MQxD(6); varq(2,7) := MQxD(7);
      when 6      => varq(6,0) := MQxD(0); varq(0,1) := MQxD(1); varq(2,2) := MQxD(2); varq(4,3) := MQxD(3);
                     varq(5,4) := MQxD(4); varq(7,5) := MQxD(5); varq(1,6) := MQxD(6); varq(3,7) := MQxD(7);
      when 7      => varq(7,0) := MQxD(0); varq(1,1) := MQxD(1); varq(3,2) := MQxD(2); varq(5,3) := MQxD(3);
                     varq(6,4) := MQxD(4); varq(0,5) := MQxD(5); varq(2,6) := MQxD(6); varq(4,7) := MQxD(7);
      when others =>                    -- We wait for the shift until the last
                                        -- cycle. Now it iis time to shift all
                                        -- values
                     for y in 0 to 7 loop
                       for x in 0 to 6 loop
                         varq(x,y) := QxDP((x+INCQ(y)) mod 8 , y);
                       end loop;  -- x
                       varq(7,y) := MQxD(y);
                     end loop;  -- y
    end case;
   Q1xD <= varq;
 end process p_shiftq;

-------------------------------------------------------------------------------
-- Output 
-------------------------------------------------------------------------------

 p_out: process (Q1xD)
   variable vout : std_logic_vector(511 downto 0);
 begin  -- process p_out
   for y in 0 to 7 loop
     for x in 0 to 7 loop
       vout( ((7-x)*64) + ((7-y) * 8) + 7  downto ((7-x)*64) + ((7-y)*8) ) := Q1xD(x,y);
     end loop;  -- x
   end loop;  -- y

   QFinxD <= vout;
 end process p_out;

 OutxDO <= QFinxD;
 
  -- Memory
  -----------------------------------------------------------------------------
  p_mem : process (ClkxCI, RstxRBI)
  begin  -- process p_mem
    if RstxRBI = '0' then               -- asynchronous reset (active low)
      QxDP     <= (others => (others => (others => '0')));
      
    elsif ClkxCI'event and ClkxCI = '1' then  -- rising clock edge
      QxDP     <= QxDN;
    end if;
  end process p_mem;


  
end rtl;



Generated on Tue Nov 22 15:16:34 CET 2011
Home