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 := 8; 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; --- 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 --- --- MANAGEMENT COMMUNICATION --- begin comb_proc: process(ext_to_socbridge_driver_rec, ip_to_socbridge_driver, controller_to_socbridge_driver, st, trans_st) 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 -- 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; socbridge_driver_to_ip.used_slots <= 0; next_rx_data_size <= 2 ** to_integer(unsigned(ext_to_socbridge_driver_rec.data(2 downto 0))); curr_response_bits := ext_to_socbridge_driver_rec.data(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.state = IDLE then socbridge_driver_to_controller.is_reading <= '0'; else socbridge_driver_to_controller.is_reading <= '1'; end if; if trans_st.write.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.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.tx_transaction = WRITE_ADD or st.tx_transaction = READ_ADD then next_tx_state <= ADDR1; elsif st.tx_transaction = WRITE then next_tx_state <= TX_W_BODY; elsif st.tx_transaction = READ then next_tx_state <= IDLE; -- Responses elsif st.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.tx_transaction = READ_ADD then next_tx_state <= IDLE; elsif st.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; end case; --- Next State Assignment Of RX FSM --- case st.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.rx_transaction = WRITE_ADD or st.rx_transaction = READ_ADD then next_rx_state <= ADDR1; elsif st.rx_transaction = WRITE then next_rx_state <= RX_W_BODY; elsif st.rx_transaction = READ then next_rx_state <= RX_AWAIT; -- Responses elsif st.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.rx_transaction = READ_ADD then next_rx_state <= RX_AWAIT; elsif st.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.rx_transaction = WRITE_ADD or st.rx_transaction = WRITE) and st.tx_transaction = WRITE_ACK then next_rx_state <= IDLE; elsif (st.rx_transaction = READ_ADD or st.rx_transaction = READ) and st.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.tx_state is when IDLE => when TX_HEADER => if st.tx_transaction = WRITE_ACK or st.tx_transaction = READ_RESPONSE then local_next_data_out := get_header_bits(st.tx_transaction, st.rx_transaction) & get_size_bits(st.rx_data_size); else local_next_data_out := get_header_bits(st.tx_transaction, st.rx_transaction) & get_size_bits(st.tx_data_size); end if; if st.tx_transaction = WRITE then socbridge_driver_to_ip.ready <= '1'; end if; when TX_W_BODY => if st.tx_stage > 1 then socbridge_driver_to_ip.ready <= '1'; end if; if st.tx_stage > 0 then 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.manager_data((((st.tx_stage - 1) mod 4) + 1) * 8 - 1 downto ((((st.tx_stage - 1) mod 4) + 1) - 1) * 8); end if; when ADDR1 => local_next_data_out := st.tx_addr(31 downto 24); when ADDR2 => local_next_data_out := st.tx_addr(23 downto 16); when ADDR3 => local_next_data_out := st.tx_addr(15 downto 8); when ADDR4 => local_next_data_out := st.tx_addr(7 downto 0); if st.tx_transaction = WRITE_ADD then socbridge_driver_to_ip.ready <= '1'; end if; end case; --- ### RX_STATE BASED OUTPUT ### --- socbridge_driver_to_manager.valid <= '0'; socbridge_driver_to_manager.data <= st.manager_data; socbridge_driver_to_manager.address <= st.manager_addr; socbridge_driver_to_ip.valid <= '0'; socbridge_driver_to_ip.data <= st.ext_to_socbridge_driver_reg.data; case st.rx_state is when RX_W_BODY => if st.rx_stage mod 4 = 0 and st.rx_stage /= st.rx_data_size then socbridge_driver_to_manager.valid <= '1'; end if; when RX_R_BODY => socbridge_driver_to_ip.valid <= '1'; when RX_AWAIT => if st.rx_transaction = WRITE or st.rx_transaction = WRITE_ADD then socbridge_driver_to_manager.valid <= '1'; end if; when others => end case; next_parity_out <= calc_parity(local_next_data_out); --- TRANSLATOR --- --- Next state assignment case trans_st.write.state is when IDLE => if st.rx_transaction = READ or st.rx_transaction = READ_ADD or st.rx_transaction = WRITE or st.rx_transaction = WRITE_ADD then trans_write_next_state <= IDLE; elsif trans_st.write.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.tx_transaction = WRITE or st.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.inst.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.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.rx_transaction = READ or st.rx_transaction = READ_ADD or st.rx_transaction = WRITE or st.rx_transaction = WRITE_ADD then trans_read_next_state <= IDLE; elsif trans_st.read.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.tx_transaction = READ or st.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.inst.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.state = IDLE and trans_st.write.state = IDLE and st.rx_state = RX_AWAIT then if (st.rx_transaction = WRITE or st.rx_transaction = WRITE_ADD) and manager_to_socbridge_driver.ready = '1' then local_next_tx_transaction := WRITE_ACK; elsif (st.rx_transaction = READ or st.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.state = SEND and not ((st.last_sent_transaction = READ or st.last_sent_transaction = READ_ADD) and trans_st.write.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.inst.access_count > MAX_PKT_SIZE then next_tx_data_size <= MAX_PKT_SIZE; elsif trans_st.read.inst.access_count > 0 then next_tx_data_size <= trans_st.read.inst.access_count; else next_tx_data_size <= 0; end if; elsif trans_st.write.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.inst.access_count > MAX_PKT_SIZE then next_tx_data_size <= MAX_PKT_SIZE; elsif trans_st.write.inst.access_count > 0 then next_tx_data_size <= trans_st.write.inst.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; end process comb_proc; -- Process updating internal registers based on primary clock seq_proc: process(ext_to_socbridge_driver_rec.clk, rst, clk) begin if(rst = '1') then st <= st_reset_vec; elsif(rising_edge(ext_to_socbridge_driver_rec.clk)) then st.ext_to_socbridge_driver_reg.data <= ext_to_socbridge_driver_rec.data; -- PARITY CHECK NOT IMPLEMENTED, REMOVING --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.tx_state <= next_tx_state; st.rx_state <= next_rx_state; case st.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.tx_transaction <= next_tx_transaction; st.tx_data_size <= next_tx_data_size; else st.tx_transaction <= NO_OP; st.tx_data_size <= 0; end if; else st.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.tx_addr <= trans_st.write.inst.address; st.tx_stage <= next_tx_data_size; else st.tx_addr <= trans_st.read.inst.address; st.tx_stage <= 0; end if; when TX_HEADER => if st.tx_transaction = WRITE or st.tx_transaction = WRITE_ADD then st.last_sent_transaction <= st.tx_transaction; if not (st.rx_state = RX_HEADER and st.rx_transaction = WRITE_ACK) then st.write_in_flight <= true; end if; elsif st.tx_transaction = READ or st.tx_transaction = READ_ADD then st.last_sent_transaction <= st.tx_transaction; if not (st.rx_state = RX_HEADER and st.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.rx_state is when IDLE => st.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.rx_transaction = WRITE_ACK then if not (st.tx_state = TX_HEADER and (st.tx_transaction = WRITE or st.tx_transaction = WRITE_ADD)) then st.write_in_flight <= false; end if; if next_rx_transaction /= NO_OP then st.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.rx_transaction = READ_RESPONSE then if not (st.tx_state = TX_HEADER and (st.tx_transaction = READ or st.tx_transaction = READ_ADD)) then st.read_in_flight <= false; end if; end if; when RX_R_BODY => 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.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.manager_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.manager_addr <= std_logic_vector(to_unsigned(to_integer(unsigned(st.manager_addr) + 4), 32)); end if; when RX_AWAIT => st.manager_data <= manager_to_socbridge_driver.data; if st.tx_transaction = READ_RESPONSE or st.tx_transaction = WRITE_ACK then if (st.rx_transaction = READ or st.rx_transaction = READ_ADD) and (st.tx_stage - 2) mod 4 = 0 then st.manager_addr <= std_logic_vector(to_unsigned(to_integer(unsigned(st.manager_addr) + 4), 32)); elsif (st.rx_transaction = WRITE or st.rx_transaction = WRITE_ADD) and (st.rx_stage - 2) mod 4 = 0 then st.manager_addr <= std_logic_vector(to_unsigned(to_integer(unsigned(st.manager_addr) + 4), 32)); end if; end if; when ADDR1 => if st.rx_transaction = READ_ADD then st.manager_addr(31 downto 24) <= st.ext_to_socbridge_driver_reg.data; else st.manager_addr(31 downto 24) <= st.ext_to_socbridge_driver_reg.data; end if; when ADDR2 => if st.rx_transaction = READ_ADD then st.manager_addr(23 downto 16) <= st.ext_to_socbridge_driver_reg.data; else st.manager_addr(23 downto 16) <= st.ext_to_socbridge_driver_reg.data; end if; when ADDR3 => if st.rx_transaction = READ_ADD then st.manager_addr(15 downto 8) <= st.ext_to_socbridge_driver_reg.data; else st.manager_addr(15 downto 8) <= st.ext_to_socbridge_driver_reg.data; end if; when ADDR4 => if st.rx_transaction = READ_ADD then st.manager_addr(7 downto 0) <= st.ext_to_socbridge_driver_reg.data; else st.manager_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 <= translator_reset_vec; elsif(rising_edge(ext_to_socbridge_driver_rec.clk)) then trans_st.read.state <= trans_read_next_state; trans_st.write.state <= trans_write_next_state; case trans_st.write.state is when IDLE => if controller_to_socbridge_driver.request = '1' and controller_to_socbridge_driver.instruction = WRITE and trans_st.write.inst.request = '0' then trans_st.write.inst.request <= controller_to_socbridge_driver.request; trans_st.write.inst.address <= controller_to_socbridge_driver.address; trans_st.write.inst.access_count <= controller_to_socbridge_driver.seq_mem_access_count; else end if; trans_st.write.is_first_word <= '1'; when SEND => if trans_st.write.inst.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.inst.access_count <= trans_st.write.inst.access_count - MAX_PKT_SIZE; trans_st.write.inst.address <= std_logic_vector(unsigned(trans_st.write.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.inst.access_count <= 0) and st.tx_state = TX_W_BODY then trans_st.write.inst <= ctrl_inst_reset_vec; end if; if trans_st.write.inst.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.state is when IDLE => if controller_to_socbridge_driver.request = '1' and controller_to_socbridge_driver.instruction = READ then trans_st.read.inst.request <= controller_to_socbridge_driver.request; trans_st.read.inst.address <= controller_to_socbridge_driver.address; trans_st.read.inst.access_count <= controller_to_socbridge_driver.seq_mem_access_count; else end if; trans_st.read.is_first_word <= '1'; when SEND => if trans_st.read.inst.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.inst.access_count <= trans_st.read.inst.access_count - MAX_PKT_SIZE; trans_st.read.inst.address <= std_logic_vector(unsigned(trans_st.read.inst.address) + MAX_PKT_SIZE); when AWAIT => if (ip_to_socbridge_driver.flush = '1' or trans_st.read.inst.access_count <= 0) and st.tx_state = IDLE then trans_st.read.inst <= ctrl_inst_reset_vec; end if; if trans_st.read.inst.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;