---------------------------------------------------------------------- ---- ---- ---- Pipelined Aes IP Core ---- ---- ---- ---- This file is part of the Pipelined AES project ---- ---- http://www.opencores.org/cores/aes_pipe/ ---- ---- ---- ---- Description ---- ---- Implementation of AES IP core according to ---- ---- FIPS PUB 197 specification document. ---- ---- ---- ---- To Do: ---- ---- - ---- ---- ---- ---- Author: ---- ---- - Subhasis Das, subhasis256@gmail.com ---- ---- ---- ---------------------------------------------------------------------- ---- ---- ---- Copyright (C) 2009 Authors and OPENCORES.ORG ---- ---- ---- ---- This source file may be used and distributed without ---- ---- restriction provided that this copyright statement is not ---- ---- removed from the file and that any derivative work contains ---- ---- the original copyright notice and the associated disclaimer. ---- ---- ---- ---- This source file is free software; you can redistribute it ---- ---- and/or modify it under the terms of the GNU Lesser General ---- ---- Public License as published by the Free Software Foundation; ---- ---- either version 2.1 of the License, or (at your option) any ---- ---- later version. ---- ---- ---- ---- This source is distributed in the hope that it will be ---- ---- useful, but WITHOUT ANY WARRANTY; without even the implied ---- ---- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ---- ---- PURPOSE. See the GNU Lesser General Public License for more ---- ---- details. ---- ---- ---- ---- You should have received a copy of the GNU Lesser General ---- ---- Public License along with this source; if not, download it ---- ---- from http://www.opencores.org/lgpl.shtml ---- ---- ---- ---------------------------------------------------------------------- ------------------------------------------------------ -- Project: AESFast -- Author: Subhasis -- Last Modified: 25/03/10 -- Email: subhasis256@gmail.com ------------------------------------------------------ -- -- Description: The Overall Core -- Ports: -- Clk: System Clock -- plaintext_i: Input plaintext blocks -- keyblock_i: Input keyblock -- ciphertext_o: Output Cipher Block ------------------------------------------------------ library IEEE; use IEEE.std_logic_1164.all; use IEEE.std_logic_arith.all; use IEEE.std_logic_unsigned.all; library work; use work.aes_pkg.all; entity AES_3PipeStages is generic ( DESIGN_WIDTH_NB: integer:= 256; REBEL_LENGTH_NB: integer:= 272); port( Clk_Launch: in std_logic; Clk_Capture: in std_logic; RESET: in std_logic; SI_Launch: in std_logic; SE_Launch: in std_logic; ClkEn_Launch: in std_logic; REBEL_load: in std_logic; REBEL_ConfigIns: in std_logic_vector(REBEL_LENGTH_NB+2 downto 0); ClkEn_Capture: in std_logic; REBEL_FDMode: in std_logic; REBEL_QMOuts: inout std_logic_vector(REBEL_LENGTH_NB-1 downto 0) -- REBEL_QOuts: out std_logic_vector(REBEL_LENGTH_NB-1 downto 0) ); end AES_3PipeStages; architecture rtl of AES_3PipeStages is signal fc3, c0, c1, c2, c3: colnet(0 downto 0); signal textnet_a_s, textnet_s_m, textnet_m_a: datanet(0 downto 0); signal key_m, key_s: datanet(0 downto 0); signal key_m_o, ciphertext_o: datablock; -- Include the 3 header bits signal AES_COuts: std_logic_vector(REBEL_LENGTH_NB+2 downto 0); signal REBEL_DIns: std_logic_vector(REBEL_LENGTH_NB+2 downto 0); signal SO_Launch_int: std_logic; signal launch_ctrl_reg, launch_ctrl_next: std_logic_vector(DESIGN_WIDTH_NB-1 downto 0); attribute keep: string; attribute keep of launch_ctrl_reg: signal is "true"; signal Launch_Row1: std_logic_vector(DESIGN_WIDTH_NB-1 downto 0); signal Launch_Row2: std_logic_vector(DESIGN_WIDTH_NB-1 downto 0); signal AES_INPUTs: std_logic_vector(DESIGN_WIDTH_NB-1 downto 0); signal REBEL_QOuts: std_logic_vector(REBEL_LENGTH_NB-1 downto 0); component addkey is port( roundkey: in datablock; datain: in datablock; rcon: in std_logic_vector(7 downto 0); dataout: out datablock; fc3: out blockcol; c0: out blockcol; c1: out blockcol; c2: out blockcol; c3: out blockcol ); end component; component sboxshr is port( blockin: in datablock; fc3: in blockcol; c0: in blockcol; c1: in blockcol; c2: in blockcol; c3: in blockcol; nextkey: out datablock; blockout: out datablock ); end component; component colmix is port( datain: in datablock; inrkey: in datablock; outrkey: out datablock; dataout: out datablock ); end component; begin -- Launch register control signal for 2-to-1 muxes below process(Clk_Launch, RESET) begin if (RESET = '1') then launch_ctrl_reg <= (others => '0'); elsif (Clk_Launch'event and Clk_Launch = '1') then launch_ctrl_reg <= launch_ctrl_next; end if; end process; launch_ctrl_next <= (DESIGN_WIDTH_NB-1 downto 0 => ClkEn_Launch); -- Regular scan FFs here -- no need for REBEL. We handle this by loading up the two patterns in two -- separate rows of FFs. Since we repeat the same pattern over-and-over again, we do NOT do a -- launch-off-capture any longer. Instead, I preserve the contents of both launch rows and carry -- out the transition test using MUXes which select which row drives the inputs of the AES stage. -- The timing associated with the ClkEn_Launch is as follows: -- -------------- -------------- -------------- -- | | | | | Clk_Launch -- ----- -------------- -------------- -- ---------------------------- -- | | ClkEn_Launch -- ------- ------------------------------------- -- ---------------------------- -- | | launch_ctrl_reg -- -------------------------------- ----------- -- ^ 'launch' occurs here by switching in Launch_Row2 MUXD_ScanFF_Row1: entity work.MUXD_ScanFF_Row(beh) generic map (NUM_SFFs=>DESIGN_WIDTH_NB) port map (D=>Launch_Row1, SI=>SI_Launch, SE=>SE_Launch, Clk=>Clk_Launch, ClkEn=>'1', RESET=>RESET, SO=>SO_Launch_int, Q=>Launch_Row1); MUXD_ScanFF_Row2: entity work.MUXD_ScanFF_Row(beh) generic map (NUM_SFFs=>DESIGN_WIDTH_NB) port map (D=>Launch_Row2, SI=>SO_Launch_int, SE=>SE_Launch, Clk=>Clk_Launch, ClkEn=>'1', RESET=>RESET, SO=>open, Q=>Launch_Row2); -- Choice must be locally static for simulations with launch_ctrl_reg select AES_INPUTs <= Launch_Row1 when (255 downto 0 => '0'), Launch_Row2 when others; -- AES_INPUTs <= Launch_Row1 when (DESIGN_WIDTH_NB-1 downto 0 => '0'), key_m(0)(3,3) <= AES_INPUTs(255 downto 248); key_m(0)(3,2) <= AES_INPUTs(247 downto 240); key_m(0)(3,1) <= AES_INPUTs(239 downto 232); key_m(0)(3,0) <= AES_INPUTs(231 downto 224); key_m(0)(2,3) <= AES_INPUTs(223 downto 216); key_m(0)(2,2) <= AES_INPUTs(215 downto 208); key_m(0)(2,1) <= AES_INPUTs(207 downto 200); key_m(0)(2,0) <= AES_INPUTs(199 downto 192); key_m(0)(1,3) <= AES_INPUTs(191 downto 184); key_m(0)(1,2) <= AES_INPUTs(183 downto 176); key_m(0)(1,1) <= AES_INPUTs(175 downto 168); key_m(0)(1,0) <= AES_INPUTs(167 downto 160); key_m(0)(0,3) <= AES_INPUTs(159 downto 152); key_m(0)(0,2) <= AES_INPUTs(151 downto 144); key_m(0)(0,1) <= AES_INPUTs(143 downto 136); key_m(0)(0,0) <= AES_INPUTs(135 downto 128); textnet_m_a(0)(3,3) <= AES_INPUTs(127 downto 120); textnet_m_a(0)(3,2) <= AES_INPUTs(119 downto 112); textnet_m_a(0)(3,1) <= AES_INPUTs(111 downto 104); textnet_m_a(0)(3,0) <= AES_INPUTs(103 downto 96); textnet_m_a(0)(2,3) <= AES_INPUTs(95 downto 88); textnet_m_a(0)(2,2) <= AES_INPUTs(87 downto 80); textnet_m_a(0)(2,1) <= AES_INPUTs(79 downto 72); textnet_m_a(0)(2,0) <= AES_INPUTs(71 downto 64); textnet_m_a(0)(1,3) <= AES_INPUTs(63 downto 56); textnet_m_a(0)(1,2) <= AES_INPUTs(55 downto 48); textnet_m_a(0)(1,1) <= AES_INPUTs(47 downto 40); textnet_m_a(0)(1,0) <= AES_INPUTs(39 downto 32); textnet_m_a(0)(0,3) <= AES_INPUTs(31 downto 24); textnet_m_a(0)(0,2) <= AES_INPUTs(23 downto 16); textnet_m_a(0)(0,1) <= AES_INPUTs(15 downto 8); textnet_m_a(0)(0,0) <= AES_INPUTs(7 downto 0); -- ================================================== add: addkey port map(roundkey=>key_m(0), datain=>textnet_m_a(0), rcon=>rcon(0), dataout=>textnet_a_s(0), fc3=>fc3(0), c0=>c0(0), c1=>c1(0), c2=>c2(0), c3=>c3(0)); sbox: sboxshr port map(blockin=>textnet_a_s(0), fc3=>fc3(0), c0=>c0(0), c1=>c1(0), c2=>c2(0), c3=>c3(0), nextkey=>key_s(0), blockout=>textnet_s_m(0)); mix: colmix port map(datain=>textnet_s_m(0), inrkey=>key_s(0), outrkey=>key_m_o, dataout=>ciphertext_o); -- ================================================== -- Include the 3 header bits here -- these are NEVER loaded into the REBEL row. AES_COuts <= "000" & key_m_o(3,3) & key_m_o(3,2) & key_m_o(3,1) & key_m_o(3,0) & key_m_o(2,3) & key_m_o(2,2) & key_m_o(2,1) & key_m_o(2,0) & key_m_o(1,3) & key_m_o(1,2) & key_m_o(1,1) & key_m_o(1,0) & key_m_o(0,3) & key_m_o(0,2) & key_m_o(0,1) & key_m_o(0,0) & ciphertext_o(3,3) & ciphertext_o(3,2) & ciphertext_o(3,1) & ciphertext_o(3,0) & ciphertext_o(2,3) & ciphertext_o(2,2) & ciphertext_o(2,1) & ciphertext_o(2,0) & ciphertext_o(1,3) & ciphertext_o(1,2) & ciphertext_o(1,1) & ciphertext_o(1,0) & ciphertext_o(0,3) & ciphertext_o(0,2) & ciphertext_o(0,1) & ciphertext_o(0,0) & ((REBEL_LENGTH_NB - DESIGN_WIDTH_NB - 1) downto 0 => '0'); -- Parallel (fast) load of REBEL configuration information. with REBEL_load select REBEL_DIns <= AES_COuts when '0', REBEL_ConfigIns when others; -- Instantiate the REBEL row. REBELRow: entity work.REBEL_MuxScanRow_WL(beh) generic map (NUM_FFs_HD=>3, NUM_FFs=>REBEL_LENGTH_NB) port map (D=>REBEL_DIns(REBEL_LENGTH_NB-1 downto 0), REBEL_load=>REBEL_load, D_HD=>REBEL_DIns(REBEL_LENGTH_NB+2 downto REBEL_LENGTH_NB), SE=>'0', RESET=>RESET, Clk_Capture=>Clk_Capture, ClkEn_Capture=>ClkEn_Capture, FDMode=>REBEL_FDMode, QMPrevRow=>'0', QM=>REBEL_QMOuts, Q=>REBEL_QOuts); end rtl;