diff --git a/src/socbridge_driver.vhd b/src/socbridge_driver.vhd index 3b6336e..c6f2cbb 100644 --- a/src/socbridge_driver.vhd +++ b/src/socbridge_driver.vhd @@ -71,7 +71,7 @@ begin READ_RESPONSE when "01000", READ_RESPONSE when "01100", NO_OP when others; - comb_proc: process(ext_in, int_out, curr_response, st) + comb_proc: process(ext_in, int_out, curr_response, st, cmd) begin -- Outputs ext_out <= create_io_type_out_from_ext_protocol(st.ext_out_reg); @@ -128,8 +128,12 @@ begin end if; when TX_HEADER => -- The header only takes one word (cycle) to transmit. - -- Continue to body directly afterwards. - next_state <= TX_BODY; + -- Continue to body or address directly afterwards. + if st.cmd_reg = WRITE_ADD then + next_state <= ADDR1; + else + next_state <= TX_BODY; + end if; when TX_BODY => -- Here we want to stay in TX_BODY for the duration of a packet. -- Right now, we transfer one single word at a time for simplicity @@ -148,7 +152,11 @@ begin when RX_HEADER => -- The header only takes one word (cycle) to transmit. -- Continue to awaiting response directly afterwards. - next_state <= RX_RESPONSE; + if st.cmd_reg = WRITE_ADD then + next_state <= ADDR1; + else + next_state <= RX_RESPONSE; + end if; when RX_RESPONSE => -- Wait for read response. if curr_response = READ_RESPONSE then @@ -165,6 +173,8 @@ begin when ADDR2 => next_state <= ADDR3; when ADDR3 => + next_state <= ADDR4; + when ADDR4 => if st.cmd_reg = WRITE or st.cmd_reg = WRITE_ADD then next_state <= TX_BODY; else @@ -178,6 +188,11 @@ begin 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_cmd_bits(cmd) & get_size_bits(cmd_size); + elsif cmd = READ or cmd = READ_ADD then + ext_out_data_cmd := get_cmd_bits(cmd) & get_size_bits(cmd_size); + end if; when TX_HEADER => if st.cmd_reg = WRITE_ADD then ext_out_data_cmd := st.addr_reg(7 downto 0); @@ -186,8 +201,13 @@ begin int_in.is_full_out <= '0'; end if; when TX_BODY => - ext_out_data_cmd := int_out.payload; - int_in.is_full_out <= '0'; + if st.write_stage > 0 then + int_in.is_full_out <= '0'; + ext_out_data_cmd := int_out.payload; + else + ext_out_data_cmd := (others => '0'); + end if; + when TX_ACK => when RX_HEADER => ext_out_data_cmd := get_cmd_bits(st.cmd_reg) & get_size_bits(cmd_size); @@ -199,6 +219,9 @@ begin ext_out_data_cmd := st.addr_reg(23 downto 16); when ADDR3 => ext_out_data_cmd := st.addr_reg(31 downto 24); + when ADDR4 => + int_in.is_full_out <= '0'; + ext_out_data_cmd := int_out.payload; end case; next_parity_out <= calc_parity(ext_out_data_cmd); --- DEBUG GLOBAL BINDINGS --- @@ -236,20 +259,20 @@ begin st.cmd_reg <= cmd; end if; when TX_HEADER => - if st.cmd_reg = WRITE then + if st.cmd_reg = WRITE_ADD then + st.write_stage <= 2**(cmd_size - 1) - 1; + else st.write_stage <= 2**(cmd_size - 1) - 1; - elsif st.cmd_reg = WRITE_ADD then - st.write_stage <= 2**(cmd_size - 1) + 3; end if; when TX_BODY => if st.write_stage > 0 then st.write_stage <= st.write_stage - 1; end if; when RX_HEADER => - if st.cmd_reg = READ then + if st.cmd_reg = READ_ADD then + st.read_stage <= 2**(cmd_size - 1); + else st.read_stage <= 2**(cmd_size - 1) - 1; - elsif st.cmd_reg = READ_ADD then - st.read_stage <= 2**(cmd_size - 1) + 3; end if; when RX_BODY => if st.read_stage > 0 then diff --git a/src/socbridge_driver_tb.vhd b/src/socbridge_driver_tb.vhd index 2bcf280..e99093b 100644 --- a/src/socbridge_driver_tb.vhd +++ b/src/socbridge_driver_tb.vhd @@ -13,6 +13,7 @@ architecture tb of socbridge_driver_tb is signal clk : std_logic := '0'; signal rst : std_logic; signal cmd : command_t; + signal address : std_logic_vector(31 downto 0); signal cmd_size : positive; signal ext_in : ext_socbridge_in_t; signal ext_out : ext_socbridge_out_t; @@ -62,6 +63,7 @@ architecture tb of socbridge_driver_tb is clk : in std_logic; rst : in std_logic; cmd : in command_t; + address : in std_logic_vector(31 downto 0); cmd_size: in positive; ext_in : in ext_socbridge_in_t; ext_out : out ext_socbridge_out_t; @@ -76,6 +78,7 @@ begin clk => clk, rst => rst, cmd => cmd, + address => address, cmd_size => cmd_size, ext_in => ext_in, ext_out => ext_out, @@ -140,7 +143,7 @@ begin check_next_state(TX_ACK); wait for CLK_PERIOD; expected_out <= "00000000"; - check_next_state(IDLE); + check_next_state(TX_ACK); wait for CLK_PERIOD; expected_out <= "00000000"; check_next_state(IDLE); @@ -162,7 +165,30 @@ begin wait for CLK_PERIOD; 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_cmd_bits(WRITE_ADD) & get_size_bits(2); + check_next_state(ADDR1); wait for CLK_PERIOD; + expected_out <= x"FA"; + check_next_state(ADDR2); + wait for CLK_PERIOD; + expected_out <= x"A0"; + check_next_state(ADDR3); + wait for CLK_PERIOD; + expected_out <= x"0F"; + check_next_state(ADDR4); + wait for CLK_PERIOD; + expected_out <= x"FA"; + check_next_state(TX_BODY); + wait for CLK_PERIOD; + expected_out <= "00000100"; + check_next_state(TX_BODY); + wait for CLK_PERIOD; + expected_out <= "00001000"; + wait for CLK_PERIOD; + expected_out <= "00000000"; wait; end process verify_signals; @@ -175,6 +201,12 @@ begin cmd <= WRITE; wait for CLK_PERIOD; cmd <= NO_OP; + wait for CLK_PERIOD * 10; + cmd <= WRITE_ADD; + address <= x"FA0FA0FA"; + wait for CLK_PERIOD; + cmd <= NO_OP; + address <= (others => '0'); wait; end process command_stimulus; @@ -194,8 +226,13 @@ begin wait for 2 * CLK_PERIOD; rst <= '0'; wait for CLK_PERIOD / 2; - wait for 3* CLK_PERIOD; + wait for 4* CLK_PERIOD; curr_word <= "00001001"; + wait for CLK_PERIOD; + curr_word <= "00000000"; + wait for CLK_PERIOD * 10; + curr_word <= "00101001"; + wait; end process external_stimulus; diff --git a/src/socbridge_driver_tb_pkg.vhd b/src/socbridge_driver_tb_pkg.vhd index d174742..19b7b7a 100644 --- a/src/socbridge_driver_tb_pkg.vhd +++ b/src/socbridge_driver_tb_pkg.vhd @@ -16,7 +16,7 @@ package socbridge_driver_tb_pkg is (NO_OP, WRITE_ACK, READ_RESPONSE); type state_t is - (IDLE, ADDR1, ADDR2, ADDR3, + (IDLE, ADDR1, ADDR2, ADDR3, ADDR4, TX_HEADER, TX_BODY, TX_ACK, RX_HEADER, RX_RESPONSE, RX_BODY);