------------------------------------------------------------
-- Copyright: 2011 Integrated Sytems Laboratory, ETH Zurich
-- http://www.iis.ee.ethz.ch/~sha3
------------------------------------------------------------
-------------------------------------------------------------------------------
-- Title : Keccak
-- Project : Schabziger
-------------------------------------------------------------------------------
-- File : keccak_controller.vhd
-- Author : Frank K. Guerkaynak
-- Company : Integrated Systems Laboratory, ETH Zurich
-- Created : 2011-08-10
-- Last update: 2011-08-17
-- Platform : ModelSim (simulation), Synopsys (synthesis)
-- Standard : VHDL'87
-------------------------------------------------------------------------------
-- Description: FSM for Keccak, original by Pietro Gendotti
-------------------------------------------------------------------------------
-- Copyright (c) 2011 Integrated Systems Laboratory, ETH Zurich
-------------------------------------------------------------------------------
-- Revisions :
-- Date Version Author Description
-- 2011-08-10 1.0 kgf Added the BlockDonexSO signal to tell that the
-- computation has reached the last round
-- 2011-08-16 1.1 kgf FinBlockxSI is now registered it will be
-- sampled at the same time as the InEnxEI
-------------------------------------------------------------------------------
library ieee;
use ieee.numeric_std.all;
use ieee.std_logic_1164.all;
entity keccak_controller is
port (
ClkxCI : in std_logic;
RstxRBI : in std_logic;
FinBlockxSI : in std_logic;
INENxEI : in std_logic;
OUTENxEO : out std_logic;
StateSelxSO : out std_logic;
PenUltCyclexSO : out std_logic;
RcntxDO : out unsigned(4 downto 0));
end keccak_controller;
architecture rtl of keccak_controller is
type state is (idle, round);
signal StatexDP, StatexDN : state;
signal RcntxDP, RcntxDN : unsigned(4 downto 0);
-- FinBlockxSI is stored until the last cycle
signal FinBlockxSP, FinBlockxSN : std_logic;
begin -- rtl
p_fsm: process (FinBlockxSI, FinBlockxSP, INENxEI, RcntxDP, StatexDP)
begin -- process p_fsm
StatexDN <= StatexDP;
RcntxDN <= (others => '0'); -- default sets the round to '0'
RcntxDO <= RcntxDP;
OUTENxEO <= '0';
StateSelxSO <= '1';
PenUltCyclexSO <= '0';
FinBlockxSN <= FinBlockxSP;
case StatexDP is
-------------------------------------------------------------------------
when idle =>
if INENxEI = '1' then
StatexDN <= round;
StateSelxSO <= '0';
FinBlockxSN <= FinBlockxSI; -- sample the final block input
end if;
-------------------------------------------------------------------------
when round =>
StateSelxSO <= '1';
if RcntxDP = 22 then -- notify the output one cycle before end
PenUltCyclexSO <= '1';
RcntxDN <= RcntxDP + 1;
elsif RcntxDP = 23 then
if FinBlockxSP = '1' then
OUTENxEO <= '1';
FinBlockxSN <='0'; -- clear the final block, we have the output
if INENxEI= '1' then -- chain directly if possible
StatexDN <= round;
StateSelxSO <= '0';
FinBlockxSN <= FinBlockxSI; -- sample the final block input
else
StatexDN <= idle;
end if;
else
FinBlockxSN <= FinBlockxSI; -- this block is not final, and we
-- have a new block that could be final
StatexDN <= round;
end if;
else
RcntxDN <= RcntxDP + 1;
end if;
-------------------------------------------------------------------------
when others => StatexDN <= idle;
end case;
end process p_fsm;
p_mem : process (ClkxCI, RstxRBI)
begin -- process p_mem
if RstxRBI = '0' then -- asynchronous reset (active low)
StatexDP <= idle;
RcntxDP <= (others => '0');
FinBlockxSP <= '0';
elsif ClkxCI'event and ClkxCI = '1' then -- rising clock edge
StatexDP <= StatexDN;
RcntxDP <= RcntxDN;
FinBlockxSP <= FinBlockxSN;
end if;
end process p_mem;
end rtl;