diff --git a/src/socbridge_driver.vhd b/src/socbridge_driver.vhd index 3102ecf..d0abb8f 100644 --- a/src/socbridge_driver.vhd +++ b/src/socbridge_driver.vhd @@ -22,29 +22,30 @@ architecture rtl of socbridge_driver is signal next_parity_out : std_logic; signal ext_in_rec : ext_protocol_t; - signal ext_out_data_cmd : std_logic_vector(interface_inst.socbridge.payload_width - 1 downto 0); + shared variable ext_out_data_cmd : std_logic_vector(interface_inst.socbridge.payload_width - 1 downto 0); + signal test : std_logic_vector(interface_inst.socbridge.payload_width - 1 downto 0); signal next_state : state_t; signal curr_command : command_t; signal curr_command_bits : std_logic_vector(4 downto 0); - signal curr_respoonse : response_t; + signal curr_response : response_t; signal curr_response_bits : std_logic_vector(4 downto 0); signal st : state_rec_t; begin - next_parity_out <= calc_parity(ext_out_data_cmd); --- DEBUG GLOBAL BINDINGS --- -- synthesis translate_off G_next_parity_out <= next_parity_out; G_ext_in_rec <= ext_in_rec; - G_ext_out_data_cmd <= ext_out_data_cmd; G_next_state <= next_state; + G_ext_out_data_cmd <=test; G_curr_command <= curr_command; G_curr_command_bits <= curr_command_bits; - G_curr_respoonse <= curr_respoonse; + G_curr_response <= curr_response; G_curr_response_bits <= curr_response_bits; G_st <= st; -- synthesis translate_on - - + ext_in_rec.data <= ext_in.payload; + ext_in_rec.clk <= ext_in.control(1); + ext_in_rec.parity <= ext_in.control(0); comb_proc: process(ext_in, int_out, st) begin @@ -53,10 +54,25 @@ begin int_in.payload <= st.ext_in_reg.data; -- Helpful Bindings -- - ext_in_rec <= create_ext_protocol_from_io_type_in(ext_in); - curr_response_bits <= ext_in_rec.data(7 downto 3); + curr_response_bits <= ext_in.payload(7 downto 3); -- CANT USE EXT_IN_REC here for some reason, the assignment becomes stasteful + -- Not sure that the two process method is helping here: if this was a normal + -- signal assignment there would be no confusion. + -- in the case ... <= ext_in_rec we get + -- curr_resp | ext_in_rec | ext_in + -- 00000 | 00000000 | 00001001 + -- 00000 | 00001001 | 00001001 + -- 00001 | 00001001 | 00001001 + -- 00001 | 00001001 | 00001001 + -- + -- but in the case ... <= ext_in we get + -- curr_resp | ext_in_rec | ext_in + -- 00000 | 00000000 | 00001001 + -- 00001 | 00001001 | 00001001 + -- 00001 | 00001001 | 00001001 + -- 00001 | 00001001 | 00001001 + with curr_response_bits select - curr_respoonse <= WRITE_ACK when "00001", + curr_response <= WRITE_ACK when "00001", WRITE_ACK when "00101", READ_RESPONSE when "01000", READ_RESPONSE when "01100", @@ -109,7 +125,7 @@ begin next_state <= TX_ACK; when TX_ACK => -- Wait for write acknowledgement. - if curr_respoonse = WRITE_ACK then + if curr_response = WRITE_ACK then next_state <= IDLE; else next_state <= TX_ACK; @@ -120,7 +136,7 @@ begin next_state <= RX_RESPONSE; when RX_RESPONSE => -- Wait for read response. - if curr_respoonse = READ_RESPONSE then + if curr_response = READ_RESPONSE then next_state <= RX_BODY; else next_state <= RX_RESPONSE; @@ -132,27 +148,42 @@ begin end case; --- Combinatorial output based on current state --- - ext_out_data_cmd <= (others => '0'); + ext_out_data_cmd := (others => '0'); int_in.is_full_out <= '1'; int_in.write_enable_in <= '0'; case st.curr_state is when IDLE => + if cmd = WRITE or cmd = WRITE_ADD then + ext_out_data_cmd := get_command_bits(WRITE) & "001"; + elsif cmd = READ or cmd = READ_ADD then + ext_out_data_cmd := get_command_bits(READ) & "001"; + end if; when RESET => when TX_HEADER => curr_command <= WRITE; - ext_out_data_cmd <= get_command_bits(WRITE) & "001"; - when TX_BODY => - ext_out_data_cmd <= int_out.payload; + ext_out_data_cmd := int_out.payload; int_in.is_full_out <= '0'; + when TX_BODY => + -- here more logic is needed for mulit word transmission (and address setting) + if cmd = WRITE_ADD then + ext_out_data_cmd := int_out.payload; + int_in.is_full_out <= '0'; + end if; when TX_ACK => when RX_HEADER => curr_command <= READ; - ext_out_data_cmd <= curr_command_bits & "001"; + ext_out_data_cmd := curr_command_bits & "001"; when RX_RESPONSE => when RX_BODY => end case; - report "Running comb part with ext_out_data_cmd = " & to_string(ext_out_data_cmd) severity note; - report "Running comb part with next_parity_out = " & std_logic'image(next_parity_out) severity note; + next_parity_out <= calc_parity(ext_out_data_cmd); + --- DEBUG GLOBAL BINDINGS --- + -- synthesis translate_off + test <= ext_out_data_cmd; + report to_string(ext_out_data_cmd); + report to_string(test); + report to_string(G_ext_out_data_cmd); + -- synthesis translate_on end process comb_proc; -- Process updating internal registers based on primary clock seq_proc: process(ext_in_rec.clk, rst) @@ -165,14 +196,12 @@ begin st.curr_state <= IDLE; elsif(rising_edge(ext_in_rec.clk)) then - report "Running seq part with ext_out_data_cmd = " & to_string(ext_out_data_cmd) severity note; - report "Running seq part with next_parity_out = " & std_logic'image(next_parity_out) severity note; - st.ext_out_reg.parity <= next_parity_out; st.ext_in_reg.data <= ext_in_rec.data; st.ext_in_reg.clk <= ext_in_rec.clk; st.ext_in_reg.parity <= ext_in_rec.parity; st.ext_out_reg.data <= ext_out_data_cmd; st.ext_out_reg.clk <= not st.ext_out_reg.clk; + st.ext_out_reg.parity <= next_parity_out; st.curr_state <= next_state; end if; end process seq_proc; diff --git a/src/socbridge_driver_tb.gtkw b/src/socbridge_driver_tb.gtkw index 3290cb7..4b32853 100644 --- a/src/socbridge_driver_tb.gtkw +++ b/src/socbridge_driver_tb.gtkw @@ -1,15 +1,15 @@ [*] -[*] GTKWave Analyzer v3.3.120 (w)1999-2024 BSI -[*] Wed Feb 26 15:43:46 2025 +[*] GTKWave Analyzer v3.3.104 (w)1999-2020 BSI +[*] Thu Feb 27 10:27:13 2025 [*] -[dumpfile] "/home/kryddan/repos/exjobb-public/src/wave/socbridge_driver_tb-tb.ghw" -[dumpfile_mtime] "Wed Feb 26 15:43:13 2025" -[dumpfile_size] 2378 -[savefile] "/home/kryddan/repos/exjobb-public/src/wave/socbridge_driver_tb.gtkw" -[timestart] 0 -[size] 1920 1080 -[pos] -966 -6 -*-23.724968 40550000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 +[dumpfile] "/home/thesis1/repos/exjobb-public/src/wave/socbridge_driver_tb-tb.ghw" +[dumpfile_mtime] "Thu Feb 27 10:26:19 2025" +[dumpfile_size] 2417 +[savefile] "/home/thesis1/repos/exjobb-public/src/socbridge_driver_tb.gtkw" +[timestart] 21800000 +[size] 956 1033 +[pos] -1 -1 +*-24.456779 22000000 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 [treeopen] top. [treeopen] top.socbridge_driver_tb. [treeopen] top.socbridge_driver_tb_pkg. @@ -37,6 +37,7 @@ top.socbridge_driver_tb.int_out.write_enable_out +{next_parity} top.socbridge_driver_tb_pkg.g_next_parity_out @22 #{top.socbridge_driver_tb.ext_out.payload[7:0]} top.socbridge_driver_tb.ext_out.payload[7] top.socbridge_driver_tb.ext_out.payload[6] top.socbridge_driver_tb.ext_out.payload[5] top.socbridge_driver_tb.ext_out.payload[4] top.socbridge_driver_tb.ext_out.payload[3] top.socbridge_driver_tb.ext_out.payload[2] top.socbridge_driver_tb.ext_out.payload[1] top.socbridge_driver_tb.ext_out.payload[0] ++{next_payload[7:0]} #{top.socbridge_driver_tb_pkg.g_ext_out_data_cmd[7:0]} top.socbridge_driver_tb_pkg.g_ext_out_data_cmd[7] top.socbridge_driver_tb_pkg.g_ext_out_data_cmd[6] top.socbridge_driver_tb_pkg.g_ext_out_data_cmd[5] top.socbridge_driver_tb_pkg.g_ext_out_data_cmd[4] top.socbridge_driver_tb_pkg.g_ext_out_data_cmd[3] top.socbridge_driver_tb_pkg.g_ext_out_data_cmd[2] top.socbridge_driver_tb_pkg.g_ext_out_data_cmd[1] top.socbridge_driver_tb_pkg.g_ext_out_data_cmd[0] @1000200 -External -Outwards @@ -67,9 +68,6 @@ top.socbridge_driver_tb.int_in.write_enable_in top.socbridge_driver_tb_pkg.g_st.curr_state +{next_state} top.socbridge_driver_tb_pkg.g_next_state top.socbridge_driver_tb_pkg.g_curr_command -@23 -#{top.socbridge_driver_tb_pkg.g_ext_out_data_cmd[7:0]} top.socbridge_driver_tb_pkg.g_ext_out_data_cmd[7] top.socbridge_driver_tb_pkg.g_ext_out_data_cmd[6] top.socbridge_driver_tb_pkg.g_ext_out_data_cmd[5] top.socbridge_driver_tb_pkg.g_ext_out_data_cmd[4] top.socbridge_driver_tb_pkg.g_ext_out_data_cmd[3] top.socbridge_driver_tb_pkg.g_ext_out_data_cmd[2] top.socbridge_driver_tb_pkg.g_ext_out_data_cmd[1] top.socbridge_driver_tb_pkg.g_ext_out_data_cmd[0] -@420 top.socbridge_driver_tb_pkg.g_curr_respoonse @1000200 -Internal Signals diff --git a/src/socbridge_driver_tb.vhd b/src/socbridge_driver_tb.vhd index 9b009e1..88d4137 100644 --- a/src/socbridge_driver_tb.vhd +++ b/src/socbridge_driver_tb.vhd @@ -10,18 +10,51 @@ entity socbridge_driver_tb is end entity socbridge_driver_tb; architecture tb of socbridge_driver_tb is - impure function check_next_state(correct_state: state_t) return boolean is + signal clk : std_logic := '0'; + signal rst : std_logic; + signal cmd : command_t; + signal ext_in : ext_socbridge_in_t; + signal ext_out : ext_socbridge_out_t; + signal int_in : int_socbridge_in_t; + signal int_out : int_socbridge_out_t; + signal curr_word : std_logic_vector(ext_in.payload'length - 1 downto 0); + signal expected_out : std_logic_vector(ext_out.payload'length - 1 downto 0); + + constant CLK_PERIOD : TIME := 10 ns; + constant SIMULATION_CYCLE_COUNT : INTEGER := 100; + + procedure fail(error_msg : string) is + begin + wait for CLK_PERIOD; + report "Simulation ending due to: " & error_msg & ". Shutting down..." severity FAILURE; + end procedure; + + procedure check_next_state(correct_state: state_t) is begin if(not (correct_state = G_next_state)) then report "Next State is not what was expected, found " & state_t'image(G_next_state) & " but expected " & state_t'image(correct_state) severity error; - return FALSE; + fail("Next State"); end if; - return TRUE; - end function; - - + end procedure; + + procedure check_data_out(correct_data: std_logic_vector(ext_out.payload'length - 1 downto 0)) is + begin + if(not (correct_data = ext_out.payload)) then + report "Data out is not what was expected, found " & to_string(ext_out.payload) + & " but expected " & to_string(correct_data) severity error; + fail("Data out"); + end if; + end procedure; + procedure check_parity(correct_data: std_logic_vector(ext_out.payload'length - 1 downto 0)) is + begin + if(not (calc_parity(correct_data) = calc_parity(ext_out.payload))) then + report "Parity out is not what was expected, found " & std_logic'image(calc_parity(ext_out.payload)) + & " but expected " & std_logic'image(calc_parity(correct_data)) severity error; + fail("Parity out"); + end if; + end procedure; component socbridge_driver is port( @@ -34,18 +67,6 @@ architecture tb of socbridge_driver_tb is int_out : in int_socbridge_out_t ); end component socbridge_driver; - signal clk : std_logic := '0'; - signal rst : std_logic; - signal cmd : command_t; - signal ext_in : ext_socbridge_in_t; - signal ext_out : ext_socbridge_out_t; - signal int_in : int_socbridge_in_t; - signal int_out : int_socbridge_out_t; - - signal curr_word : std_logic_vector(ext_in.payload'length - 1 downto 0); - - constant CLK_PERIOD : TIME := 10 ns; - constant SIMULATION_CYCLE_COUNT : INTEGER := 100; begin socbridge_driver_inst: entity work.socbridge_driver @@ -68,7 +89,6 @@ begin end loop; wait; end process real_clk_proc; - verify_clk: process variable last_clk : std_logic; @@ -84,52 +104,64 @@ begin wait; end process verify_clk; - verify_parity: process + verify_out_signals: process variable curr_parity : std_logic; begin - for x in 0 to SIMULATION_CYCLE_COUNT * 10 loop - curr_parity := calc_parity(ext_out.payload); - if not (curr_parity = ext_out.control(0)) then - report "Secondary side parity not correct" severity error; - wait for CLK_PERIOD; - report "Ending Simulation... " severity FAILURE; - end if; - wait for CLK_PERIOD / 10; + wait for CLK_PERIOD / 2; + for x in 0 to SIMULATION_CYCLE_COUNT loop + check_data_out(expected_out); + check_parity(expected_out); + wait for CLK_PERIOD; end loop; wait; - end process verify_parity; + end process verify_out_signals; - verify_next_state : process + verify_signals : process variable nsv: boolean; begin + expected_out <= "00000000"; wait for 3 * CLK_PERIOD; - wait for CLK_PERIOD / 2; - nsv := check_next_state(IDLE); + wait for CLK_PERIOD / 3; + expected_out <= "00000000"; + check_next_state(IDLE); + wait for CLK_PERIOD /4; + check_next_state(TX_HEADER); + wait for CLK_PERIOD * 3 / 4; + expected_out <= get_command_bits(WRITE) & "001"; + check_next_state(TX_BODY); wait for CLK_PERIOD; - nsv := check_next_state(TX_HEADER); + expected_out <= "00000001"; + check_next_state(TX_ACK); wait for CLK_PERIOD; - nsv := check_next_state(TX_BODY); + expected_out <= "00000000"; + check_next_state(TX_ACK); wait for CLK_PERIOD; - nsv := check_next_state(TX_ACK); + expected_out <= "00000000"; + check_next_state(IDLE); wait for CLK_PERIOD; - nsv := check_next_state(TX_ACK); + expected_out <= "00000000"; + check_next_state(IDLE); wait for CLK_PERIOD; - nsv := check_next_state(IDLE); + expected_out <= "00000000"; + check_next_state(IDLE); wait for CLK_PERIOD; - nsv := check_next_state(IDLE); + expected_out <= "00000000"; + check_next_state(IDLE); wait for CLK_PERIOD; - nsv := check_next_state(IDLE); + expected_out <= "00000000"; + check_next_state(IDLE); wait for CLK_PERIOD; - nsv := check_next_state(IDLE); + expected_out <= "00000000"; + check_next_state(IDLE); wait for CLK_PERIOD; - nsv := check_next_state(IDLE); + expected_out <= "00000000"; + check_next_state(IDLE); wait for CLK_PERIOD; - nsv := check_next_state(IDLE); - wait for CLK_PERIOD; - nsv := check_next_state(IDLE); + expected_out <= "00000000"; + check_next_state(IDLE); wait for CLK_PERIOD; wait; - end process verify_next_state; + end process verify_signals; command_stimulus: process begin @@ -150,9 +182,12 @@ begin external_stimulus: process begin + rst <= '0'; + wait for CLK_PERIOD / 1000; rst <= '1'; curr_word <= "00000000"; - wait for 3 * CLK_PERIOD; + wait for 999 * CLK_PERIOD / 1000; + wait for 2 * CLK_PERIOD; rst <= '0'; wait for CLK_PERIOD / 2; wait for 3* CLK_PERIOD; @@ -167,24 +202,35 @@ begin wait for 3 * CLK_PERIOD; -- stimulus goes here int_out.write_enable_out <= '1'; - int_out.payload <= "00000000"; + int_out.payload <= "00000001"; wait until int_in.is_full_out = '0'; wait until rising_edge(clk); + wait until rising_edge(clk); int_out.payload <= "00000010"; wait until int_in.is_full_out = '0'; + wait for CLK_PERIOD/2; + wait until rising_edge(clk); wait until rising_edge(clk); int_out.payload <= "00000100"; wait until int_in.is_full_out = '0'; + wait for CLK_PERIOD/2; + wait until rising_edge(clk); wait until rising_edge(clk); int_out.payload <= "00001000"; wait until int_in.is_full_out = '0'; + wait for CLK_PERIOD/2; + wait until rising_edge(clk); wait until rising_edge(clk); int_out.payload <= "00010000"; wait until int_in.is_full_out = '0'; + wait for CLK_PERIOD/2; + wait until rising_edge(clk); wait until rising_edge(clk); int_out.payload <= "00100000"; wait until int_in.is_full_out = '0'; + wait for CLK_PERIOD/2; wait until rising_edge(clk); + wait until rising_edge(clk); --- ??? Why all these rising_edge checks? wait; end process internal_stimulus; diff --git a/src/socbridge_driver_tb_pkg.vhd b/src/socbridge_driver_tb_pkg.vhd index 676b6ef..10dad39 100644 --- a/src/socbridge_driver_tb_pkg.vhd +++ b/src/socbridge_driver_tb_pkg.vhd @@ -27,9 +27,6 @@ package socbridge_driver_tb_pkg is impure function calc_parity( d : STD_LOGIC_VECTOR(interface_inst.socbridge.payload_width - 1 downto 0) ) return std_logic; - pure function create_ext_protocol_from_io_type_in ( - input : ext_socbridge_in_t - ) return ext_protocol_t; pure function create_io_type_out_from_ext_protocol( input: ext_protocol_t ) return ext_socbridge_out_t; @@ -43,7 +40,7 @@ package socbridge_driver_tb_pkg is signal G_next_state : state_t; signal G_curr_command : command_t; signal G_curr_command_bits : std_logic_vector(4 downto 0); - signal G_curr_respoonse : response_t; + signal G_curr_response : response_t; signal G_curr_response_bits : std_logic_vector(4 downto 0); signal G_st : state_rec_t; -- synthesis translate_on @@ -74,16 +71,6 @@ package body socbridge_driver_tb_pkg is return not parity; end function; - pure function create_ext_protocol_from_io_type_in( - input : ext_socbridge_in_t - ) return ext_protocol_t is - variable val : ext_protocol_t; - begin - val.data := input.payload; - val.clk := input.control(1); - val.parity := input.control(0); - return val; - end function; pure function create_io_type_out_from_ext_protocol( input : ext_protocol_t ) return ext_socbridge_out_t is