--- /dev/null
+library ieee;\r
+use ieee.std_logic_1164.all;\r
+use ieee.numeric_std.all;\r
+\r
+library work;\r
+\r
+entity fwd_test is\r
+ port(\r
+ CLK : in std_logic;\r
+ RESET : in std_logic;\r
+ --\r
+ FWD_ENABLE_IN : in std_logic := '0';\r
+ FWD_DELAY_IN : in std_logic_vector(15 downto 0) := x"0010";\r
+ FWD_SIZE_IN : in std_logic_vector(15 downto 0) := x"0010";\r
+ FWD_START_IN : in std_logic := '0';\r
+ FWD_BUSY_OUT : out std_logic;\r
+ --\r
+ FWD_READY_IN : in std_logic := '0';\r
+ FWD_FULL_IN : in std_logic := '0';\r
+ FWD_DATA_OUT : out std_logic_vector(7 downto 0);\r
+ FWD_DATA_VALID_OUT : out std_logic;\r
+ FWD_SOP_OUT : out std_logic;\r
+ FWD_EOP_OUT : out std_logic;\r
+ --\r
+ DEBUG : out std_logic_vector(15 downto 0)\r
+ );\r
+end entity fwd_test;\r
+\r
+architecture fwd_test_arch of fwd_test is\r
+\r
+-- Components\r
+\r
+-- state machine signals\r
+ type state_t is (IDLE, START, DATA, CLEANUP, DELAY);\r
+ signal STATE, NEXT_STATE : state_t;\r
+\r
+-- Signals\r
+ signal sop_x : std_logic;\r
+ signal sop : std_logic;\r
+ signal eop_x : std_logic;\r
+ signal eop : std_logic;\r
+ signal rst_x : std_logic;\r
+ signal rst : std_logic;\r
+\r
+ signal test_cnt : unsigned(15 downto 0);\r
+ signal test_data : unsigned(7 downto 0);\r
+ signal test_done_x : std_logic;\r
+ signal test_done : std_logic;\r
+ signal test_ce_x : std_logic;\r
+ signal delay_ce_x : std_logic;\r
+\r
+begin\r
+\r
+ -----------------------------------------------------------\r
+ -- Test data generator\r
+ -----------------------------------------------------------\r
+ THE_TEST_DATA_PROC: process( CLK )\r
+ begin\r
+ if( rising_edge(CLK) ) then\r
+ if ( (RESET = '1') or (sop = '1') ) then\r
+ test_data <= (others => '0');\r
+ elsif( test_ce_x = '1' ) then\r
+ test_data <= test_data + 1;\r
+ end if;\r
+ end if;\r
+ end process THE_TEST_DATA_PROC;\r
+\r
+ test_ce_x <= '1' when ((STATE = DATA) and (FWD_FULL_IN = '0'))\r
+ else '0';\r
+\r
+ FWD_DATA_OUT <= std_logic_vector(test_data);\r
+\r
+ FWD_DATA_VALID_OUT <= test_ce_x;\r
+\r
+ -----------------------------------------------------------\r
+ -- Test counter\r
+ -----------------------------------------------------------\r
+ THE_TEST_CNT_PROC: process( CLK )\r
+ begin\r
+ if( rising_edge(CLK) ) then\r
+ if ( RESET = '1' ) then\r
+ test_cnt <= (others => '1');\r
+ elsif( sop = '1' ) then\r
+ test_cnt <= unsigned(FWD_SIZE_IN);\r
+ elsif( rst = '1' ) then\r
+ test_cnt <= unsigned(FWD_DELAY_IN);\r
+ elsif( (test_ce_x = '1') or (delay_ce_x = '1') ) then\r
+ test_cnt <= test_cnt - 1;\r
+ end if;\r
+ end if;\r
+ end process THE_TEST_CNT_PROC;\r
+\r
+ delay_ce_x <= '1' when (STATE = DELAY) else '0';\r
+\r
+ test_done_x <= '1' when (test_cnt = x"0001") else '0';\r
+\r
+ test_done <= test_done_x when rising_edge(CLK);\r
+\r
+ eop_x <= '1' when ((test_cnt = x"0001") and (STATE = DATA)) else '0';\r
+\r
+ eop <= eop_x when rising_edge(CLK);\r
+\r
+ -----------------------------------------------------------\r
+ -- statemachine: clocked process\r
+ -----------------------------------------------------------\r
+ THE_FSM: process( CLK )\r
+ begin\r
+ if( rising_edge(CLK) ) then\r
+ if( RESET = '1' ) then\r
+ STATE <= IDLE;\r
+ sop <= '0';\r
+ rst <= '0';\r
+ else\r
+ STATE <= NEXT_STATE;\r
+ sop <= sop_x;\r
+ rst <= rst_x;\r
+ end if;\r
+ end if;\r
+ end process THE_FSM;\r
+\r
+ -----------------------------------------------------------\r
+ --\r
+ -----------------------------------------------------------\r
+ THE_STATE_TRANSITIONS: process( STATE, FWD_ENABLE_IN, FWD_START_IN, test_done )\r
+ begin\r
+ sop_x <= '0';\r
+ rst_x <= '0';\r
+\r
+ case STATE is\r
+\r
+ when IDLE =>\r
+ if( (FWD_ENABLE_IN = '1') and (FWD_START_IN = '1') and (FWD_READY_IN = '1') and (FWD_FULL_IN = '0') ) then\r
+ NEXT_STATE <= START;\r
+ sop_x <= '1';\r
+ else\r
+ NEXT_STATE <= IDLE;\r
+ end if;\r
+\r
+ when START =>\r
+ if( FWD_FULL_IN = '0' ) then\r
+ NEXT_STATE <= DATA;\r
+ else\r
+ NEXT_STATE <= START;\r
+ end if;\r
+\r
+ when DATA =>\r
+ if( test_done = '1' ) then\r
+ NEXT_STATE <= CLEANUP;\r
+ rst_x <= '1';\r
+ else\r
+ NEXT_STATE <= DATA;\r
+ end if;\r
+\r
+ when CLEANUP =>\r
+ NEXT_STATE <= DELAY;\r
+\r
+ when DELAY =>\r
+ if( test_done = '1' ) then\r
+ NEXT_STATE <= IDLE;\r
+ else\r
+ NEXT_STATE <= DELAY;\r
+ end if;\r
+\r
+ when others =>\r
+ NEXT_STATE <= IDLE;\r
+ end case;\r
+ end process THE_STATE_TRANSITIONS;\r
+\r
+ FWD_SOP_OUT <= sop;\r
+ FWD_EOP_OUT <= eop;\r
+\r
+ FWD_BUSY_OUT <= '1' when (STATE /= IDLE) else '0';\r
+\r
+end architecture;\r
--- /dev/null
+library ieee;\r
+use ieee.std_logic_1164.all;\r
+use ieee.numeric_std.all;\r
+\r
+library work;\r
+\r
+entity fwd_test_random is\r
+ port(\r
+ CLK : in std_logic;\r
+ RESET : in std_logic;\r
+ --\r
+ FWD_ENABLE_IN : in std_logic := '0';\r
+ FWD_DELAY_IN : in std_logic_vector(15 downto 0) := x"0000";\r
+ FWD_START_IN : in std_logic := '0';\r
+ FWD_BUSY_OUT : out std_logic;\r
+ --\r
+ FWD_READY_IN : in std_logic := '0';\r
+ FWD_FULL_IN : in std_logic := '0';\r
+ FWD_DATA_OUT : out std_logic_vector(7 downto 0);\r
+ FWD_DATA_VALID_OUT : out std_logic;\r
+ FWD_SOP_OUT : out std_logic;\r
+ FWD_EOP_OUT : out std_logic;\r
+ --\r
+ DEBUG : out std_logic_vector(15 downto 0)\r
+ );\r
+end entity fwd_test_random;\r
+\r
+architecture fwd_test_random_arch of fwd_test_random is\r
+\r
+-- Components\r
+ component rng_trivium is\r
+ generic(\r
+ NUM_BITS: integer range 1 to 64 := 32;\r
+ -- Default key.\r
+ INIT_KEY: std_logic_vector(79 downto 0) := x"00000000000000000000";\r
+ INIT_IV: std_logic_vector(79 downto 0) := x"00000000000000000000"\r
+ );\r
+ port(\r
+ CLK : in std_logic;\r
+ RESET : in std_logic;\r
+ RESEED_IN : in std_logic;\r
+ NEWKEY_IN : in std_logic_vector(79 downto 0);\r
+ NEWIV_IN : in std_logic_vector(79 downto 0);\r
+ READY_IN : in std_logic;\r
+ VALID_OUT : out std_logic;\r
+ DATA_OUT : out std_logic_vector(NUM_BITS-1 downto 0) \r
+ );\r
+ end component rng_trivium;\r
+\r
+-- state machine signals\r
+ type state_t is (IDLE, START, FLH, FLL, DATA, CLEANUP, DELAY);\r
+ signal STATE, NEXT_STATE : state_t;\r
+\r
+-- Signals\r
+ signal sop_x : std_logic;\r
+ signal sop : std_logic;\r
+ signal eop_x : std_logic;\r
+ signal eop : std_logic;\r
+ signal rst_x : std_logic;\r
+ signal rst : std_logic;\r
+ \r
+ signal frame_len : std_logic_vector(15 downto 0);\r
+\r
+ signal test_cnt : unsigned(15 downto 0);\r
+ signal test_data : std_logic_vector(15 downto 0);\r
+ signal test_done_x : std_logic;\r
+ signal test_done : std_logic;\r
+ signal test_ce_x : std_logic;\r
+ signal delay_ce_x : std_logic;\r
+\r
+ signal data_valid_x : std_logic;\r
+\r
+begin\r
+\r
+ -----------------------------------------------------------\r
+ -- Test data generator\r
+ -----------------------------------------------------------\r
+ THE_PRNG: rng_trivium\r
+ generic map(\r
+ NUM_BITS => 16,\r
+ INIT_KEY => x"00000000000000000000",\r
+ INIT_IV => x"00000000000000000000"\r
+ )\r
+ port map(\r
+ CLK => CLK,\r
+ RESET => RESET,\r
+ RESEED_IN => '0',\r
+ NEWKEY_IN => (others => '0'),\r
+ NEWIV_IN => (others => '0'),\r
+ READY_IN => test_ce_x,\r
+ VALID_OUT => open,\r
+ DATA_OUT => test_data \r
+ );\r
+\r
+ -- store the random frame length\r
+ THE_FL_PROC: process( CLK )\r
+ begin\r
+ if( rising_edge(CLK) ) then\r
+ if ( RESET = '1' ) then\r
+ frame_len <= (others => '0');\r
+ elsif( sop = '1' ) then\r
+ frame_len <= b"00000" & test_data(8 downto 0) & b"11";\r
+ end if;\r
+ end if;\r
+ end process THE_FL_PROC;\r
+\r
+ -- TAKE CARE HERE: we write two bytes "length"... must be considered carefully.\r
+\r
+ -- new PRNG data is produced when we are idle and in case we wrote a byte \r
+ test_ce_x <= '1' when ((STATE = IDLE) or (data_valid_x = '1'))\r
+ else '0';\r
+ \r
+ -- test data is only written when we are ready\r
+ data_valid_x <= '1' when ((STATE = DATA) or (STATE = FLH) or (STATE = FLL)) and (FWD_FULL_IN = '0')\r
+ else '0';\r
+\r
+ -- multiplex output data\r
+ FWD_DATA_OUT <= frame_len(15 downto 8) when (STATE = FLH) else\r
+ frame_len(7 downto 0) when (STATE = FLL) else\r
+ test_data(7 downto 0) when (STATE = DATA);\r
+\r
+ -- write signal for next stage\r
+ FWD_DATA_VALID_OUT <= data_valid_x;\r
+\r
+--------------------------------------------------------------------------------------------------------------------------\r
+--------------------------------------------------------------------------------------------------------------------------\r
+--------------------------------------------------------------------------------------------------------------------------\r
+\r
+\r
+\r
+ -----------------------------------------------------------\r
+ -- Test counter\r
+ -----------------------------------------------------------\r
+ THE_TEST_CNT_PROC: process( CLK )\r
+ begin\r
+ if( rising_edge(CLK) ) then\r
+ if ( RESET = '1' ) then\r
+ test_cnt <= (others => '1');\r
+ elsif( sop = '1' ) then\r
+ test_cnt <= unsigned(b"00000" & test_data(8 downto 0) & b"11");\r
+ elsif( rst = '1' ) then\r
+ test_cnt <= unsigned(FWD_DELAY_IN);\r
+ elsif( (data_valid_x = '1') or (delay_ce_x = '1') ) then\r
+ test_cnt <= test_cnt - 1;\r
+ end if;\r
+ end if;\r
+ end process THE_TEST_CNT_PROC;\r
+\r
+ delay_ce_x <= '1' when (STATE = DELAY) else '0';\r
+\r
+ test_done_x <= '1' when (test_cnt = x"0000") else '0';\r
+\r
+ test_done <= test_done_x when rising_edge(CLK);\r
+\r
+ eop_x <= '1' when ((test_cnt = x"0000") and (STATE = DATA)) else '0';\r
+\r
+ eop <= eop_x when rising_edge(CLK);\r
+\r
+ -----------------------------------------------------------\r
+ -- statemachine: clocked process\r
+ -----------------------------------------------------------\r
+ THE_FSM: process( CLK )\r
+ begin\r
+ if( rising_edge(CLK) ) then\r
+ if( RESET = '1' ) then\r
+ STATE <= IDLE;\r
+ sop <= '0';\r
+ rst <= '0';\r
+ else\r
+ STATE <= NEXT_STATE;\r
+ sop <= sop_x;\r
+ rst <= rst_x;\r
+ end if;\r
+ end if;\r
+ end process THE_FSM;\r
+\r
+ -----------------------------------------------------------\r
+ --\r
+ -----------------------------------------------------------\r
+ THE_STATE_TRANSITIONS: process( STATE, FWD_ENABLE_IN, FWD_START_IN, test_done )\r
+ begin\r
+ sop_x <= '0';\r
+ rst_x <= '0';\r
+\r
+ case STATE is\r
+\r
+ when IDLE =>\r
+ if( (FWD_ENABLE_IN = '1') and (FWD_START_IN = '1') and (FWD_READY_IN = '1') and (FWD_FULL_IN = '0') ) then\r
+ NEXT_STATE <= START;\r
+ sop_x <= '1';\r
+ else\r
+ NEXT_STATE <= IDLE;\r
+ end if;\r
+\r
+ when START =>\r
+ if( FWD_FULL_IN = '0' ) then\r
+ NEXT_STATE <= FLH;\r
+ else\r
+ NEXT_STATE <= START;\r
+ end if;\r
+\r
+ when FLH =>\r
+ if( FWD_FULL_IN = '0' ) then\r
+ NEXT_STATE <= FLL;\r
+ else\r
+ NEXT_STATE <= FLH;\r
+ end if;\r
+\r
+ when FLL =>\r
+ if( FWD_FULL_IN = '0' ) then\r
+ NEXT_STATE <= DATA;\r
+ else\r
+ NEXT_STATE <= FLL;\r
+ end if;\r
+\r
+ when DATA =>\r
+ if( test_done = '1' ) then\r
+ NEXT_STATE <= CLEANUP;\r
+ rst_x <= '1';\r
+ else\r
+ NEXT_STATE <= DATA;\r
+ end if;\r
+\r
+ when CLEANUP =>\r
+ NEXT_STATE <= DELAY;\r
+\r
+ when DELAY =>\r
+ if( test_done = '1' ) then\r
+ NEXT_STATE <= IDLE;\r
+ else\r
+ NEXT_STATE <= DELAY;\r
+ end if;\r
+\r
+ when others =>\r
+ NEXT_STATE <= IDLE;\r
+ end case;\r
+ end process THE_STATE_TRANSITIONS;\r
+\r
+ FWD_SOP_OUT <= sop;\r
+ FWD_EOP_OUT <= eop;\r
+\r
+ FWD_BUSY_OUT <= '1' when (STATE /= IDLE) else '0';\r
+\r
+end architecture;\r
--- /dev/null
+--\r
+-- Pseudo Random Number Generator "Trivium".\r
+--\r
+-- Author: Joris van Rantwijk <joris@jorisvr.nl>\r
+--\r
+-- This is a pseudo-random number generator in synthesizable VHDL.\r
+-- The generator produces up to 64 new random bits on every clock cycle.\r
+--\r
+-- The algorithm "Trivium" is by Christophe De Canniere and Bart Preneel.\r
+-- See also:\r
+-- C. De Canniere, B. Preneel, "Trivium Specifications",\r
+-- http://www.ecrypt.eu.org/stream/p3ciphers/trivium/trivium_p3.pdf\r
+--\r
+-- The eSTREAM portfolio page for Trivium:\r
+-- http://www.ecrypt.eu.org/stream/e2-trivium.html\r
+--\r
+-- The generator requires an 80-bit key and an 80-bit initialization\r
+-- vector. Defaults for these values must be supplied at compile time\r
+-- and will be used to initialize the generator at reset. The generator\r
+-- also supports re-keying at run time.\r
+--\r
+-- After reset and after re-seeding, at least (1152/num_bits) clock cycles\r
+-- are needed before valid random data appears on the output.\r
+--\r
+-- NOTE: This generator is designed to produce up to 2**64 bits\r
+-- of secure random data. If more than 2**64 bits are generated\r
+-- with the same key and IV, it becomes inceasingly likely that\r
+-- the output contains patterns and correlations.\r
+--\r
+\r
+--\r
+-- Copyright (C) 2016 Joris van Rantwijk\r
+--\r
+-- This code is free software; you can redistribute it and/or\r
+-- modify it under the terms of the GNU Lesser General Public\r
+-- License as published by the Free Software Foundation; either\r
+-- version 2.1 of the License, or (at your option) any later version.\r
+--\r
+-- See <https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html>\r
+--\r
+\r
+library ieee;\r
+use ieee.std_logic_1164.all;\r
+use ieee.numeric_std.all;\r
+\r
+entity rng_trivium is\r
+ generic(\r
+ NUM_BITS: integer range 1 to 64 := 32;\r
+ -- Default key.\r
+ INIT_KEY: std_logic_vector(79 downto 0) := x"00000000000000000000";\r
+ INIT_IV: std_logic_vector(79 downto 0) := x"00000000000000000000"\r
+ );\r
+ port(\r
+ CLK : in std_logic;\r
+ RESET : in std_logic;\r
+ RESEED_IN : in std_logic;\r
+ NEWKEY_IN : in std_logic_vector(79 downto 0);\r
+ NEWIV_IN : in std_logic_vector(79 downto 0);\r
+ READY_IN : in std_logic;\r
+ VALID_OUT : out std_logic;\r
+ DATA_OUT : out std_logic_vector(NUM_BITS-1 downto 0) \r
+ );\r
+end entity;\r
+\r
+architecture trivium_arch of rng_trivium is\r
+ -- Prepare initial state vector for given key and IV.\r
+ --\r
+ -- NOTE: Elements 0 .. 79 from the key vector are mapped to\r
+ -- to state elements s_80 .. s_1.\r
+ -- Elements 0 .. 79 from the IV vector are mapped\r
+ -- to state elements s_173 .. s_94.\r
+ --\r
+ -- This deviates from the original Trivium specification\r
+ -- but is in line with the phase-3, API-compliant implementation\r
+ -- of Trivium as published on the ECRYPT website.\r
+ --\r
+ function make_initial_state(nkey, niv: in std_logic_vector)\r
+ return std_logic_vector\r
+ is\r
+ variable s: std_logic_vector(287 downto 0);\r
+ begin\r
+ assert nkey'length = 80;\r
+ assert niv'length = 80;\r
+\r
+ s := (others => '0');\r
+\r
+ for k in 0 to 79 loop\r
+ s(79-k) := nkey(k);\r
+ end loop;\r
+\r
+ for k in 0 to 79 loop\r
+ s(93+79-k) := niv(k);\r
+ end loop;\r
+\r
+ s(288-1 downto 288-3) := "111";\r
+\r
+ return s;\r
+ end function;\r
+\r
+ signal reg_state : std_logic_vector(287 downto 0) := make_initial_state(INIT_KEY, INIT_IV);\r
+ signal reg_valid_wait : unsigned(10 downto 0) := (others => '0');\r
+ signal reg_valid : std_logic := '0';\r
+ signal reg_output : std_logic_vector(NUM_BITS-1 downto 0);\r
+\r
+begin\r
+\r
+ -- Check that num_bits is a power of 2.\r
+ assert (64 / NUM_BITS) * NUM_BITS = 64;\r
+\r
+ -- Drive output signal.\r
+ VALID_OUT <= reg_valid;\r
+ DATA_OUT <= reg_output;\r
+\r
+ -- Synchronous process.\r
+ process( CLK ) is\r
+ variable t1, t2, t3: std_logic_vector(NUM_BITS-1 downto 0);\r
+ begin\r
+ if rising_edge(CLK) then\r
+ -- Determine valid output state.\r
+ -- Delay by 4*288/num_bits clock cycles after re-seeding.\r
+ if reg_valid_wait = 4*288/NUM_BITS then\r
+ reg_valid <= '1';\r
+ end if;\r
+\r
+ if reg_valid = '0' then\r
+ reg_valid_wait <= reg_valid_wait + 1;\r
+ end if;\r
+\r
+ if READY_IN = '1' or reg_valid = '0' then\r
+ -- Prepare output word.\r
+ t1 := reg_state(66-1 downto 66-NUM_BITS) xor reg_state(93-1 downto 93-NUM_BITS);\r
+ t2 := reg_state(162-1 downto 162-NUM_BITS) xor reg_state(177-1 downto 177-NUM_BITS);\r
+ t3 := reg_state(243-1 downto 243-NUM_BITS) xor reg_state(288-1 downto 288-NUM_BITS);\r
+\r
+ -- Create output word such that index 0 of the output\r
+ -- contains the earliest-generated bit and index (num_bits-1)\r
+ -- of the output contains the last-generated bit.\r
+ for k in 0 to NUM_BITS-1 loop\r
+ reg_output(NUM_BITS-1-k) <= t1(k) xor t2(k) xor t3(k);\r
+ end loop;\r
+\r
+ -- Update internal state.\r
+ t1 := t1 xor (reg_state(91-1 downto 91-NUM_BITS) and reg_state(92-1 downto 92-NUM_BITS)) xor reg_state(171-1 downto 171-NUM_BITS);\r
+ t2 := t2 xor (reg_state(175-1 downto 175-NUM_BITS) and reg_state(176-1 downto 176-NUM_BITS)) xor reg_state(264-1 downto 264-NUM_BITS);\r
+ t3 := t3 xor (reg_state(286-1 downto 286-NUM_BITS) and reg_state(287-1 downto 287-NUM_BITS)) xor reg_state(69-1 downto 69-NUM_BITS);\r
+\r
+ reg_state(93-1 downto 0) <= reg_state(93-1-NUM_BITS downto 0) & t3;\r
+ reg_state(177-1 downto 94-1) <= reg_state(177-1-NUM_BITS downto 94-1) & t1;\r
+ reg_state(288-1 downto 178-1) <= reg_state(288-1-NUM_BITS downto 178-1) & t2;\r
+ end if;\r
+\r
+ -- Re-seed function.\r
+ if RESEED_IN = '1' then\r
+ reg_valid <= '0';\r
+ reg_valid_wait <= (others => '0');\r
+ reg_state <= make_initial_state(NEWKEY_IN, NEWIV_IN);\r
+ end if;\r
+\r
+ -- Synchronous reset.\r
+ if RESET = '1' then\r
+ reg_valid <= '0';\r
+ reg_valid_wait <= (others => '0');\r
+ reg_state <= make_initial_state(INIT_KEY, INIT_IV);\r
+ reg_output <= (others => '0');\r
+ end if;\r
+\r
+ end if;\r
+ end process;\r
+\r
+end architecture;\r
+\r