From c6c5d2d7fc74083b06f2e996433841f30cfa7ce1 Mon Sep 17 00:00:00 2001 From: Adam Date: Thu, 3 Apr 2025 12:23:51 +0200 Subject: [PATCH] RX FSM almost done --- src/socbridge/socbridge_driver.vhd | 105 +++++++++++----------- src/socbridge/socbridge_driver_tb_pkg.vhd | 15 ++-- 2 files changed, 60 insertions(+), 60 deletions(-) diff --git a/src/socbridge/socbridge_driver.vhd b/src/socbridge/socbridge_driver.vhd index 36fb01e..4fe4acb 100644 --- a/src/socbridge/socbridge_driver.vhd +++ b/src/socbridge/socbridge_driver.vhd @@ -25,6 +25,7 @@ architecture rtl of socbridge_driver is signal next_parity_out : std_logic; signal ext_to_socbridge_driver_rec : ext_protocol_t; shared variable socbridge_driver_to_ext_data_cmd : std_logic_vector(interface_inst.socbridge.payload_width - 1 downto 0); + shared variable next_rx_transaction : transaction_t; signal test : std_logic_vector(interface_inst.socbridge.payload_width - 1 downto 0); signal next_cmd : command_t; signal next_cmd_size : integer; @@ -72,19 +73,30 @@ begin -- 00001 | 00001001 | 00001001 -- 00001 | 00001001 | 00001001 - with curr_response_bits select - curr_response <= WRITE_ACK when "00001", - WRITE_ACK when "00101", - READ_RESPONSE when "01000", - READ_RESPONSE when "01100", - NO_OP when others; - comb_proc: process(ext_to_socbridge_driver, ip_to_socbridge_driver, curr_response, st, controller_to_socbridge_driver, trans_st) + comb_proc: process(ext_to_socbridge_driver, ip_to_socbridge_driver, st, controller_to_socbridge_driver, trans_st) begin -- Outputs socbridge_driver_to_ext <= create_io_type_out_from_ext_protocol(st.socbridge_driver_to_ext_reg); with trans_st.curr_state select socbridge_driver_to_controller.is_active <= '0' when IDLE, '1' when others; + if curr_response_bits = "10000" then + next_rx_transaction := WRITE_ADD; + elsif curr_response_bits = "10100" then + next_rx_transaction := WRITE; + elsif curr_response_bits = "11000" then + next_rx_transaction := READ_ADD; + elsif curr_response_bits = "11100" then + next_rx_transaction := READ; + elsif curr_response_bits = "01001" then -- TODO Might have to check bits 2:0 + next_rx_transaction := P_ERR; + elsif curr_response_bits = "00101" then + next_rx_transaction := WRITE_ACK; + elsif curr_response_bits = "01100" then + next_rx_transaction := READ_RESPONSE; + else + next_rx_transaction := NO_OP; + end if; --- State Transition Diagram OUTDATED!! --- -- @@ -127,43 +139,31 @@ begin --- Next State Assignment Of RX FSM --- case st.curr_rx_state is when IDLE => - if PACKET_TYPE = COMMAND then -- TODO Make this a real type and variable - next_rx_state <= CMD; - elsif PACKET_TYPE = RESPONSE then - next_rx_state <= RX_BODY; + if next_rx_transaction /= NO_OP then + next_rx_state <= RX_HEADER; else next_rx_state <= IDLE; end if; - when CMD => - -- TODO This should be changed to not to check 'st.curr_cmd' but rather - -- the command received which may not be the same variable - if st.curr_cmd = WRITE_ADD then + when RX_HEADER => + -- The header only takes one word (cycle) to transmit. + -- Continue to awaiting response directly afterwards. + if next_rx_transaction = READ_ADD or next_rx_transaction = WRITE_ADD then next_rx_state <= ADDR1; - elsif st.curr_cmd = WRITE then - next_rx_state <= PAYLOAD; - elsif st.curr_cmd = READ_ADD then - next_rx_state <= ADDR1; - elsif st.curr_cmd = READ then - next_rx_state <= GEN_ACCESS; + elsif next_rx_transaction = WRITE_ACK then + next_rx_state <= IDLE; + elsif next_rx_transaction = WRITE or next_rx_transaction = READ_RESPONSE then + next_rx_state <= RX_BODY; + elsif next_rx_transaction = WRITE_ACK then + + elsif next_rx_transaction = WRITE_ACK then + elsif next_rx_transaction = WRITE_ACK then + else + -- Bogus command + next_rx_state <= IDLE; end if; - --when RX_HEADER => - ---- The header only takes one word (cycle) to transmit. - ---- Continue to awaiting response directly afterwards. - -- if st.curr_cmd = READ_ADD then - -- next_rx_state <= ADDR1; - -- else - -- next_rx_state <= RX_RESPONSE; - -- end if; - --when RX_RESPONSE => - ---- Wait for read response. - -- if curr_response = READ_RESPONSE then - -- next_rx_state <= RX_BODY; - -- else - -- next_rx_state <= RX_RESPONSE; - -- end if; when RX_BODY => -- Here we want to stay in RX_BODY for the duration of a packet. - if st.read_stage = 0 then + if st.rx_stage = 0 then next_rx_state <= IDLE; else next_rx_state <= RX_BODY; @@ -176,11 +176,12 @@ begin when ADDR3 => next_rx_state <= ADDR4; when ADDR4 => - -- TODO this should probably not be dependant on state's instruction - if st.curr_cmd = WRITE or st.curr_cmd = WRITE_ADD then - next_rx_state <= PAYLOAD; - else + if next_rx_transaction = WRITE_ADD then next_rx_state <= RX_BODY; + elsif next_rx_transaction = READ_ADD then + next_rx_state <= TELL_TX_TO_SEND_A_READ_RESPONSE; + else + next_rx_state <= IDLE; -- Potentially superfluous safety end if; end case; @@ -199,10 +200,10 @@ begin end if; when RESPONSE => -- TODO consider whether this should be moved to TX_BODY - if MORE_RESPONSE then - next_tx_state <= RESPONSE; - else + if st.tx_stage = 0 then next_tx_state <= IDLE; + else + next_tx_state <= RESPONSE; end if; when TX_HEADER => -- The header only takes one word (cycle) to transmit. @@ -240,14 +241,14 @@ begin else -- If it is a read instruction we wait for response. -- TODO separate read from NO_OP and P_ERR - next_tx_state <= AWAIT; + next_tx_state <= AWAIT_ACK; end if; - when AWAIT => + when AWAIT_ACK => -- Wait for RX FSM to get a response - if st.curr_rx_state = RX_BODY and st.read_stage = 0 then + if next_rx_transaction = WRITE_ACK then next_tx_state <= IDLE; else - next_tx_state <= AWAIT; + next_tx_state <= AWAIT_ACK; end if; end case; @@ -378,7 +379,7 @@ begin st.socbridge_driver_to_ext_reg.parity <= '1'; st.curr_state <= IDLE; st.write_stage <= 0; - st.read_stage <= 0; + st.rx_stage <= 0; st.curr_cmd <= NO_OP; st.curr_cmd_size <= 0; st.curr_addr <= (others => '0'); @@ -398,7 +399,7 @@ begin st.curr_addr <= trans_st.curr_inst.address; if next_cmd_size > 0 then st.write_stage <= next_cmd_size - 1; - st.read_stage <= next_cmd_size - 1; + st.rx_stage <= next_cmd_size - 1; end if; when TX_HEADER => when TX_BODY => @@ -410,8 +411,8 @@ begin st.curr_cmd_size <= 0; when RX_HEADER => when RX_BODY => - if st.read_stage > 0 then - st.read_stage <= st.read_stage - 1; + if st.rx_stage > 0 then + st.rx_stage <= st.rx_stage - 1; else st.curr_cmd <= NO_OP; st.curr_cmd_size <= 0; diff --git a/src/socbridge/socbridge_driver_tb_pkg.vhd b/src/socbridge/socbridge_driver_tb_pkg.vhd index 453e3fb..5e4e34f 100644 --- a/src/socbridge/socbridge_driver_tb_pkg.vhd +++ b/src/socbridge/socbridge_driver_tb_pkg.vhd @@ -9,20 +9,17 @@ use ganimede.io_types.all; package socbridge_driver_tb_pkg is subtype command_size_t is integer range 0 to 128; - 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 transaction_t is + (NO_OP, WRITE_ADD, WRITE, READ_ADD, READ, P_ERR, WRITE_ACK, READ_RESPONSE); type rx_state_t is (IDLE, ADDR1, ADDR2, ADDR3, ADDR4, - CMD, RESPONSE, READ, WRITE, PAYLOAD, + RESPONSE, READ, WRITE, PAYLOAD, RX_HEADER, RX_RESPONSE, RX_BODY); type tx_state_t is (IDLE, ADDR1, ADDR2, ADDR3, ADDR4, - CMD, RESPONSE, READ, WRITE, PAYLOAD, AWAIT, + RESPONSE, READ, WRITE, PAYLOAD, AWAIT_ACK, TX_HEADER, TX_BODY, TX_ACK); --- TRANSLATOR --- type translator_state_t is (IDLE, SEND, SEND_ACCEPTED, AWAIT); @@ -40,10 +37,12 @@ package socbridge_driver_tb_pkg is end record ext_protocol_t; type state_rec_t is record + curr_rx_transaction : transaction_t; + curr_tx_transaction : transaction_t; curr_rx_state: rx_state_t; curr_tx_state: tx_state_t; ext_to_socbridge_driver_reg, socbridge_driver_to_ext_reg : ext_protocol_t; - write_stage, read_stage : NATURAL; + write_stage, rx_stage : NATURAL; curr_cmd : command_t; curr_cmd_size: integer; curr_addr : std_logic_vector(31 downto 0);