diff --git a/src/socbridge_driver.vhd b/src/socbridge_driver.vhd index 19c0834..3b6336e 100644 --- a/src/socbridge_driver.vhd +++ b/src/socbridge_driver.vhd @@ -11,6 +11,7 @@ entity socbridge_driver 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; @@ -26,8 +27,7 @@ architecture rtl of socbridge_driver is 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_cmd_bits : std_logic_vector(4 downto 0); signal curr_response : response_t; signal curr_response_bits : std_logic_vector(4 downto 0); signal st : state_rec_t; @@ -38,8 +38,7 @@ begin G_ext_in_rec <= ext_in_rec; 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_command_bits <= curr_cmd_bits; G_curr_response <= curr_response; G_curr_response_bits <= curr_response_bits; G_st <= st; @@ -81,19 +80,32 @@ begin --- State Transition Diagram --- -- --- +-----+ --- \|/ | --- RESET --+ --- | --- | +-- +-- +-- +-----+ +-- | | +-- \|/ /--+ -- IDLE<-------------------+ -- / \ | -- / \ | -- / \ | -- \|/ \|/ | -- TX_HEADER RX_HEADER | --- | | | --- | | ----+ | +-- |\ / | | +-- | \ / | | +-- | ADDR1 | | +-- | | | | +-- | \|/ | | +-- | ADDR2 | | +-- | | | | +-- | \|/ | | +-- | ADDR3 | | +-- | | | | +-- | \|/ | | +-- | ADDR4 | | +-- | /\ | | +-- | / \ | | +-- |-+ +----| +---+ | -- \|/ \|/ \|/ | | -- TX_BODY RX_RESPONSE---+ | -- | | | @@ -114,8 +126,6 @@ begin else next_state <= IDLE; end if; - when RESET => - next_state <= IDLE; when TX_HEADER => -- The header only takes one word (cycle) to transmit. -- Continue to body directly afterwards. @@ -150,6 +160,16 @@ begin -- Here we want to stay in RX_BODY for the duration of a packet. -- Right now, we receive only one single word at a time for simplicity next_state <= IDLE; + when ADDR1 => + next_state <= ADDR2; + when ADDR2 => + next_state <= ADDR3; + when ADDR3 => + if st.cmd_reg = WRITE or st.cmd_reg = WRITE_ADD then + next_state <= TX_BODY; + else + next_state <= RX_BODY; + end if; end case; --- Combinatorial output based on current state --- @@ -158,34 +178,27 @@ begin int_in.write_enable_in <= '0'; case st.curr_state is when IDLE => - if cmd = WRITE or cmd = WRITE_ADD then - curr_command <= cmd; - ext_out_data_cmd := get_command_bits(cmd) & get_size_bits(cmd_size); - elsif cmd = READ or cmd = READ_ADD then - curr_command <= cmd; - ext_out_data_cmd := get_command_bits(cmd) & get_size_bits(cmd_size); - end if; - when RESET => when TX_HEADER => - if cmd = WRITE_ADD then - --ext_out_data_cmd := address; - else - ext_out_data_cmd := int_out.payload; - end if; - int_in.is_full_out <= '0'; - when TX_BODY => - if curr_response = WRITE_ACK then - ext_out_data_cmd := "00000000"; + if st.cmd_reg = WRITE_ADD then + ext_out_data_cmd := st.addr_reg(7 downto 0); else ext_out_data_cmd := int_out.payload; int_in.is_full_out <= '0'; end if; + when TX_BODY => + ext_out_data_cmd := int_out.payload; + int_in.is_full_out <= '0'; when TX_ACK => when RX_HEADER => - curr_command <= READ; - ext_out_data_cmd := curr_command_bits & get_size_bits(cmd_size); + ext_out_data_cmd := get_cmd_bits(st.cmd_reg) & get_size_bits(cmd_size); when RX_RESPONSE => when RX_BODY => + when ADDR1 => + ext_out_data_cmd := st.addr_reg(15 downto 8); + when ADDR2 => + ext_out_data_cmd := st.addr_reg(23 downto 16); + when ADDR3 => + ext_out_data_cmd := st.addr_reg(31 downto 24); end case; next_parity_out <= calc_parity(ext_out_data_cmd); --- DEBUG GLOBAL BINDINGS --- @@ -204,6 +217,8 @@ begin st.curr_state <= IDLE; st.write_stage <= 0; st.read_stage <= 0; + st.cmd_reg <= NO_OP; + st.addr_reg <= (others => '0'); elsif(rising_edge(ext_in_rec.clk)) then st.ext_in_reg.data <= ext_in_rec.data; @@ -214,21 +229,27 @@ begin st.ext_out_reg.parity <= next_parity_out; st.curr_state <= next_state; case st.curr_state is + when IDLE => + if cmd = WRITE or cmd = WRITE_ADD or + cmd = READ or cmd = READ_ADD then + st.addr_reg <= address; + st.cmd_reg <= cmd; + end if; when TX_HEADER => - if curr_command = WRITE then + if st.cmd_reg = WRITE then st.write_stage <= 2**(cmd_size - 1) - 1; - elsif curr_command = WRITE_ADD then - st.write_stage <= 2**(cmd_size - 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 curr_command = READ then + if st.cmd_reg = READ then st.read_stage <= 2**(cmd_size - 1) - 1; - elsif curr_command = WRITE_ADD then - st.read_stage <= 2**(cmd_size - 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 65f196d..2bcf280 100644 --- a/src/socbridge_driver_tb.vhd +++ b/src/socbridge_driver_tb.vhd @@ -130,7 +130,7 @@ begin wait for CLK_PERIOD /4; check_next_state(TX_HEADER); wait for CLK_PERIOD * 3 / 4; - expected_out <= get_command_bits(WRITE) & get_size_bits_sim(2); + expected_out <= get_cmd_bits(WRITE) & get_size_bits_sim(2); check_next_state(TX_BODY); wait for CLK_PERIOD; expected_out <= "00000001"; diff --git a/src/socbridge_driver_tb_pkg.vhd b/src/socbridge_driver_tb_pkg.vhd index 6723108..d174742 100644 --- a/src/socbridge_driver_tb_pkg.vhd +++ b/src/socbridge_driver_tb_pkg.vhd @@ -16,7 +16,9 @@ package socbridge_driver_tb_pkg is (NO_OP, WRITE_ACK, READ_RESPONSE); type state_t is - (RESET, IDLE, TX_HEADER, TX_BODY, TX_ACK, RX_HEADER, RX_RESPONSE, RX_BODY); + (IDLE, ADDR1, ADDR2, ADDR3, + TX_HEADER, TX_BODY, TX_ACK, + RX_HEADER, RX_RESPONSE, RX_BODY); type ext_protocol_t is record data : std_logic_vector(interface_inst.socbridge.payload_width - 1 downto 0); @@ -28,6 +30,8 @@ package socbridge_driver_tb_pkg is curr_state: state_t; ext_in_reg, ext_out_reg : ext_protocol_t; write_stage, read_stage : NATURAL; + cmd_reg : command_t; + addr_reg : std_logic_vector(31 downto 0); end record state_rec_t; impure function calc_parity( d : STD_LOGIC_VECTOR(interface_inst.socbridge.payload_width - 1 downto 0) @@ -36,7 +40,7 @@ package socbridge_driver_tb_pkg is input: ext_protocol_t ) return ext_socbridge_out_t; function to_string ( a: std_logic_vector) return string; - pure function get_command_bits(command : command_t) return std_logic_vector; + pure function get_cmd_bits(command : command_t) return std_logic_vector; pure function get_size_bits(size : command_size_t) return std_logic_vector; pure function get_size_bits_sim(size : command_size_t) return std_logic_vector; --- DEBUG GLOBAL SIGNALS --- @@ -88,7 +92,7 @@ package body socbridge_driver_tb_pkg is val.control(0) := input.parity; return val; end function; - pure function get_command_bits(command : command_t) + pure function get_cmd_bits(command : command_t) return std_logic_vector is variable val : std_logic_vector(4 downto 0); begin