library IEEE; use IEEE.std_logic_1164.all; use IEEE.NUMERIC_STD.all; library gan_ganimede; use gan_ganimede.io_types.all; library gan_socbridge; use gan_socbridge.socbridge_driver_pkg.all; library gan_manager; use gan_manager.management_types.all; library grlib; use grlib.stdlib.all; entity socbridge_driver is generic( MAX_PKT_SIZE : integer range 1 to 128 := 128; BUFFER_SIZE : integer ); port( clk : in std_logic; rst : in std_logic; socbridge_clk : out std_logic; controller_to_socbridge_driver : in controller_to_socbridge_driver_t; socbridge_driver_to_controller : out socbridge_driver_to_controller_t; manager_to_socbridge_driver : in manager_to_socbridge_driver_t; socbridge_driver_to_manager : out socbridge_driver_to_manager_t; ext_to_socbridge_driver : in ext_to_socbridge_driver_t; socbridge_driver_to_ext : out socbridge_driver_to_ext_t; ip_to_socbridge_driver : in ip_to_socbridge_driver_t; socbridge_driver_to_ip : out socbridge_driver_to_ip_t ); end entity socbridge_driver; architecture rtl of socbridge_driver is signal next_parity_out : std_logic; signal ext_to_socbridge_driver_rec : ext_protocol_t; signal next_data_out : std_logic_vector(interface_inst.socbridge.payload_width - 1 downto 0); signal next_rx_transaction : transaction_t; signal next_tx_transaction : transaction_t; signal next_tx_data_size, next_rx_data_size : integer; signal next_rx_state : rx_state_t; signal next_tx_state : tx_state_t; signal st : state_rec_t; signal valid_out : std_logic; --- TRANSLATOR --- signal trans_st : translator_state_t; signal trans_read_next_state : ctrl_inst_state_t; signal trans_write_next_state : ctrl_inst_state_t; --- FSM COMMUNICATION --- signal tx_sent_response, rx_received_response : std_logic; --- MANAGEMENT COMMUNICATION --- begin ext_to_socbridge_driver_rec.data <= ext_to_socbridge_driver.payload; ext_to_socbridge_driver_rec.clk <= ext_to_socbridge_driver.control(1); ext_to_socbridge_driver_rec.parity <= ext_to_socbridge_driver.control(0); socbridge_clk <= ext_to_socbridge_driver_rec.clk; comb_proc: process(ext_to_socbridge_driver, ip_to_socbridge_driver, st, controller_to_socbridge_driver, trans_st, tx_sent_response, rx_received_response, valid_out) variable curr_response_bits : std_logic_vector(4 downto 0); variable local_next_rx_transaction : transaction_t; variable local_next_tx_transaction : transaction_t; variable local_next_data_out : std_logic_vector(interface_inst.socbridge.payload_width - 1 downto 0); begin -- DEFAULT VALUES -- Helpful Bindings -- next_rx_data_size <= 2 ** to_integer(unsigned(ext_to_socbridge_driver.payload(2 downto 0))); curr_response_bits := ext_to_socbridge_driver.payload(7 downto 3); -- Set helper var to current transaction seen at the input. local_next_rx_transaction := NO_OP; if curr_response_bits = "10000" then local_next_rx_transaction := WRITE_ADD; elsif curr_response_bits = "10100" then local_next_rx_transaction := WRITE; elsif curr_response_bits = "11000" then local_next_rx_transaction := READ_ADD; elsif curr_response_bits = "11100" then local_next_rx_transaction := READ; elsif curr_response_bits = "01001" then local_next_rx_transaction := P_ERR; elsif curr_response_bits = "00101" or curr_response_bits = "00001" then local_next_rx_transaction := WRITE_ACK; elsif curr_response_bits = "01100" or curr_response_bits = "01000" then local_next_rx_transaction := READ_RESPONSE; end if; -- Outputs -- socbridge_driver_to_ext.payload <= st.socbridge_driver_to_ext_reg.data; socbridge_driver_to_ext.control(0) <= st.socbridge_driver_to_ext_reg.parity; socbridge_driver_to_ext.control(1) <= st.socbridge_driver_to_ext_reg.clk; if trans_st.read.curr_state = IDLE then socbridge_driver_to_controller.is_reading <= '0'; else socbridge_driver_to_controller.is_reading <= '1'; end if; if trans_st.write.curr_state = IDLE then socbridge_driver_to_controller.is_writing <= '0'; else socbridge_driver_to_controller.is_writing <= '1'; end if; --- Next State Assignments --- --- ### TX NEXT STATE ASSIGNMENTS ### --- case st.curr_tx_state is when IDLE => if (local_next_tx_transaction = WRITE or local_next_tx_transaction = WRITE_ADD) and not st.write_in_flight then next_tx_state <= TX_HEADER; elsif (local_next_tx_transaction = READ or local_next_tx_transaction = READ_ADD) and not st.read_in_flight then next_tx_state <= TX_HEADER; elsif local_next_tx_transaction = READ_RESPONSE or local_next_tx_transaction = WRITE_ACK then next_tx_state <= TX_HEADER; else next_tx_state <= IDLE; end if; when TX_HEADER => -- Commands if st.curr_tx_transaction = WRITE_ADD or st.curr_tx_transaction = READ_ADD then next_tx_state <= ADDR1; elsif st.curr_tx_transaction = WRITE then next_tx_state <= TX_W_BODY; elsif st.curr_tx_transaction = READ then next_tx_state <= IDLE; -- Responses elsif st.curr_tx_transaction = READ_RESPONSE then next_tx_state <= TX_R_BODY; else next_tx_state <= IDLE; end if; when TX_R_BODY => if st.tx_stage <= 1 then next_tx_state <= IDLE; else next_tx_state <= TX_R_BODY; end if; when ADDR1 => next_tx_state <= ADDR2; when ADDR2 => next_tx_state <= ADDR3; when ADDR3 => next_tx_state <= ADDR4; when ADDR4 => if st.curr_tx_transaction = READ_ADD then next_tx_state <= IDLE; elsif st.curr_tx_transaction = WRITE_ADD then next_tx_state <= TX_W_BODY; else next_tx_state <= IDLE; end if; when TX_W_BODY => if st.tx_stage <= 1 then next_tx_state <= IDLE; else next_tx_state <= TX_W_BODY; end if; when TX_AWAIT => -- Wait for RX FSM to get a response if (st.curr_tx_transaction = WRITE_ADD or st.curr_tx_transaction = WRITE) and st.curr_rx_transaction = WRITE_ACK then next_tx_state <= IDLE; elsif (st.curr_tx_transaction = READ_ADD or st.curr_tx_transaction = READ) and st.curr_rx_transaction = READ_RESPONSE and (st.rx_stage = 1 or next_tx_transaction = WRITE or next_tx_transaction = WRITE_ADD) then next_tx_state <= IDLE; else next_tx_state <= TX_AWAIT; end if; end case; --- Next State Assignment Of RX FSM --- case st.curr_rx_state is when IDLE => if local_next_rx_transaction /= NO_OP then next_rx_state <= RX_HEADER; else next_rx_state <= IDLE; end if; when RX_HEADER => -- Commands if st.curr_rx_transaction = WRITE_ADD or st.curr_rx_transaction = READ_ADD then next_rx_state <= ADDR1; elsif st.curr_rx_transaction = WRITE then next_rx_state <= RX_W_BODY; elsif st.curr_rx_transaction = READ then next_rx_state <= RX_AWAIT; -- Responses elsif st.curr_rx_transaction = READ_RESPONSE then next_rx_state <= RX_R_BODY; elsif local_next_rx_transaction /= NO_OP then next_rx_state <= RX_HEADER; else next_rx_state <= IDLE; end if; when RX_R_BODY => if st.rx_stage <= 1 then if local_next_rx_transaction /= NO_OP then next_rx_state <= RX_HEADER; else next_rx_state <= IDLE; end if; else next_rx_state <= RX_R_BODY; end if; when ADDR1 => next_rx_state <= ADDR2; when ADDR2 => next_rx_state <= ADDR3; when ADDR3 => next_rx_state <= ADDR4; when ADDR4 => if st.curr_rx_transaction = READ_ADD then next_rx_state <= RX_AWAIT; elsif st.curr_rx_transaction = WRITE_ADD then next_rx_state <= RX_W_BODY; else next_rx_state <= IDLE; -- Potentially superfluous safety end if; when RX_W_BODY => if st.rx_stage <= 1 then next_rx_state <= RX_AWAIT; else next_rx_state <= RX_W_BODY; end if; when RX_AWAIT => -- Wait for TX FSM to send a response if (st.curr_rx_transaction = WRITE_ADD or st.curr_rx_transaction = WRITE) and st.curr_tx_transaction = WRITE_ACK then next_rx_state <= IDLE; elsif (st.curr_rx_transaction = READ_ADD or st.curr_rx_transaction = READ) and st.curr_tx_transaction = READ_RESPONSE and st.tx_stage = 1 then next_rx_state <= IDLE; else next_rx_state <= RX_AWAIT; end if; end case; --- Combinatorial output based on current state --- local_next_data_out := (others => '0'); socbridge_driver_to_ip.ready <= '0'; --- ### TX_STATE BASED OUTPUT ### --- case st.curr_tx_state is when IDLE => when TX_HEADER => if st.curr_tx_transaction = WRITE_ACK or st.curr_tx_transaction = READ_RESPONSE then local_next_data_out := get_header_bits(st.curr_tx_transaction, st.curr_rx_transaction) & get_size_bits(st.rx_data_size); else local_next_data_out := get_header_bits(st.curr_tx_transaction, st.curr_rx_transaction) & get_size_bits(st.tx_data_size); end if; when TX_W_BODY => if st.tx_stage > 0 then socbridge_driver_to_ip.ready <= '1'; if ip_to_socbridge_driver.fifo.valid = '1' then local_next_data_out := ip_to_socbridge_driver.fifo.data; else local_next_data_out := (others => '0'); end if; end if; when TX_R_BODY => if st.tx_stage > 0 then local_next_data_out := st.curr_read_data((((st.tx_stage - 1) mod 4) + 1) * 8 - 1 downto ((((st.tx_stage - 1) mod 4) + 1) - 1) * 8); end if; when TX_AWAIT => when ADDR1 => local_next_data_out := st.curr_tx_addr(31 downto 24); when ADDR2 => local_next_data_out := st.curr_tx_addr(23 downto 16); when ADDR3 => local_next_data_out := st.curr_tx_addr(15 downto 8); when ADDR4 => local_next_data_out := st.curr_tx_addr(7 downto 0); end case; --- ### RX_STATE BASED OUTPUT ### --- socbridge_driver_to_manager.valid <= '0'; socbridge_driver_to_manager.address <= (others => '0'); socbridge_driver_to_manager.data <= (others => '0'); case st.curr_rx_state is when IDLE => when RX_HEADER => when RX_W_BODY => if st.rx_stage mod 4 = 0 and st.rx_stage /= st.rx_data_size then socbridge_driver_to_manager.data <= st.curr_write_data; socbridge_driver_to_manager.address <= st.curr_rx_write_addr; socbridge_driver_to_manager.valid <= '1'; end if; when RX_R_BODY => when RX_AWAIT => if st.curr_rx_transaction = WRITE or st.curr_rx_transaction = WRITE_ADD then socbridge_driver_to_manager.data <= st.curr_write_data; socbridge_driver_to_manager.address <= st.curr_rx_write_addr; socbridge_driver_to_manager.valid <= '1'; else socbridge_driver_to_manager.address <= st.curr_rx_read_addr; end if; when ADDR1 => when ADDR2 => when ADDR3 => when ADDR4 => end case; next_parity_out <= calc_parity(local_next_data_out); --- TRANSLATOR --- --- Next state assignment case trans_st.write.curr_state is when IDLE => if st.curr_rx_transaction = READ or st.curr_rx_transaction = READ_ADD or st.curr_rx_transaction = WRITE or st.curr_rx_transaction = WRITE_ADD then trans_write_next_state <= IDLE; elsif trans_st.write.curr_inst.request = '1' and (ip_to_socbridge_driver.fifo.used_slots >= MAX_PKT_SIZE or ip_to_socbridge_driver.flush = '1') then trans_write_next_state <= SEND; else trans_write_next_state <= IDLE; end if; -- Wait for driver to go idle and send next instruction. Then enter AWAIT when SEND => if st.curr_tx_transaction = WRITE or st.curr_tx_transaction = WRITE_ADD then trans_write_next_state <= SEND_ACCEPTED; else trans_write_next_state <= SEND; end if; -- Transisitonal state to decrement counter in transition between SEND and AWAIT. when SEND_ACCEPTED => trans_write_next_state <= AWAIT; -- Wait for driver to finish current instruction, then reenter SEND when AWAIT => if trans_st.write.curr_inst.seq_mem_access_count <= MAX_PKT_SIZE and not st.write_in_flight then trans_write_next_state <= IDLE; elsif ip_to_socbridge_driver.fifo.used_slots = 0 and ip_to_socbridge_driver.flush = '1' and not st.write_in_flight then trans_write_next_state <= IDLE; elsif not st.write_in_flight and (ip_to_socbridge_driver.fifo.used_slots >= MAX_PKT_SIZE or ip_to_socbridge_driver.flush = '1') then trans_write_next_state <= SEND; else trans_write_next_state <= AWAIT; end if; end case; case trans_st.read.curr_state is when IDLE => if next_rx_transaction = READ or next_rx_transaction = READ_ADD or next_rx_transaction = WRITE or next_rx_transaction = WRITE_ADD then trans_read_next_state <= IDLE; elsif st.curr_rx_transaction = READ or st.curr_rx_transaction = READ_ADD or st.curr_rx_transaction = WRITE or st.curr_rx_transaction = WRITE_ADD then trans_read_next_state <= IDLE; elsif trans_st.read.curr_inst.request = '1' and BUFFER_SIZE - ip_to_socbridge_driver.read_fifo.used_slots > 2*MAX_PKT_SIZE then trans_read_next_state <= SEND; else trans_read_next_state <= IDLE; end if; -- Wait for driver to go idle and send next instruction. Then enter AWAIT when SEND => if st.curr_tx_transaction = READ or st.curr_tx_transaction = READ_ADD then trans_read_next_state <= SEND_ACCEPTED; else trans_read_next_state <= SEND; end if; -- Transisitonal state to decrement counter in transition between SEND and AWAIT. when SEND_ACCEPTED => trans_read_next_state <= AWAIT; -- Wait for driver to finish current instruction, then reenter SEND when AWAIT => if trans_st.read.curr_inst.seq_mem_access_count <= MAX_PKT_SIZE and not st.read_in_flight then trans_read_next_state <= IDLE; elsif ip_to_socbridge_driver.flush = '1'and not st.read_in_flight then trans_read_next_state <= IDLE; elsif not st.read_in_flight and BUFFER_SIZE - ip_to_socbridge_driver.read_fifo.used_slots > 2*MAX_PKT_SIZE then trans_read_next_state <= SEND; else trans_read_next_state <= AWAIT; end if; end case; --- NEXT TX TRANSACTION --- local_next_tx_transaction := NO_OP; next_tx_data_size <= 0; if trans_st.read.curr_state = IDLE and trans_st.write.curr_state = IDLE and st.curr_rx_state = RX_AWAIT then if (st.curr_rx_transaction = WRITE or st.curr_rx_transaction = WRITE_ADD) and manager_to_socbridge_driver.ready = '1' then local_next_tx_transaction := WRITE_ACK; elsif (st.curr_rx_transaction = READ or st.curr_rx_transaction = READ_ADD) and manager_to_socbridge_driver.valid = '1' then next_tx_data_size <= st.rx_data_size; local_next_tx_transaction := READ_RESPONSE; end if; elsif trans_st.read.curr_state = SEND and not ((st.last_sent_transaction = READ or st.last_sent_transaction = READ_ADD) and trans_st.write.curr_state = SEND) then if trans_st.read.is_first_word = '1' then local_next_tx_transaction := READ_ADD; else local_next_tx_transaction := READ; end if; if trans_st.read.curr_inst.seq_mem_access_count > MAX_PKT_SIZE then next_tx_data_size <= MAX_PKT_SIZE; elsif trans_st.read.curr_inst.seq_mem_access_count > 0 then next_tx_data_size <= trans_st.read.curr_inst.seq_mem_access_count; else next_tx_data_size <= 0; end if; elsif trans_st.write.curr_state = SEND and not st.read_in_flight then if trans_st.write.is_first_word = '1' then local_next_tx_transaction := WRITE_ADD; else local_next_tx_transaction := WRITE; end if; if trans_st.write.curr_inst.seq_mem_access_count > MAX_PKT_SIZE then next_tx_data_size <= MAX_PKT_SIZE; elsif trans_st.write.curr_inst.seq_mem_access_count > 0 then next_tx_data_size <= trans_st.write.curr_inst.seq_mem_access_count; else next_tx_data_size <= 0; end if; end if; next_tx_transaction <= local_next_tx_transaction; next_rx_transaction <= local_next_rx_transaction; next_data_out <= local_next_data_out; socbridge_driver_to_ip.valid <= valid_out; end process comb_proc; -- Process updating internal registers based on primary clock seq_proc: process(ext_to_socbridge_driver_rec.clk, st.ext_to_socbridge_driver_reg.data, rst, clk) begin if(rst = '1') then st.ext_to_socbridge_driver_reg.data <= (others => '0'); st.socbridge_driver_to_ext_reg.data <= (others => '0'); st.socbridge_driver_to_ext_reg.clk <= '0'; st.socbridge_driver_to_ext_reg.parity <= '1'; st.curr_tx_state <= IDLE; st.curr_rx_state <= IDLE; st.tx_stage <= 0; st.rx_stage <= 0; st.curr_tx_transaction <= NO_OP; st.curr_rx_transaction <= NO_OP; st.tx_data_size <= 0; st.rx_data_size <= 0; st.curr_rx_read_addr <= (others => '0'); st.curr_rx_write_addr <= (others => '0'); st.curr_write_data <= (others => '0'); st.curr_read_data <= (others => '0'); socbridge_driver_to_ip.data <= (others => '0'); st.read_in_flight <= false; st.write_in_flight <= false; st.last_sent_transaction <= NO_OP; valid_out <= '0'; elsif(rising_edge(ext_to_socbridge_driver_rec.clk)) then st.ext_to_socbridge_driver_reg.data <= ext_to_socbridge_driver_rec.data; st.ext_to_socbridge_driver_reg.clk <= ext_to_socbridge_driver_rec.clk; st.ext_to_socbridge_driver_reg.parity <= ext_to_socbridge_driver_rec.parity; st.socbridge_driver_to_ext_reg.data <= next_data_out; st.socbridge_driver_to_ext_reg.clk <= not st.socbridge_driver_to_ext_reg.clk; st.socbridge_driver_to_ext_reg.parity <= next_parity_out; st.curr_tx_state <= next_tx_state; st.curr_rx_state <= next_rx_state; valid_out <= '0'; case st.curr_tx_state is when IDLE => if ip_to_socbridge_driver.flush = '1' then st.last_sent_transaction <= NO_OP; end if; if (next_tx_transaction = WRITE or next_tx_transaction = WRITE_ADD or next_tx_transaction = READ or next_tx_transaction = READ_ADD) then if not st.read_in_flight or not st.write_in_flight then st.curr_tx_transaction <= next_tx_transaction; st.tx_data_size <= next_tx_data_size; else st.curr_tx_transaction <= NO_OP; st.tx_data_size <= 0; end if; else st.curr_tx_transaction <= next_tx_transaction; st.tx_data_size <= next_tx_data_size; end if; if next_tx_transaction = WRITE_ADD or next_tx_transaction = WRITE or next_tx_transaction = READ_RESPONSE then st.curr_tx_addr <= trans_st.write.curr_inst.address; st.tx_stage <= next_tx_data_size; else st.curr_tx_addr <= trans_st.read.curr_inst.address; st.tx_stage <= 0; end if; when TX_HEADER => if st.curr_tx_transaction = WRITE or st.curr_tx_transaction = WRITE_ADD then st.last_sent_transaction <= st.curr_tx_transaction; if not (st.curr_rx_state = RX_HEADER and st.curr_rx_transaction = WRITE_ACK) then st.write_in_flight <= true; end if; elsif st.curr_tx_transaction = READ or st.curr_tx_transaction = READ_ADD then st.last_sent_transaction <= st.curr_tx_transaction; if not (st.curr_rx_state = RX_HEADER and st.curr_rx_transaction = READ_RESPONSE) then st.read_in_flight <= true; end if; end if; when TX_W_BODY => if st.tx_stage > 0 then st.tx_stage <= st.tx_stage - 1; end if; when TX_R_BODY => if st.tx_stage > 0 then st.tx_stage <= st.tx_stage - 1; end if; when others => end case; case st.curr_rx_state is when IDLE => st.curr_rx_transaction <= next_rx_transaction; st.rx_data_size <= next_rx_data_size; if next_rx_transaction = WRITE_ADD or next_rx_transaction = WRITE or next_rx_transaction = READ_RESPONSE then st.rx_stage <= next_rx_data_size; else st.rx_stage <= 0; end if; when RX_HEADER => if st.curr_rx_transaction = WRITE_ACK then if not (st.curr_tx_state = TX_HEADER and (st.curr_tx_transaction = WRITE or st.curr_tx_transaction = WRITE_ADD)) then st.write_in_flight <= false; end if; if next_rx_transaction /= NO_OP then st.curr_rx_transaction <= next_rx_transaction; st.rx_data_size <= next_rx_data_size; if next_rx_transaction = WRITE_ADD or next_rx_transaction = WRITE or next_rx_transaction = READ_RESPONSE then st.rx_stage <= next_rx_data_size; else st.rx_stage <= 0; end if; end if; elsif st.curr_rx_transaction = READ_RESPONSE then if not (st.curr_tx_state = TX_HEADER and (st.curr_tx_transaction = READ or st.curr_tx_transaction = READ_ADD)) then st.read_in_flight <= false; end if; end if; when RX_R_BODY => valid_out <= '1'; socbridge_driver_to_ip.data <= st.ext_to_socbridge_driver_reg.data; if st.rx_stage > 0 then st.rx_stage <= st.rx_stage - 1; end if; if next_rx_transaction /= NO_OP and st.rx_stage <= 1 then st.curr_rx_transaction <= next_rx_transaction; st.rx_data_size <= next_rx_data_size; if next_rx_transaction = WRITE_ADD or next_rx_transaction = WRITE or next_rx_transaction = READ_RESPONSE then st.rx_stage <= next_rx_data_size; else st.rx_stage <= 0; end if; end if; when RX_W_BODY => if st.rx_stage > 0 then st.rx_stage <= st.rx_stage - 1; st.curr_write_data((((st.rx_stage - 1) mod 4) + 1) * 8 - 1 downto ((((st.rx_stage - 1) mod 4) + 1) - 1) * 8) <= st.ext_to_socbridge_driver_reg.data; end if; if (st.rx_stage - 2) mod 4 = 0 and st.rx_data_size - st.rx_stage > 4 then st.curr_rx_write_addr <= std_logic_vector(to_unsigned(to_integer(unsigned(st.curr_rx_write_addr) + 4), 32)); end if; when RX_AWAIT => st.curr_read_data <= manager_to_socbridge_driver.data; -- THIS DOESN'T WORK FOR LARGER THAN 4 BYTE ACCESSES, SHOULD BE FIXED BUT NOT NEEDED IF ONLY 4 BYTE ACCESSES ARRIVE if st.curr_tx_transaction = READ_RESPONSE or st.curr_tx_transaction = WRITE_ACK then if (st.curr_rx_transaction = READ or st.curr_rx_transaction = READ_ADD) and (st.tx_stage - 2) mod 4 = 0 then st.curr_rx_read_addr <= std_logic_vector(to_unsigned(to_integer(unsigned(st.curr_rx_read_addr) + 4), 32)); elsif (st.curr_rx_transaction = WRITE or st.curr_rx_transaction = WRITE_ADD) and (st.rx_stage - 2) mod 4 = 0 then st.curr_rx_write_addr <= std_logic_vector(to_unsigned(to_integer(unsigned(st.curr_rx_write_addr) + 4), 32)); end if; end if; when ADDR1 => if st.curr_rx_transaction = READ_ADD then st.curr_rx_read_addr(31 downto 24) <= st.ext_to_socbridge_driver_reg.data; else st.curr_rx_write_addr(31 downto 24) <= st.ext_to_socbridge_driver_reg.data; end if; when ADDR2 => if st.curr_rx_transaction = READ_ADD then st.curr_rx_read_addr(23 downto 16) <= st.ext_to_socbridge_driver_reg.data; else st.curr_rx_write_addr(23 downto 16) <= st.ext_to_socbridge_driver_reg.data; end if; when ADDR3 => if st.curr_rx_transaction = READ_ADD then st.curr_rx_read_addr(15 downto 8) <= st.ext_to_socbridge_driver_reg.data; else st.curr_rx_write_addr(15 downto 8) <= st.ext_to_socbridge_driver_reg.data; end if; when ADDR4 => if st.curr_rx_transaction = READ_ADD then st.curr_rx_read_addr(7 downto 0) <= st.ext_to_socbridge_driver_reg.data; else st.curr_rx_write_addr(7 downto 0) <= st.ext_to_socbridge_driver_reg.data; end if; when others => end case; end if; --- TRANSLATOR --- if(rst = '1') then trans_st.read.curr_state <= IDLE; trans_st.read.curr_inst.request <= '0'; trans_st.read.curr_inst.address <= (others => '0'); trans_st.read.curr_inst.seq_mem_access_count <= 0; trans_st.read.curr_inst.instruction <= NO_OP; trans_st.read.is_first_word <= '1'; trans_st.write.curr_state <= IDLE; trans_st.write.curr_inst.request <= '0'; trans_st.write.curr_inst.address <= (others => '0'); trans_st.write.curr_inst.seq_mem_access_count <= 0; trans_st.write.curr_inst.instruction <= NO_OP; trans_st.write.is_first_word <= '1'; elsif(rising_edge(ext_to_socbridge_driver_rec.clk)) then trans_st.read.curr_state <= trans_read_next_state; trans_st.write.curr_state <= trans_write_next_state; case trans_st.write.curr_state is when IDLE => if controller_to_socbridge_driver.request = '1' and controller_to_socbridge_driver.instruction = WRITE and trans_st.write.curr_inst.request = '0' then trans_st.write.curr_inst <= controller_to_socbridge_driver; else end if; trans_st.write.is_first_word <= '1'; when SEND => if trans_st.write.curr_inst.seq_mem_access_count mod 256 = 0 then trans_st.write.is_first_word <= '1'; elsif st.last_sent_transaction = READ or st.last_sent_transaction = READ_ADD or next_tx_transaction = READ or next_tx_transaction = READ_ADD then trans_st.write.is_first_word <= '1'; else trans_st.write.is_first_word <= '0'; end if; when SEND_ACCEPTED => trans_st.write.curr_inst.seq_mem_access_count <= trans_st.write.curr_inst.seq_mem_access_count - MAX_PKT_SIZE; trans_st.write.curr_inst.address <= std_logic_vector(unsigned(trans_st.write.curr_inst.address) + MAX_PKT_SIZE); when AWAIT => if ((ip_to_socbridge_driver.fifo.used_slots = 0 and ip_to_socbridge_driver.flush = '1') or trans_st.write.curr_inst.seq_mem_access_count <= 0) and st.curr_tx_state = TX_W_BODY then trans_st.write.curr_inst.request <= '0'; trans_st.write.curr_inst.address <= (others => '0'); trans_st.write.curr_inst.seq_mem_access_count <= 0; trans_st.write.curr_inst.instruction <= NO_OP; end if; if trans_st.write.curr_inst.seq_mem_access_count mod 256 = 0 then trans_st.write.is_first_word <= '1'; elsif st.last_sent_transaction = READ or st.last_sent_transaction = READ_ADD or next_tx_transaction = READ or next_tx_transaction = READ_ADD then trans_st.write.is_first_word <= '1'; else trans_st.write.is_first_word <= '0'; end if; when others => end case; case trans_st.read.curr_state is when IDLE => if controller_to_socbridge_driver.request = '1' and controller_to_socbridge_driver.instruction = READ then trans_st.read.curr_inst <= controller_to_socbridge_driver; else end if; trans_st.read.is_first_word <= '1'; when SEND => if trans_st.read.curr_inst.seq_mem_access_count mod 256 = 0 then trans_st.read.is_first_word <= '1'; elsif st.last_sent_transaction = WRITE or st.last_sent_transaction = WRITE_ADD or next_tx_transaction = WRITE or next_tx_transaction = WRITE_ADD then trans_st.read.is_first_word <= '1'; else trans_st.read.is_first_word <= '0'; end if; when SEND_ACCEPTED => trans_st.read.curr_inst.seq_mem_access_count <= trans_st.read.curr_inst.seq_mem_access_count - MAX_PKT_SIZE; trans_st.read.curr_inst.address <= std_logic_vector(unsigned(trans_st.read.curr_inst.address) + MAX_PKT_SIZE); when AWAIT => if (ip_to_socbridge_driver.flush = '1' or trans_st.read.curr_inst.seq_mem_access_count <= 0) and st.curr_tx_state = IDLE then trans_st.read.curr_inst.request <= '0'; trans_st.read.curr_inst.address <= (others => '0'); trans_st.read.curr_inst.seq_mem_access_count <= 0; trans_st.read.curr_inst.instruction <= NO_OP; end if; if trans_st.read.curr_inst.seq_mem_access_count mod 256 = 0 then trans_st.read.is_first_word <= '1'; elsif st.last_sent_transaction = WRITE or st.last_sent_transaction = WRITE_ADD or next_tx_transaction = WRITE or next_tx_transaction = WRITE_ADD then trans_st.read.is_first_word <= '1'; else trans_st.read.is_first_word <= '0'; end if; when others => end case; end if; end process seq_proc; end architecture rtl;