diff --git a/src/Tests/Type2_key_holder.vhd b/src/Tests/Type2_key_holder.vhd new file mode 100644 index 0000000..a921a16 --- /dev/null +++ b/src/Tests/Type2_key_holder.vhd @@ -0,0 +1,783 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +use work.rtps_package.all; +use work.rtps_config_package.all; +use work.Type2_package.all; + +architecture TYPE2 of key_holder is + + --*****COMPONENT DECLARATION***** + component md5_calculator is + port ( + clk : in std_logic; + reset : in std_logic; + + start : in std_logic; + ack : out std_logic; + + data_in : in std_logic_vector(7 downto 0); + valid_in : in std_logic; + ready_in : out std_logic; + last_word_in : in std_logic; + + hash_out : out std_logic_vector(127 downto 0); + done : out std_logic + ); + end component; + + --*****TYPE DECLARATION***** + -- FSM states. Explained below in detail + type STAGE_TYPE is (IDLE,START_MD5_CALCULATION,GET_PAYLOAD_HEADER,FETCH,ALIGN_IN_STREAM,SKIP_PAYLOAD,DECODE_PAYLOAD,PUSH,ALIGN_OUT_STREAM,SERIALIZE_KEY,GET_KEY_HASH,PUSH_KEY_HASH); + -- ###GENERATED START### + type DECODE_STAGE_TYPE is (GET_ID,GET_TESTSEQUENCE_LENGTH,GET_TESTSEQUENCE_TESTARRAY,GET_TESTSEQUENCE_TESTCHAR,GET_TESTSEQUENCE_TESTWCHAR,GET_TESTSEQUENCE_TESTLONGLONG,GET_TESTSEQUENCE_TESTLONGDOUBLE,TESTSEQUENCE_MEMBER_END,GET_OPTIONAL_HEADER); + type ENCODE_STAGE_TYPE is (WRITE_ID,WRITE_TESTSEQUENCE_LENGTH,WRITE_TESTSEQUENCE_TESTARRAY,TESTSEQUENCE_MEMBER_END); + type TESTSEQUENCE_TESTARRAY_ADDR_TYPE is array (0 to TESTSEQUENCE_MAX_DEPTH-1) of std_logic_vector(TESTSEQUENCE_TESTARRAY_ADDR_WIDTH-1 downto 0); + type TESTSEQUENCE_TESTARRAY_DATA_TYPE is array (0 to TESTSEQUENCE_MAX_DEPTH-1) of std_logic_vector(CDR_OCTET_WIDTH-1 downto 0); + -- ###GENERATED END### + + -- *MAIN PROCESS* + signal stage, stage_next : STAGE_TYPE := IDLE; + signal cnt, cnt_next : natural range 0 to 5 := 0; + signal endian_flag, endian_flag_next : std_logic := '0'; + signal last_word_in_latch, last_word_in_latch_next : std_logic := '0'; + signal decode_error_latch, decode_error_latch_next : std_logic := '0'; + signal align_offset, align_offset_next : unsigned(MAX_ALIGN_OFFSET_WIDTH-1 downto 0) := (others => '0'); + signal target_align, target_align_next : ALIGN_TYPE := ALIGN_1; + signal data_in_latch, data_in_latch_next : std_logic_vector(WORD_WIDTH-1 downto 0) := (others => '0'); + signal data_out_latch, data_out_latch_next : std_logic_vector(WORD_WIDTH-1 downto 0) := (others => '0'); + signal optional, optional_next : std_logic := '0'; + signal abort_mem : std_logic := '0'; + signal opcode_latch, opcode_latch_next : KEY_HOLDER_OPCODE_TYPE := NOP; + signal cnt_2, cnt_2_next : natural range 0 to (WORD_WIDTH/BYTE_WIDTH)-1 := 0; + signal align_op, align_op_next : std_logic := '0'; + signal finalize_payload, finalize_payload_next : std_logic := '0'; + signal ready_in_sig : std_logic := '0'; + -- ###GENERATED START### + signal start_md5, ack_md5, done_md5 : std_logic := '0'; + signal data_in_md5 : std_logic_vector(BYTE_WIDTH-1 downto 0) := (others => '0'); + signal valid_in_md5, ready_in_md5, last_word_in_md5 : std_logic := '0'; + signal hash_out_md5 : std_logic_vector(KEY_HASH_WIDTH-1 downto 0) := (others => '0'); + signal key_hash, key_hash_next : KEY_HASH_TYPE := HANDLE_NIL; + signal decode_stage, decode_stage_next : DECODE_STAGE_TYPE := GET_ID; + signal encode_stage, encode_stage_next : ENCODE_STAGE_TYPE := WRITE_ID; + signal return_stage, return_stage_next : DECODE_STAGE_TYPE := GET_ID; + signal id_latch, id_latch_next : std_logic_vector(CDR_LONG_WIDTH-1 downto 0) := (others => '0'); + signal TestSequence_cnt, TestSequence_cnt_next : natural range 0 to TESTSEQUENCE_MAX_DEPTH-1 := 0; + signal TestSequence_len_latch, TestSequence_len_latch_next : unsigned(TESTSEQUENCE_ADDR_WIDTH-1 downto 0) := (others => '0'); + signal TestSequence_addr_latch, TestSequence_addr_latch_next : std_logic_vector(TESTSEQUENCE_ADDR_WIDTH-1 downto 0) := (others => '0'); + signal TestSequence_TestArray_cnt, TestSequence_TestArray_cnt_next : natural range 0 to TESTSEQUENCE_TESTARRAY_MAX_DEPTH-1 := 0; + -- TestSequence_TestArray_mem SIGNALS + signal TestSequence_TestArray_mem_addr : TESTSEQUENCE_TESTARRAY_ADDR_TYPE := (others => (others => '0')); + signal TestSequence_TestArray_mem_read, TestSequence_TestArray_mem_ready_in, TestSequence_TestArray_mem_ready_out, TestSequence_TestArray_mem_valid_in, TestSequence_TestArray_mem_valid_out : std_logic_vector(0 to TESTSEQUENCE_TESTARRAY_MAX_DEPTH-1) := (others => '0'); + signal TestSequence_TestArray_mem_data_in, TestSequence_TestArray_mem_data_out : TESTSEQUENCE_TESTARRAY_DATA_TYPE := (others => (others => '0')); + -- ###GENERATED END### + + --*****ALIAS DECLARATION***** + alias representation_id : std_logic_vector(PAYLOAD_REPRESENTATION_ID_WIDTH-1 downto 0) is data_in(WORD_WIDTH-1 downto WORD_WIDTH-PAYLOAD_REPRESENTATION_ID_WIDTH); + alias representation_options : std_logic_vector(PAYLOAD_REPRESENTATION_ID_WIDTH-1 downto 0) is data_in(PAYLOAD_REPRESENTATION_OPTIONS_WIDTH-1 downto 0); + alias parameter_id : std_logic_vector(PARAMETER_ID_WIDTH-1 downto 0) is data_in_latch(WORD_WIDTH-1 downto WORD_WIDTH-PARAMETER_ID_WIDTH); + alias parameter_length : std_logic_vector(PARAMETER_LENGTH_WIDTH-1 downto 0) is data_in_latch(PARAMETER_LENGTH_WIDTH-1 downto 0); + + +begin + + -- ###GENERATED START### + TestSequence_TestArray_gen : for i in 0 to TESTSEQUENCE_MAX_DEPTH-1 generate + begin + TestSequence_TestArray_mem : entity work.mem_ctrl(arch) + generic map ( + ADDR_WIDTH => TESTSEQUENCE_TESTARRAY_ADDR_WIDTH, + DATA_WIDTH => CDR_OCTET_WIDTH, + MEMORY_DEPTH => TESTSEQUENCE_TESTARRAY_MAX_DEPTH, + MAX_BURST_LENGTH => 1 + ) + port map ( + clk => clk, + reset => reset or abort_mem, + addr => TestSequence_TestArray_mem_addr(i), + read => TestSequence_TestArray_mem_read(i), + ready_in => TestSequence_TestArray_mem_ready_in(i), + valid_in => TestSequence_TestArray_mem_valid_in(i), + data_in => TestSequence_TestArray_mem_data_in(i), + ready_out => TestSequence_TestArray_mem_ready_out(i), + valid_out => TestSequence_TestArray_mem_valid_out(i), + data_out => TestSequence_TestArray_mem_data_out(i) + ); + end generate; + + md5_calculator_inst : md5_calculator + port map ( + clk => clk, + reset => reset, + start => start_md5, + ack => ack_md5, + data_in => data_in_md5, + valid_in => valid_in_md5, + ready_in => ready_in_md5, + last_word_in => last_word_in_md5, + hash_out => hash_out_md5, + done => done_md5 + ); + -- ###GENERATED END### + + decode_error <= decode_error_latch; + ready_in <= ready_in_sig; + + main_prc : process (all) + variable tmp_length : unsigned(WORD_WIDTH-1 downto 0) := (others => '0'); + begin + -- DEFAULT + stage_next <= stage; + decode_stage_next <= decode_stage; + encode_stage_next <= encode_stage; + return_stage_next <= return_stage; + cnt_next <= cnt; + cnt_2_next <= cnt_2; + endian_flag_next <= endian_flag; + last_word_in_latch_next <= last_word_in_latch; + decode_error_latch_next <= decode_error_latch; + align_offset_next <= align_offset; + target_align_next <= target_align; + optional_next <= optional; + data_in_latch_next <= data_in_latch; + opcode_latch_next <= opcode_latch; + key_hash_next <= key_hash; + align_op_next <= align_op; + finalize_payload_next <= finalize_payload; + abort_mem <= '0'; + ack <= '0'; + ready_in_sig <= '0'; + last_word_out <= '0'; + valid_out <= '0'; + data_out <= (others => '0'); + -- ###GENERATED START### + id_latch_next <= id_latch; + TestSequence_len_latch_next <= TestSequence_len_latch; + TestSequence_cnt_next <= TestSequence_cnt; + TestSequence_TestArray_cnt_next <= TestSequence_TestArray_cnt; + TestSequence_addr_latch_next <= TestSequence_addr_latch; + TestSequence_TestArray_mem_addr <= (others => (others => '0')); + TestSequence_TestArray_mem_read <= (others => '0'); + TestSequence_TestArray_mem_valid_in <= (others => '0'); + TestSequence_TestArray_mem_ready_out <= (others => '0'); + TestSequence_TestArray_mem_data_in <= (others => (others => '0')); + -- ###GENERATED END### + + -- Last Word Latch Setter + if (last_word_in = '1') then + last_word_in_latch_next <= '1'; + end if; + + case (stage) is + when IDLE => + -- Latch Opcode + opcode_latch_next <= opcode; + + if (start = '1') then + case (opcode) is + when PUSH_DATA => + ack <= '1'; + stage_next <= GET_PAYLOAD_HEADER; + -- Reset + key_hash_next <= HANDLE_NIL; + when PUSH_SERIALIZED_KEY => + ack <= '1'; + -- Serialized Key is in PLAIN_CDR2 Big Endian encoding + endian_flag_next <= '0'; + stage_next <= FETCH; + decode_stage_next <= GET_ID; + when READ_KEY_HASH => + ack <= '1'; + -- Key Hash not calculated + if (key_hash = HANDLE_NIL) then + -- DES: If MAX_TYPE2_KEY_HOLDER_SIZE is <= 16 we don't have to calculate the md5 (or even instantiate the md5_calculator at all) + stage_next <= START_MD5_CALCULATION; + else + stage_next <= PUSH_KEY_HASH; + cnt_next <= 0; + end if; + when READ_SERIALIZED_KEY => + ack <= '1'; + stage_next <= SERIALIZE_KEY; + encode_stage_next <= WRITE_ID; + when others => + null; + end case; + end if; + when START_MD5_CALCULATION => + start_md5 <= '1'; + + if (ack_md5 = '1') then + stage_next <= SERIALIZE_KEY; + encode_stage_next <= WRITE_ID; + end if; + when GET_PAYLOAD_HEADER => + -- TODO: Latch Offset from Options Field? + + ready_in_sig <= '1'; + -- Input Guard + if (valid_in = '1') then + case (representation_id) is + when CDR_BE => + endian_flag_next <= '0'; + stage_next <= FETCH; + decode_stage_next <= GET_ID; + -- Alignment Reset + align_offset_next <= (others => '0'); + -- Initial Fetch + when CDR_LE => + endian_flag_next <= '1'; + stage_next <= FETCH; + decode_stage_next <= GET_ID; + -- Alignment Reset + align_offset_next <= (others => '0'); + when others => + -- Unknown Payload Encoding + stage_next <= SKIP_PAYLOAD; + decode_error_latch_next <= '1'; + end case; + end if; + when FETCH => + ready_in_sig <= '1'; + -- Input Guard + if (valid_in = '1') then + data_in_latch_next <= data_in; + -- Alignment Operation in progress + if (align_op = '1') then + stage_next <= ALIGN_IN_STREAM; + -- Reset + align_op_next <= '0'; + else + stage_next <= DECODE_PAYLOAD; + end if; + end if; + when ALIGN_IN_STREAM => + -- Target Stream Alignment reached + if (check_align(align_offset, target_align)) then + -- DONE + stage_next <= DECODE_PAYLOAD; + else + align_offset_next <= align_offset + 1; + -- Need to fetch new Input Word + if (align_offset(1 downto 0) = "11") then + align_op_next <= '1'; + stage_next <= FETCH; + end if; + end if; + when SKIP_PAYLOAD => + if (last_word_in_latch = '0' and last_word_in = '0') then + -- Skip Read + ready_in_sig <= '1'; + else + stage_next <= IDLE; + -- Reset + last_word_in_latch_next <= '0'; + end if; + when DECODE_PAYLOAD => + -- ###GENERATED START### + case (decode_stage) is + when GET_ID => + -- ALIGN GUARD + -- DES: If ALIGN_8 is used, we have to to check the latched opcode and use ALIGN_4 if PUSH_SERIALIZED_KEY (since it uses PLAIN_CDR2 encoding) + if (not check_align(align_offset, ALIGN_4)) then + target_align_next <= ALIGN_4; + stage_next <= ALIGN_IN_STREAM; + else + id_latch_next <= endian_swap(endian_flag, data_in_latch); + align_offset_next <= align_offset + 4; + stage_next <= FETCH; + -- Next Member + decode_stage_next <= GET_TESTSEQUENCE_LENGTH; + end if; + when GET_TESTSEQUENCE_LENGTH => + -- ALIGN GUARD + if (not check_align(align_offset, ALIGN_4)) then + target_align_next <= ALIGN_4; + stage_next <= ALIGN_IN_STREAM; + else + tmp_length := unsigned(endian_swap(endian_flag, data_in_latch)); + align_offset_next <= align_offset + 4; + stage_next <= FETCH; + + -- Empty Sequence + if (tmp_length = 0) then + -- Next Member + stage_next <= SKIP_PAYLOAD; + else + decode_stage_next <= GET_TESTSEQUENCE_TESTARRAY; + TestSequence_len_latch_next <= resize(tmp_length, TestSequence_len_latch_next'length); + TestSequence_cnt_next <= 0; + -- DES: For array types the _cnt has to be initialized in the previous member stage + TestSequence_TestArray_cnt_next <= 0; + end if; + end if; + when GET_TESTSEQUENCE_TESTARRAY => + -- ALIGN GUARD + if (not check_align(align_offset, ALIGN_1)) then + target_align_next <= ALIGN_1; + stage_next <= ALIGN_IN_STREAM; + else + TestSequence_TestArray_mem_addr(TestSequence_cnt) <= std_logic_vector(to_unsigned(TestSequence_TestArray_cnt,TestSequence_TestArray_mem_addr'length)); + TestSequence_TestArray_mem_data_in(TestSequence_cnt) <= endian_swap(endian_flag, get_sub_vector(data_in_latch, to_integer(align_offset(1 downto 0)), CDR_OCTET_WIDTH, TRUE)); + TestSequence_TestArray_mem_valid_in(TestSequence_cnt) <= '1'; + -- Memory Operation Guard + if (TestSequence_TestArray_mem_ready_in(TestSequence_cnt) = '1') then + align_offset_next <= align_offset + 1; + + -- All Elements processed + if (TestSequence_TestArray_cnt = TESTSEQUENCE_TESTARRAY_MAX_DEPTH-1) then + -- DES: The decoding stages are used for both PUSH_DATA and PUSH_SERIALIZED_KEY. + -- We us the latched opcode to differentiate between them. + if (opcode_latch = READ_SERIALIZED_KEY) then + decode_stage_next <= TESTSEQUENCE_MEMBER_END; + else + decode_stage_next <= GET_TESTSEQUENCE_TESTCHAR; + end if; + else + TestSequence_TestArray_cnt_next <= TestSequence_TestArray_cnt + 1; + end if; + + -- DES: Needed for ALIGN_1 + -- Need to fetch next Word + if(align_offset(1 downto 0) = "11") then + stage_next <= FETCH; + end if; + end if; + end if; + when GET_TESTSEQUENCE_TESTCHAR => + -- ALIGN GUARD + if (not check_align(align_offset, ALIGN_1)) then + target_align_next <= ALIGN_1; + stage_next <= ALIGN_IN_STREAM; + else + align_offset_next <= align_offset + 1; + decode_stage_next <= GET_TESTSEQUENCE_TESTWCHAR; + + -- Need to fetch next Word + if(align_offset(1 downto 0) = "11") then + stage_next <= FETCH; + end if; + end if; + when GET_TESTSEQUENCE_TESTWCHAR => + -- ALIGN GUARD + if (not check_align(align_offset, ALIGN_2)) then + target_align_next <= ALIGN_2; + stage_next <= ALIGN_IN_STREAM; + else + align_offset_next <= align_offset + 2; + decode_stage_next <= GET_TESTSEQUENCE_TESTLONGLONG; + cnt_next <= 0; + + -- DES: Needed for ALIGN_2 + -- Need to fetch next Word + if(align_offset(1) = '1') then + stage_next <= FETCH; + end if; + end if; + when GET_TESTSEQUENCE_TESTLONGLONG => + -- ALIGN GUARD + if (not check_align(align_offset, ALIGN_8)) then + target_align_next <= ALIGN_8; + stage_next <= ALIGN_IN_STREAM; + else + case (cnt) is + -- Double Word 1/2 + when 0 => + stage_next <= FETCH; + cnt_next <= cnt + 1; + -- Double Word 2/2 + when 1 => + stage_next <= FETCH; + cnt_next <= cnt + 1; + -- Push Double Word + when 2 => + align_offset_next <= align_offset + 8; + decode_stage_next <= GET_OPTIONAL_HEADER; + return_stage_next <= GET_TESTSEQUENCE_TESTLONGDOUBLE; + cnt_next <= 0; + when others => + null; + end case; + end if; + when GET_TESTSEQUENCE_TESTLONGDOUBLE => + -- Optional Omitted + if (optional = '0') then + decode_stage_next <= TESTSEQUENCE_MEMBER_END; + -- ALIGN GUARD + elsif (not check_align(align_offset, ALIGN_8)) then + target_align_next <= ALIGN_8; + stage_next <= ALIGN_IN_STREAM; + else + case (cnt) is + -- Quad Word 1/4 + when 0 => + stage_next <= FETCH; + cnt_next <= cnt + 1; + -- Quad Word 2/4 + when 1 => + stage_next <= FETCH; + cnt_next <= cnt + 1; + -- Quad Word 3/4 + when 2 => + stage_next <= FETCH; + cnt_next <= cnt + 1; + -- Quad Word 4/4 + when 3 => + stage_next <= FETCH; + cnt_next <= cnt + 1; + -- Push Quad Word + when 4 => + align_offset_next <= align_offset + 16; + decode_stage_next <= TESTSEQUENCE_MEMBER_END; + when others => + null; + end case; + end if; + -- DES: If the elements of an array/sequence are of a complex/nested type, the array/sequence iteration check is done in a seperate *_MEMBER_END stage. + when TESTSEQUENCE_MEMBER_END => + -- All Elements processed + if (TestSequence_cnt = TestSequence_len_latch-1) then + -- Next Member + stage_next <= SKIP_PAYLOAD; + else + TestSequence_cnt_next <= TestSequence_cnt + 1; + decode_stage_next <= GET_TESTSEQUENCE_TESTARRAY; + TestSequence_TestArray_cnt_next <= 0; + end if; + when GET_OPTIONAL_HEADER => + -- ALIGN GUARD + if (not check_align(align_offset, ALIGN_4)) then + target_align_next <= ALIGN_4; + stage_next <= ALIGN_IN_STREAM; + else + case (cnt) is + -- Optional Member Header + when 0 => + -- Extended Parameter Header + if (endian_swap(endian_flag,parameter_id) = PID_EXTENDED) then + cnt_next <= cnt + 1; + stage_next <= FETCH; + else + stage_next <= FETCH; + decode_stage_next <= return_stage; + cnt_next <= 0; + -- Alignment Reset + align_offset_next <= (others => '0'); + + -- Optional omitted + if(endian_swap(endian_flag,parameter_length) = (parameter_length'reverse_range => '0')) then + optional_next <= '0'; + else + optional_next <= '1'; + end if; + end if; + -- eMemberHeader + when 1 => + -- Ignore Parameter ID + cnt_next <= cnt + 1; + stage_next <= FETCH; + -- Llength + when 2 => + stage_next <= FETCH; + decode_stage_next <= return_stage; + cnt_next <= 0; + -- Alignment Reset + align_offset_next <= (others => '0'); + + -- Optional omitted + if(endian_swap(endian_flag, data_in) = (data_in'reverse_range => '0')) then + optional_next <= '0'; + else + optional_next <= '1'; + end if; + when others => + null; + end case; + end if; + when others => + null; + end case; + -- ###GENERATED END### + when PUSH => + -- Push to MD5 Calculator + if (opcode_latch = READ_KEY_HASH) then + -- Mark Last Word + if (finalize_payload = '1' and cnt_2 = to_integer(unsigned(align_offset(1 downto 0)))) then + last_word_out <= '1'; + end if; + + valid_in_md5 <= '1'; + data_in_md5 <= get_sub_vector(data_out_latch, cnt_2, BYTE_WIDTH, TRUE); + -- Output Guard + if (ready_in_md5 = '1') then + -- Last Byte + if ((finalize_payload = '1' and cnt_2 = to_integer(unsigned(align_offset(1 downto 0)))) or cnt_2 = (WORD_WIDTH/BYTE_WIDTH)-1) then + -- Reset + cnt_2_next <= 0; + -- Alignment Operation in process + if (align_op = '1') then + stage_next <= ALIGN_OUT_STREAM; + -- Reset + align_op_next <= '0'; + -- DONE + elsif (finalize_payload = '1') then + stage_next <= GET_KEY_HASH; + -- Reset + finalize_payload_next <= '0'; + else + stage_next <= SERIALIZE_KEY; + end if; + else + cnt_2_next <= cnt_2 + 1; + end if; + end if; + else + -- Mark Last Word + if (finalize_payload = '1') then + last_word_out <= '1'; + end if; + + valid_out <= '1'; + data_out <= data_out_latch; + -- Output Guard + if (ready_out = '1') then + -- NOTE: Ensures all padding is zero. + data_out_latch_next <= (others => '0'); + -- Alignment Operation in process + if (align_op = '1') then + stage_next <= ALIGN_OUT_STREAM; + -- Reset + align_op_next <= '0'; + -- DONE + elsif (finalize_payload = '1') then + finalize_payload_next <= '0'; + stage_next <= IDLE; + else + stage_next <= SERIALIZE_KEY; + end if; + end if; + end if; + when ALIGN_OUT_STREAM => + -- Target Stream Alignment reached + if (check_align(align_offset, target_align)) then + -- DONE + stage_next <= SERIALIZE_KEY; + else + align_offset_next <= align_offset + 1; + -- Need to push Word + if (align_offset(1 downto 0) = "11") then + align_op_next <= '1'; + stage_next <= PUSH; + end if; + end if; + when SERIALIZE_KEY => + -- ###GENERATED START### + case (encode_stage) is + when WRITE_ID => + -- ALIGN GUARD + if (not check_align(align_offset, ALIGN_4)) then + target_align_next <= ALIGN_4; + stage_next <= ALIGN_OUT_STREAM; + else + data_out_latch_next <= id_latch; + align_offset_next <= align_offset + 4; + stage_next <= PUSH; + -- Next Member + encode_stage_next <= WRITE_TESTSEQUENCE_LENGTH; + end if; + when WRITE_TESTSEQUENCE_LENGTH => + -- ALIGN GUARD + if (not check_align(align_offset, ALIGN_4)) then + target_align_next <= ALIGN_4; + stage_next <= ALIGN_OUT_STREAM; + else + data_out_latch_next <= std_logic_vector(resize(TestSequence_len_latch,WORD_WIDTH)); + align_offset_next <= align_offset + 4; + stage_next <= PUSH; + + -- Empty Sequence + if (unsigned(TestSequence_len_latch) = 0) then + -- DONE + stage_next <= PUSH; + finalize_payload_next <= '1'; + else + encode_stage_next <= WRITE_TESTSEQUENCE_TESTARRAY; + cnt_next <= 0; + TestSequence_cnt_next <= 0; + -- DES: For array types the _cnt has to be initialized in the previous member stage + TestSequence_TestArray_cnt_next <= 0; + end if; + end if; + when WRITE_TESTSEQUENCE_TESTARRAY => + -- ALIGN GUARD + if (not check_align(align_offset, ALIGN_1)) then + target_align_next <= ALIGN_1; + stage_next <= ALIGN_OUT_STREAM; + else + case (cnt) is + -- GET + when 0 => + TestSequence_TestArray_mem_addr(TestSequence_cnt) <= std_logic_vector(to_unsigned(TestSequence_TestArray_cnt,TestSequence_TestArray_mem_addr'length)); + TestSequence_TestArray_mem_valid_in(TestSequence_cnt) <= '1'; + TestSequence_TestArray_mem_read(TestSequence_cnt) <= '1'; + -- Memory Operation Guard + if (TestSequence_TestArray_mem_ready_in(TestSequence_cnt) = '1') then + cnt_next <= cnt + 1; + end if; + -- WRITE + when 1 => + TestSequence_TestArray_mem_ready_out(TestSequence_cnt) <= '1'; + -- Memory Operation Guard + if (TestSequence_TestArray_mem_valid_out(TestSequence_cnt) = '1') then + data_out_latch_next <= write_sub_vector(data_out_latch, TestSequence_TestArray_mem_data_out(TestSequence_cnt), to_integer(align_offset(1 downto 0)), TRUE); + align_offset_next <= align_offset + 1; + cnt_next <= 0; + + -- All Elements processed + if (TestSequence_TestArray_cnt = TESTSEQUENCE_TESTARRAY_MAX_DEPTH-1) then + -- DONE + stage_next <= PUSH; + finalize_payload_next <= '1'; + else + TestSequence_TestArray_cnt_next <= TestSequence_TestArray_cnt + 1; + end if; + + -- DES: Needed for ALIGN_1 + -- Need to fetch next Word + if(align_offset(1 downto 0) = "11") then + stage_next <= PUSH; + end if; + end if; + when others => + end case; + end if; + when TESTSEQUENCE_MEMBER_END => + -- All Elements processed + if (TestSequence_cnt = unsigned(TestSequence_len_latch)-1) then + -- DONE + stage_next <= PUSH; + finalize_payload_next <= '1'; + else + TestSequence_cnt_next <= TestSequence_cnt + 1; + encode_stage_next <= WRITE_TESTSEQUENCE_TESTARRAY; + TestSequence_TestArray_cnt_next <= 0; + cnt_next <= 0; + end if; + end case; + -- ###GENERATED END### + when GET_KEY_HASH => + if (done_md5 = '1') then + key_hash_next <= to_key_hash(hash_out_md5); + stage_next <= PUSH_KEY_HASH; + cnt_next <= 0; + end if; + when PUSH_KEY_HASH => + case (cnt) is + -- Key Hash 1/4 + when 0 => + data_out <= key_hash(0); + valid_out <= '1'; + -- Output Guard + if (ready_out = '1') then + cnt_next <= cnt + 1; + end if; + -- Key Hash 2/4 + when 1 => + data_out <= key_hash(1); + valid_out <= '1'; + -- Output Guard + if (ready_out = '1') then + cnt_next <= cnt + 1; + end if; + -- Key Hash 3/4 + when 2 => + data_out <= key_hash(2); + valid_out <= '1'; + -- Output Guard + if (ready_out = '1') then + cnt_next <= cnt + 1; + end if; + -- Key Hash 4/4 + when 3 => + data_out <= key_hash(3); + valid_out <= '1'; + last_word_out <= '1'; + -- Output Guard + if (ready_out = '1') then + -- DONE + stage_next <= IDLE; + end if; + when others => + null; + end case; + when others => + null; + end case; + + -- OVERREAD GUARD + -- Attempted read on empty input + if (last_word_in_latch = '1' and ready_in_sig = '1') then + stage_next <= SKIP_PAYLOAD; + decode_error_latch_next <= '1'; + end if; + + end process; + + sync_prc : process(clk) + begin + if rising_edge(clk) then + if (reset = '1') then + stage <= IDLE; + decode_stage <= GET_ID; + encode_stage <= WRITE_ID; + return_stage <= GET_ID; + target_align <= ALIGN_1; + opcode_latch <= NOP; + cnt <= 0; + cnt_2 <= 0; + endian_flag <= '0'; + last_word_in_latch <= '0'; + decode_error <= '0'; + optional <= '0'; + align_op <= '0'; + finalize_payload <= '0'; + align_offset <= (others => '0'); + data_in_latch <= (others => '0'); + key_hash <= HANDLE_NIL; + -- ###GENERATED START### + id_latch <= (others => '0'); + TestSequence_len_latch <= (others => '0'); + TestSequence_cnt <= 0; + TestSequence_TestArray_cnt <= 0; + -- ###GENERATED END### + else + stage <= stage_next; + decode_stage <= decode_stage_next; + encode_stage <= encode_stage_next; + return_stage <= return_stage_next; + target_align <= target_align_next; + opcode_latch <= opcode_latch_next; + cnt <= cnt_next; + cnt_2 <= cnt_2_next; + endian_flag <= endian_flag_next; + last_word_in_latch <= last_word_in_latch_next; + decode_error <= decode_error_latch_next; + optional <= optional_next; + align_op <= align_op_next; + finalize_payload <= finalize_payload_next; + align_offset <= align_offset_next; + data_in_latch <= data_in_latch_next; + key_hash <= key_hash_next; + -- ###GENERATED START### + id_latch <= id_latch_next; + TestSequence_len_latch <= TestSequence_len_latch_next; + TestSequence_cnt <= TestSequence_cnt_next; + TestSequence_TestArray_cnt <= TestSequence_TestArray_cnt_next; + -- ###GENERATED END### + end if; + end if; + end process; + +end architecture; \ No newline at end of file diff --git a/src/key_generator.vhd b/src/key_generator.vhd deleted file mode 100644 index 42582b3..0000000 --- a/src/key_generator.vhd +++ /dev/null @@ -1,24 +0,0 @@ -library ieee; -use ieee.std_logic_1164.all; -use ieee.numeric_std.all; - -entity key_generator is - port ( - clk : in std_logic; - reset : in std_logic; - - start : in std_logic; - opcode : in KEY_GENERATOR_OPCODE_TYPE; - busy : out std_logic; - - data_in : in std_logic_vector(WORD_WIDTH-1 downto 0); - valid_in : in std_logic; - ready_in : out std_logic; - last_word_in : in std_logic; - - data_out : out std_logic_vector(WORD_WIDTH-1 downto 0); - valid_out : out std_logic; - ready_out : in std_logic; - last_word_out : out std_logic - ); -end entity; \ No newline at end of file diff --git a/src/key_hash_generator.vhd b/src/key_hash_generator.vhd deleted file mode 100644 index ea81952..0000000 --- a/src/key_hash_generator.vhd +++ /dev/null @@ -1,148 +0,0 @@ -library ieee; -use ieee.std_logic_1164.all; -use ieee.numeric_std.all; - -entity key_hash_generator is - port ( - clk : in std_logic; - reset : in std_logic; - - data_in : in std_logic_vector(WORD_WIDTH-1 downto 0); - valid_in : in std_logic; - ready_in : out std_logic; - last_word_in : in std_logic; - - data_out : out std_logic_vector(WORD_WIDTH-1 downto 0); - valid_out : out std_logic; - ready_out : in std_logic; - last_word_out : out std_logic - ); -end entity; - -architecture arch of key_hash_generator is - - --*****CONSTANT DECLARATION***** - constant KEY_SIZE : natural := TODO; - - --*****TYPE DECLARATION***** - type STAGE_TYPE is (IDLE, TODO); - - --*****SIGNAL DECLARATION***** - signal key_gen_start, key_gen_busy, key_gen_valid_in, key_gen_ready_in, key_gen_last_word_in, key_gen_valid_out, key_gen_ready_out, key_gen_last_word_out : std_logic := '0'; - signal key_gen_opcode : KEY_GENERATOR_OPCODE_TYPE := NOP; - signal key_gen_data_in, key_gen_data_out : std_logic_vector(WORD_WIDTH-1 downto 0) := (others => '0'); - - signal stage, stage_next : STAGE_TYPE := IDLE; - signal key_hash, key_hash_next : KEY_HASH_TYPE := (others => (others => '0')); - signal cnt, cnt_next : natural range 0 to KEY_HASH_TYPE'length-1 := 0; - -begin - - key_generator_inst : entity work.key_generator(arch) - port map( - clk => clk, - reset => reset, - start => key_gen_start, - opcode => key_gen_opcode, - busy => key_gen_busy, - data_in => key_gen_data_in, - valid_in => key_gen_valid_in, - ready_in => key_gen_ready_in, - last_word_in => key_gen_last_word_in, - data_out => key_gen_data_out, - valid_out => key_gen_valid_out, - ready_out => key_gen_ready_out, - last_word_out => key_gen_last_word_out - ); - - - main_prc : process (all) - begin - -- DEFAULT - stage_next <= stage; - key_hash_next <= key_hash; - cnt_next <= cnt; - ready_in <= '0'; - key_gen_start <= '0'; - key_gen_valid_in <= '0'; - key_gen_last_word_in <= '0'; - key_gen_data_in <= (others => '0'); - key_gen_ready_out <= '0'; - valid_out <= '0'; - last_word_out <= '0'; - data_out <= (others => '0'); - - case (stage) is - when IDLE => - if (valid_in = '1' and key_gen_busy = '0') then - key_gen_start <= '1'; - key_gen_opcode <= WRITE_PAYLOAD; - stage_next <= PASSTHROUGH_PAYLOAD; - end if; - when PASSTHROUGH_PAYLOAD => - -- TODO: Connect directly to key_generator? - ready_in <= key_gen_ready_in; - key_gen_valid_in <= valid_in; - key_gen_data_in <= data_in; - key_gen_last_word_in <= last_word_in; - - -- Exit Condition - if (last_word_in = '1') then - stage_next <= GET_SIZE; - end if; - when GET_SIZE => - if (key_gen_busy = '0') then - key_gen_start <= '1'; - key_gen_opcode <= READ_SIZE; - stage_next <= READ_SIZE; - end if; - when READ_SIZE => - key_gen_ready_out <= '1'; - if (key_gen_valid_out = '1') then - if (unsigned(key_gen_data_out)) > (KEY_HASH_WIDTH/BYTE_WIDTH)) then - -- TODO: MD5 Calculation - assert FALSE report "MD5 Key hash generation not yet implemented." severity FAILURE; - else - stage_next <= GET_KEY_HASH; - end if; - end if; - when GET_KEY_HASH => - if (key_gen_busy = '0') then - key_gen_start <= '1'; - key_gen_opcode <= READ_KEY; - - stage_next <= WRITE_KEY_HASH; - cnt_next <= 0; - key_hash_next <= (others => (others => '0')); - end if; - when WRITE_KEY_HASH => - key_gen_ready_out <= '1'; - if (key_gen_valid_out) then - cnt_next <= cnt + 1; - - key_hash_next(cnt) <= key_gen_data_out; - - if (key_gen_last_word_out = '1') then - stage_next <= FINISHED_KEY_HASH; - cnt_next <= 0; - end if; - end if; - when FINISHED_KEY_HASH => - valid_out <= '1'; - if (ready_out = '1') then - cnt_next <= cnt + 1; - - data_out <= key_hash(cnt); - - if (cnt = key_hash'length-1) then - last_word_out <= '1'; - -- DONE - stage_next <= IDLE; - end if; - end if; - when others => - null; - end case; - end process; - -end architecture; \ No newline at end of file diff --git a/src/key_holder.vhd b/src/key_holder.vhd index b56e56d..d726760 100644 --- a/src/key_holder.vhd +++ b/src/key_holder.vhd @@ -8,8 +8,9 @@ entity key_holder is reset : in std_logic; start : in std_logic; - opcode : in KEY_HOLDER_TYPE; - ack : in std_logic; + opcode : in KEY_HOLDER_OPCODE_TYPE; + ack : out std_logic; + decode_error : out std_logic; data_in : in std_logic_vector(WORD_WIDTH-1 downto 0); valid_in : in std_logic; diff --git a/src/md5_calculator.vhd b/src/md5_calculator.vhd new file mode 100644 index 0000000..c7b5675 --- /dev/null +++ b/src/md5_calculator.vhd @@ -0,0 +1,21 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity md5_calculator is + port ( + clk : in std_logic; + reset : in std_logic; + + start : in std_logic; + ack : out std_logic; + + data_in : in std_logic_vector(7 downto 0); + valid_in : in std_logic; + ready_in : out std_logic; + last_word_in : in std_logic; + + hash_out : out std_logic_vector(127 downto 0); + done : out std_logic; + ); +end entity; \ No newline at end of file diff --git a/src/rtps_package.vhd b/src/rtps_package.vhd index 4e5e308..710277b 100644 --- a/src/rtps_package.vhd +++ b/src/rtps_package.vhd @@ -462,7 +462,8 @@ package rtps_package is constant DEFAULT_USER_DOMAIN_TAG : USER_STRING_TYPE := (others => NUL); function to_guid(A : GUIDPREFIX_TYPE; B : std_logic_vector(ENTITYID_WIDTH-1 downto 0)) return GUID_TYPE; - function to_key_hash (A : GUID_TYPE) return KEY_HASH_TYPE; + function to_key_hash(A : GUID_TYPE) return KEY_HASH_TYPE; + function to_key_hash(A : std_logic_vector) return KEY_HASH_TYPE; -- *OVERLOAD FUNCTIONS* function to_unsigned (input: DOUBLE_WORD_ARRAY) return unsigned; @@ -709,6 +710,16 @@ package body rtps_package is return ret; end function; + function to_key_hash (A : std_logic_vector) return KEY_HASH_TYPE is + variable ret : KEY_HASH_TYPE := HANDLE_NIL; + begin + assert (A'length = KEY_HASH_WIDTH) severity FAILURE; + for i in 0 to KEY_HASH_TYPE'length-1 loop + ret(i) := A(((i+1)*WORD_WIDTH)-1 downto i*WORD_WIDTH); + end loop; + return ret; + end function; + function to_unsigned(input : KEY_HASH_TYPE) return unsigned is variable ret : unsigned(KEY_HASH_WIDTH-1 downto 0) := (others => '0'); begin diff --git a/src/serialized_key_generator.vhd b/src/serialized_key_generator.vhd deleted file mode 100644 index a4cf608..0000000 --- a/src/serialized_key_generator.vhd +++ /dev/null @@ -1,24 +0,0 @@ -library ieee; -use ieee.std_logic_1164.all; -use ieee.numeric_std.all; - -entity serialized_key_generator is - port ( - clk : in std_logic; - reset : in std_logic; - - start : in std_logic; - opcode : in KEY_GENERATOR_OPCODE_TYPE; - busy : out std_logic; - - data_in : in std_logic_vector(WORD_WIDTH-1 downto 0); - valid_in : in std_logic; - ready_in : out std_logic; - last_word_in : in std_logic; - - data_out : out std_logic_vector(WORD_WIDTH-1 downto 0); - valid_out : out std_logic; - ready_out : in std_logic; - last_word_out : out std_logic - ); -end entity; \ No newline at end of file