library IEEE; use IEEE.std_logic_1164.all; library work; use work.io_types.all; entity socbridge_driver is port( clk : in std_logic; rst : in std_logic; ext_in : in ext_socbridge_in_t; ext_out : out ext_socbridge_out_t; int_in : out int_socbridge_in_t; int_out : in int_socbridge_out_t ); end entity socbridge_driver; architecture rtl of socbridge_driver is pure function calc_parity( d : STD_LOGIC_VECTOR(interface_inst.socbridge.payload_width - 1 downto 0) ) return std_logic is variable parity : std_logic; begin parity := d(0); for x in 1 to d'length - 1 loop parity := parity xor d(x); end loop; return not parity; end function; signal ext_d_in, ext_d_out,ext_d_in_reg, ext_d_out_reg : std_logic_vector(interface_inst.socbridge.payload_width - 1 downto 0); signal ext_clk_in, ext_clk_out, ext_parity_in, ext_parity_out, ext_next_parity_out : std_logic; type command_t is (NO_OP, WRITE_ADD, WRITE, READ_ADD, READ, P_ERR); type response_t 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); signal curr_state, 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_bits : std_logic_vector(4 downto 0); begin comb_proc: process(ext_in, int_out, ext_d_out_reg, ext_clk_out, ext_parity_out, curr_state) begin ext_next_parity_out <= calc_parity(int_out.payload); ext_out.payload <= ext_d_out_reg; ext_out.control <= ext_clk_out & ext_parity_out; ext_d_in <= ext_in.payload; ext_parity_in <= ext_in.control(0); ext_clk_in <= ext_in.control(1); curr_response_bits <= ext_d_in(7 downto 3); -- Create combinational bindings for command/response types with curr_command select curr_command_bits <= "00000" when NO_OP, "10000" when WRITE_ADD, "10100" when WRITE, "11000" when READ_ADD, "11100" when READ, "01001" when P_ERR, "11111" when others; with curr_response_bits select curr_respoonse <= WRITE_ACK when "00001", WRITE_ACK when "00101", READ_RESPONSE when "01000", READ_RESPONSE when "01100", NO_OP when others; --- State Transition Diagram --- -- -- +-----+ -- \|/ | -- RESET --+ -- | -- | -- IDLE<-------------------+ -- / \ | -- / \ | -- / \ | -- \|/ \|/ | -- TX_HEADER RX_HEADER | -- | | | -- | | ----+ | -- \|/ \|/ \|/ | | -- TX_BODY RX_RESPONSE---+ | -- | | | -- | +--+ | | -- \|/\|/ | \|/ | -- TX_ACK--+ RX_BODY | -- | | | -- | | | -- +-----------+--------------+ -- case curr_state is when IDLE => if curr_command = WRITE or curr_command = WRITE_ADD then next_state <= TX_HEADER; elsif curr_command = READ or curr_command = READ_ADD then next_state <= RX_HEADER; 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. next_state <= TX_BODY; 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 next_state <= TX_ACK; when TX_ACK => -- Wait for write acknowledgement. if curr_respoonse = WRITE_ACK then next_state <= IDLE; else next_state <= TX_ACK; end if; when RX_HEADER => -- The header only takes one word (cycle) to transmit. -- Continue to awaiting response directly afterwards. next_state <= RX_RESPONSE; when RX_RESPONSE => -- Wait for read response. if curr_respoonse = READ_RESPONSE then next_state <= RX_BODY; else next_state <= RX_RESPONSE; end if; when RX_BODY => -- 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; end case; end process comb_proc; -- Process updating internal registers based on primary clock seq_proc: process(ext_clk_in, rst) begin if(rst = '1') then ext_d_in_reg <= (others => '0'); ext_d_out_reg <= (others => '0'); ext_clk_out <= '0'; ext_parity_out <= '1'; curr_state <= IDLE; elsif(rising_edge(ext_clk_in)) then ext_clk_out <= not ext_clk_out; ext_d_in_reg <= ext_d_in; ext_d_out_reg <= int_out.payload; ext_parity_out <= ext_next_parity_out; curr_state <= next_state; end if; end process seq_proc; end architecture rtl;