ECE 545 Lecture 11 Addendum Controllers for Keccak_F and AES George Mason University
ECE 448 FPGA and ASIC Design with VHDL Keccak_F
1600 din start done Keccak_F rst 1600 dout ready
Note: Bold line represents a 1600 bit bus unless specified otherwise din round 5 0 1 sel_in RC ROM rin Round en_in rc 64 rout dout
din key clk rst start din key start Keccak_F Datapath dout en_in sel_in round 5 rst en_in sel_in round ready Keccak_F Control done dout ready done Note: Bold line represents a 1600 bit bus unless specified otherwise
rst RESET WAIT_START round = 0 ready DONE done ready round = 0 N start? Y sel_in en_in N PROCESS Y round= RNDS 1? en_in Note: RNDS=G_ROUNDS round++
library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all; entity Keccak_F_Control is generic ( G_RNDS : integer := 24 --! Number of round_rs for the permutation ); port ( --! Global signals clk : in std_logic; rst : in std_logic; --! External signals start : in std_logic; --! Start signal ready : out std_logic; --! Ready signal done : out std_logic; --! Done signal --! Internal signals round : out std_logic_vector(4 downto 0); sel_in : out std_logic; en_in : out std_logic ); end Keccak_F_Control;
architecture behav of Keccak_F_Control is type type_state is (S_RESET, S_WAIT_START, S_PROCESS, S_DONE); signal state : type_state; signal state_next : type_state; signal round_r : std_logic_vector(4 downto 0); signal round_next : std_logic_vector(4 downto 0); begin pctrl: process( clk ) begin if rising_edge( clk ) then if rst = '1' then state <= S_RESET; round_r <= (others => '0'); else state <= state_next; round_r <= round_next; end process; round <= round_r;
pcomb: process(state, round_r, start) begin --! Default values state_next <= state; round_next <= round_r; ready <= '0'; sel_in <= '0'; en_in <= '0'; done <= '0'; case state is when S_RESET => round_next <= (others => '0'); state_next <= S_WAIT_START; when S_WAIT_START => ready <= '1'; if (start = '1') then en_in <= '1'; sel_in <= '1'; round_next <= round_r + 1; state_next <= S_PROCESS;
when S_PROCESS => en_in <= '1'; if (round_r = G_RNDS-1) then round_next <= (others => '0'); state_next <= S_DONE; else round_next <= round_r + 1; when S_DONE => done <= '1'; ready <= '1'; if (start = '1') then en_in <= '1'; sel_in <= '1'; round_next <= round_r + 1; state_next <= S_PROCESS; else state_next <= S_WAIT_START; end case; end process; end behav;
AES_Enc ECE 448 FPGA and ASIC Design with VHDL 11
128 128 start din key done init done_init rst AES_Enc 128 dout ready
Note: Bold line represents a 128 bit bus unless specified otherwise din 0 1 din Round sel_in en_in rkey key we dout en_fkey wr_rkey RAM din addr 0 1 sel_fkey ki KeyUpdate dout_fdb dout en_rkey round round ko dout
din key 128 128 clk rst init start din key init start Enc Datapath 128 dout dout en_rkey wr_rkey en_fkey sel_fkey en_in sel_in round Note: Bold line represents a 128 bit bus unless specified otherwise 4 rst en_rkey wr_rkey en_fkey sel_fkey en_in sel_in round ready Enc Control done_init done ready done done_init
rst RESET round = 0 done_init_s round=0 WAIT_START ready done_s round=0 N Y round=0? N Y round= RNDS 1? init? Y N N start? Y N Y round= RNDS 1? sel_fkey en_fkey INIT round++ wr_rkey Note: Output of "done" and "done_init" signals are registered. RNDS = G_ROUNDS sel_in en_in en_rkey PROCESS en_rkey en_in round++
Registered Outputs done_s and done_init_s are outputs of the Mealy type done and done_init are the corresponding outputs of the Moore type done and done_init become ac7ve at the rising edge of the clock if done_s and done_init_s are already ac7ve when this edge happens Pulses at the outputs done_s and done_init_s last for a frac7on of a clock period. Pulses at the outputs done and done_init last for the en7re following clock period.
library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all; use ieee.numeric_std.all; use work.aes_pkg.all; entity AES_Enc_Control is generic ( G_RNDS : integer := AES_ROUNDS); port( clk : in std_logic; rst : in std_logic; start : in std_logic; init : in std_logic; sel_fkey : out std_logic; en_fkey : out std_logic; en_rkey : out std_logic; wr_rkey : out std_logic; round : out std_logic_vector(3 downto 0); sel_in : out std_logic; en_in : out std_logic; ready : out std_logic; done : out std_logic; done_init : out std_logic); end AES_Enc_Control;
architecture behav of AES_Enc_Control is type t_state is (S_RESET, S_WAIT_START, S_INIT, S_PROCESS); signal state : t_state; signal state_next : t_state; signal round_r : std_logic_vector(3 downto 0); signal round_next : std_logic_vector(3 downto 0); signal done_s : std_logic; signal done_init_s : std_logic; begin p_fsm: process(clk) begin if rising_edge(clk) then if (rst = '1') then state <= S_RESET; else state <= state_next; round_r <= round_next; done <= done_s; done_init <= done_init_s; end process; round <= round_r;
p_comb: process(state, round_r, init, start) begin --! Default values state_next <= state; round_next <= round_r; ready <= '0'; en_fkey <= '0'; wr_rkey <= '0'; sel_fkey <= '0'; sel_in <= '0'; en_in <= '0'; en_rkey <= '0'; done_init_s <= '0'; done_s <= '0'; case state is when S_RESET => state_next <= S_WAIT_START; round_next <= (others => '0');
when S_WAIT_START => ready <= '1'; if (init = '1') then en_fkey <= '1'; state_next <= S_INIT; elsif (start = '1') then sel_in <= '1'; en_in <= '1'; en_rkey <= '1'; round_next <= round_r + 1; state_next <= S_PROCESS; when S_INIT => wr_rkey <= '1'; if (round_r = G_RNDS-1) then round_next <= (others => '0'); done_init_s <= '1'; state_next <= S_WAIT_START; else if (round_r = 0) then sel_fkey <= '1'; round_next <= round_r + 1;
when S_PROCESS => en_rkey <= '1'; en_in <= '1'; if (round_r = G_RNDS-1) then round_next <= (others => '0'); done_s <= '1'; state_next <= S_WAIT_START; else round_next <= round_r + 1; end case; end process; end behav;
Advanced Coding Style for the Datapath Note: Bold line represents a 128 bit bus unless specified otherwise din 0 1 din Round sel_in en_in rkey key we dout en_fkey wr_rkey RAM din addr 0 1 sel_fkey ki KeyUpdate dout_fdb dout en_rkey round round ko dout
library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; use work.aes_pkg.all; entity AES_Enc_Datapath is port( clk : in std_logic; rst : in std_logic; din : in t_aes_state; key : in t_aes_state; dout : out t_aes_state; sel_fkey : in std_logic; en_fkey : in std_logic; en_rkey : in std_logic; wr_rkey : in std_logic; round : in std_logic_vector(3 downto 0); sel_in : in std_logic; en_in : in std_logic); end AES_Enc_Datapath;
architecture structure of AES_Enc_Datapath is signal from_reg : t_aes_state; signal from_round_fdb : t_aes_state; signal ki_state : t_aes_state; signal ko_state : t_aes_state; signal fkey : t_aes_state; signal rkey_state : t_aes_state; signal ko_reg : t_aes_state; signal ko : std_logic_vector(aes_block_size-1 downto 0); signal rkey : std_logic_vector(aes_block_size-1 downto 0); type t_key_ram is array (0 to 15) of std_logic_vector(aes_block_size-1 downto 0); signal key_ram : t_key_ram; begin u_inv_ko: entity work.aes_invmap(structure) port map ( ii => ko_state, oo => ko); u_map_rkey: entity work.aes_map(structure) port map ( ii => rkey, oo => rkey_state);
p_reg: process(clk) begin if rising_edge(clk) then if en_in = '1' then if sel_in = '1' then for i in 0 to 3 loop for j in 0 to 3 loop from_reg(j,i) <= din(j,i) xor fkey(j,i); end loop; end loop; else from_reg <= from_round_fdb; if en_fkey = '1' then fkey <= key;
if wr_rkey = '1' then key_ram(to_integer(unsigned(round))) <= ko; ko_reg <= ko_state; if en_rkey = '1' then rkey <= key_ram(to_integer(unsigned(round))); end process;
u_round: entity work.aes_round(basic) port map ( din => from_reg, rkey => rkey_state, dout_fdb => from_round_fdb, dout => dout); --! Key Expansion ki_state <= fkey when sel_fkey = '1' else ko_reg; u_keyexp: entity work.aes_keyupdate(key_size_128) port map ( round => round, ki => ki_state, ko => ko_state); end structure;
ECE 448 FPGA and ASIC Design with VHDL AES_EncDec
128 din start decrypt init 128 key done done_init AES_EncDec rst ready dout 128
KeyUpdate round ko ki din en_fkey 4 sel_fkey 1 0 round Note: Bold line represents a 128 bit bus unless specified otherwise key en_lkey 0 2 1 2 sel_in round invround 4 4 en_in 0 1 din Round rkey rkey din Inv Round din addr RAM we dout sel_round wr_rkey dout_fdb dout dout dout_fdb en_rkey 0 1 sel_decrypt dout
din key 128 128 rst clk start init decrypt din key start init decrypt EncDec Datapath sel_decrypt invround round sel_round sel_in en_in en_rkey wr_rkey en_lkey en_fkey sel_fkey dout 128 dout rst sel_decrypt invround round sel_round sel_in en_in en_rkey wr_rkey en_lkey en_fkey sel_fkey ready done_init Note: Bold line represents a 128 bit bus unless specified otherwise 4 4 2 EncDec Control done ready done done_init
rst round++ en_lkey N N INIT_KEY round = 1 done_init_s Y round= RNDS? sel_fkey Y round = 0? wr_rkey RESET WAIT_START round = 1 invround=rnds 1 ready init? Y round = 0 en_lkey en_fkey Note: Output of "done" and "done_init" signals are registered. RNDS = G_ROUNDS N start? decrypt_r = decrypt sel_in=2 en_in en_rkey decrypt? N N Y Y round = 1 invround=rnds 1 done_s sel_round sel_fkey Y round= RNDS? N N PROCESS round++ invround sel_round sel_in=1 Y decrypt_r? en_rkey en_in
Using a Pulse to Store the Current Value of an Input decrypt is an input to FSM that lasts for just one clock cycle we store its value for future use in the register decrypt_r, as represented in the ASM chart using the ac7on decrypt_r = decrypt in order to perform this ac7on in the VHDL code, the assignment decrypt_r = decrypt is represented as an ac7ve value of the enable signal of the register decrypt_r, called en_decrypt_s
library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all; use ieee.numeric_std.all; use work.aes_pkg.all; entity AES_EncDec_Control is generic ( G_RNDS : integer := AES_ROUNDS); port( clk : in std_logic; rst : in std_logic; --! Internal sel_decrypt : out std_logic; invround : out std_logic_vector(3 downto 0); round : out std_logic_vector(3 downto 0); en_rkey : out std_logic; wr_rkey : out std_logic; en_fkey : out std_logic; en_lkey : out std_logic; sel_fkey : out std_logic; sel_round : out std_logic; sel_in : out std_logic_vector(1 downto 0); en_in : out std_logic;
--! External init : in std_logic; done_init : out std_logic; start : in std_logic; decrypt : in std_logic; ready : out std_logic; done : out std_logic); end AES_EncDec_Control;
architecture behav of AES_EncDec_Control is --! Internal Registers type t_state is (S_RESET, S_WAIT_START, S_INIT_KEY, S_PROCESS); signal state : t_state; signal state_next : t_state; signal round_r : std_logic_vector(3 downto 0); signal round_next : std_logic_vector(3 downto 0); signal invround_r : std_logic_vector(3 downto 0); signal invround_next : std_logic_vector(3 downto 0); signal decrypt_r : std_logic; signal done_r : std_logic; signal done_init_r : std_logic; --! Internal signals signal en_decrypt_s signal done_s signal done_init_s : std_logic; : std_logic; : std_logic;
begin p_fsm: process(clk) begin if rising_edge(clk) then if (rst = '1') then state <= S_RESET; else state <= state_next; if (en_decrypt_s = '1') then decrypt_r <= decrypt; round_r <= round_next; invround_r <= invround_next; done_init_r <= done_init_s; done_r <= done_s; end process; round <= round_r; invround <= invround_r; sel_decrypt <= decrypt_r; done_init <= done_init_r; done <= done_r;
p_comb: process(state, round_r, init, start, decrypt_r, decrypt) begin --! Default values state_next <= state; round_next <= round_r; ready <= '0'; en_lkey <= '0'; en_fkey <= '0'; wr_rkey <= '0'; sel_fkey <= '0'; sel_in <= "00"; en_in <= '0'; sel_round <= '0'; en_rkey <= '0'; en_decrypt_s <= '0'; done_s <= '0'; done_init_s <= '0'; case state is when S_RESET => round_next <= std_logic_vector(to_unsigned(1,4)); invround_next <= std_logic_vector(to_unsigned(g_rnds-1,4)); state_next <= S_WAIT_START;
when S_WAIT_START => ready <= '1'; if (init = '1') then round_next <= (others => '0'); en_lkey <= '1'; en_fkey <= '1'; state_next <= S_INIT_KEY; elsif (start = '1') then en_decrypt_s <= '1'; sel_in <= "10"; en_in <= '1'; en_rkey <= '1'; if (decrypt = '1') then sel_round <= '1'; else sel_fkey <= '1'; round_next <= round_r + 1; invround_next <= invround_r - 1; state_next <= S_PROCESS;
when S_INIT_KEY => wr_rkey <= '1'; if (round_r = 0) then sel_fkey <= '1'; if (round_r = G_RNDS) then round_next <= std_logic_vector(to_unsigned(1,4)); done_init_s <= '1'; state_next <= S_WAIT_START; else round_next <= round_r + 1; en_lkey <= '1';
when S_PROCESS => en_rkey <= '1'; en_in <= '1'; if (decrypt_r = '1') then sel_round <= '1'; sel_in <= "01"; if (round_r = G_RNDS) then round_next <= std_logic_vector(to_unsigned(1,4)); invround_next <= std_logic_vector(to_unsigned(g_rnds-1,4)); done_s <= '1'; state_next <= S_WAIT_START; else round_next <= round_r + 1; invround_next <= invround_r - 1; end case; end process; end behav;