diff --git a/src/controller/control_unit.vhd b/src/controller/control_unit.vhd index 88f5730..d707c73 100644 --- a/src/controller/control_unit.vhd +++ b/src/controller/control_unit.vhd @@ -26,24 +26,19 @@ architecture behave of control_unit is end record state_t; signal state: state_t; - signal ored_reading: std_logic; - signal ored_writing: std_logic; + signal ored: std_logic; begin comb_proc: process(manager_to_controller, drivers_to_controller, state) - variable local_ored_reading : std_logic; - variable local_ored_writing : std_logic; + variable local_ored : std_logic; begin - local_ored_reading := '0'; - local_ored_writing := '0'; + local_ored := '0'; ready_reduction: for i in 0 to number_of_drivers - 1 loop - local_ored_reading := local_ored_reading or drivers_to_controller.socbridge.is_reading; - local_ored_writing := local_ored_writing or drivers_to_controller.socbridge.is_writing; + local_ored := local_ored or drivers_to_controller.socbridge.is_active; end loop ready_reduction; - ored_reading <= local_ored_reading; - ored_writing <= local_ored_writing; + ored <= local_ored; controller_to_drivers.socbridge.request <= state.curr_driver; controller_to_drivers.socbridge.address <= state.address; controller_to_drivers.socbridge.seq_mem_access_count <= state.seq_mem_access_count; @@ -62,13 +57,12 @@ begin state.instruction <= NO_OP; else -- Make sure to tell the management unit instruction is done - if (ored_writing = '0' and ored_reading = '0') and state.ready = '0' then + if ored = '0' and state.ready = '0' then state.ready <= '1'; else end if; - controller_to_manager.done_reading <= ored_reading; - controller_to_manager.done_writing <= ored_writing; - if ored_reading = '0' or ored_writing = '0' then + controller_to_manager.done <= ored; + if ored = '0' then state.address <= manager_to_controller.address; state.seq_mem_access_count <= manager_to_controller.seq_mem_access_count; state.curr_driver <= manager_to_controller.driver_id(0); diff --git a/src/ganimede/io_type_pkg.vhd b/src/ganimede/io_type_pkg.vhd index dd8271b..4cf73ff 100644 --- a/src/ganimede/io_type_pkg.vhd +++ b/src/ganimede/io_type_pkg.vhd @@ -37,7 +37,7 @@ package io_types is end record manager_to_controller_t; type controller_to_manager_t is record - ready, done_reading, done_writing : std_logic; + ready, done : std_logic; end record controller_to_manager_t; --- PROTOCOL INFORMATION --- @@ -47,8 +47,7 @@ package io_types is --- AUTOGENERATED TYPES --- type socbridge_driver_to_controller_t is record - is_reading : std_logic; - is_writing : std_logic; + is_active : std_logic; end record socbridge_driver_to_controller_t; type controller_to_socbridge_driver_t is record diff --git a/src/manager/management_unit.vhd b/src/manager/management_unit.vhd index caed8da..1dbed34 100644 --- a/src/manager/management_unit.vhd +++ b/src/manager/management_unit.vhd @@ -76,19 +76,19 @@ begin -- CLEAR BUFFER TO IP CORE end if; -- Is the controller done executing an instruction - elsif controller_to_manager.done_reading = '1' then + elsif controller_to_manager.done = '1' and cmd = "01" then manager_state.memory(0) <= manager_word_reset_val; - elsif controller_to_manager.done_writing = '1' then + elsif controller_to_manager.done = '1' and cmd = "10" then manager_state.memory(1) <= manager_word_reset_val; end if; -- Is there a read instruction in memory - if pack(read_address) /= empty_word and controller_to_manager.ready = '1' and controller_to_manager.done_reading = '0' then + if pack(read_address) /= empty_word and controller_to_manager.ready = '1' and controller_to_manager.done = '0' then manager_to_controller.address <= read_address.address & "0000000000"; manager_to_controller.driver_id <= "1"; -- Only supprts one driver at present manager_to_controller.seq_mem_access_count <= 2**to_integer(unsigned(read_address.size)) * 2**10; cmd <= "10"; -- Is there a write instruction in memory - elsif pack(write_address) /= empty_word and controller_to_manager.ready = '1' and controller_to_manager.done_writing = '0'then + elsif pack(write_address) /= empty_word and controller_to_manager.ready = '1' and controller_to_manager.done = '0'then manager_to_controller.address <= write_address.address & "0000000000"; manager_to_controller.driver_id <= "1"; -- Only supports one driver at present manager_to_controller.seq_mem_access_count <= 2**to_integer(unsigned(read_address.size)) * 2**10; diff --git a/src/socbridge/socbridge_driver.vhd b/src/socbridge/socbridge_driver.vhd index 0dcc2e1..88c9c66 100644 --- a/src/socbridge/socbridge_driver.vhd +++ b/src/socbridge/socbridge_driver.vhd @@ -7,8 +7,6 @@ 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 @@ -43,9 +41,8 @@ architecture rtl of socbridge_driver is 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; + signal trans_st : translator_state_rec_t; + signal trans_next_state : translator_state_t; --- FSM COMMUNICATION --- signal tx_sent_response, rx_received_response : std_logic; --- MANAGEMENT COMMUNICATION --- @@ -57,7 +54,8 @@ begin comb_proc: process(ext_to_socbridge_driver, ip_to_socbridge_driver, st, controller_to_socbridge_driver, trans_st, - tx_sent_response, rx_received_response) + 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; @@ -87,15 +85,10 @@ begin 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'; + if trans_st.curr_state = IDLE then + socbridge_driver_to_controller.is_active <= '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'; + socbridge_driver_to_controller.is_active <= '1'; end if; --- Next State Assignments --- @@ -153,7 +146,7 @@ begin 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 + and st.curr_rx_transaction = READ_RESPONSE and st.rx_stage = 1 then next_tx_state <= IDLE; else next_tx_state <= TX_AWAIT; @@ -260,11 +253,6 @@ begin 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 @@ -282,103 +270,74 @@ begin next_parity_out <= calc_parity(local_next_data_out); --- TRANSLATOR --- --- Next state assignment - case trans_st.write.curr_state is + case trans_st.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' then - trans_write_next_state <= SEND; + trans_next_state <= IDLE; + elsif trans_st.curr_inst.request = '1' then + trans_next_state <= SEND; else - trans_write_next_state <= IDLE; + trans_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; + if st.curr_tx_state /= IDLE then + trans_next_state <= SEND_ACCEPTED; else - trans_write_next_state <= SEND; + trans_next_state <= SEND; end if; -- Transisitonal state to decrement counter in transition between SEND and AWAIT. when SEND_ACCEPTED => - trans_write_next_state <= AWAIT; + trans_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 st.curr_tx_state = IDLE then - trans_write_next_state <= IDLE; + if trans_st.curr_inst.seq_mem_access_count <= 0 and st.curr_tx_state = IDLE then + trans_next_state <= IDLE; elsif st.curr_tx_state = IDLE then - trans_write_next_state <= SEND; + trans_next_state <= SEND; else - trans_write_next_state <= AWAIT; - end if; - end case; - case trans_st.read.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_read_next_state <= IDLE; - elsif trans_st.read.curr_inst.request = '1' 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 st.curr_tx_state = IDLE then - trans_read_next_state <= IDLE; - elsif st.curr_tx_state = IDLE then - trans_read_next_state <= SEND; - else - trans_read_next_state <= AWAIT; + trans_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 trans_st.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 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 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; + else + case trans_st.curr_state is + when IDLE => + when SEND => + if trans_st.is_first_word = '1' then + if trans_st.curr_inst.instruction = READ then + local_next_tx_transaction := READ_ADD; + elsif trans_st.curr_inst.instruction = WRITE then + local_next_tx_transaction := WRITE_ADD; + end if; + else + if trans_st.curr_inst.instruction = READ then + local_next_tx_transaction := READ; + elsif trans_st.curr_inst.instruction = WRITE then + local_next_tx_transaction := WRITE; + end if; + end if; + + if trans_st.curr_inst.seq_mem_access_count > MAX_PKT_SIZE then + next_tx_data_size <= MAX_PKT_SIZE; + elsif trans_st.curr_inst.seq_mem_access_count > 0 then + next_tx_data_size <= trans_st.curr_inst.seq_mem_access_count; + else + next_tx_data_size <= 0; + end if; + when others => + end case; end if; next_tx_transaction <= local_next_tx_transaction; @@ -402,6 +361,7 @@ begin st.curr_rx_transaction <= NO_OP; st.tx_data_size <= 0; st.rx_data_size <= 0; + st.curr_tx_addr <= (others => '0'); st.curr_rx_read_addr <= (others => '0'); st.curr_rx_write_addr <= (others => '0'); st.curr_write_data <= (others => '0'); @@ -418,16 +378,16 @@ begin 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 => st.curr_tx_transaction <= next_tx_transaction; st.tx_data_size <= next_tx_data_size; + st.curr_tx_addr <= trans_st.curr_inst.address; 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_W_BODY => @@ -462,9 +422,6 @@ begin 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 @@ -506,76 +463,36 @@ begin --- 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 + trans_st.curr_state <= IDLE; + trans_st.curr_inst.request <= '0'; + trans_st.curr_inst.address <= (others => '0'); + trans_st.curr_inst.seq_mem_access_count <= 0; + trans_st.curr_inst.instruction <= NO_OP; + trans_st.is_first_word <= '1'; + elsif(rising_edge(clk)) then + trans_st.curr_state <= trans_next_state; + case trans_st.curr_state is when IDLE => - if controller_to_socbridge_driver.request = '1' and controller_to_socbridge_driver.instruction = WRITE then - trans_st.write.curr_inst <= controller_to_socbridge_driver; + if controller_to_socbridge_driver.request = '1' then + trans_st.curr_inst <= controller_to_socbridge_driver; else end if; - trans_st.write.is_first_word <= '1'; + trans_st.is_first_word <= '1'; when SEND => 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); + trans_st.curr_inst.seq_mem_access_count <= trans_st.curr_inst.seq_mem_access_count - MAX_PKT_SIZE; when AWAIT => - if trans_st.write.curr_inst.seq_mem_access_count <= 0 and st.curr_tx_state = IDLE 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 trans_st.read.curr_inst.instruction /= NO_OP 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 => - 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 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 trans_st.write.curr_inst.instruction /= NO_OP then - trans_st.read.is_first_word <= '1'; - else - trans_st.read.is_first_word <= '0'; + if trans_st.curr_inst.seq_mem_access_count <= 0 and st.curr_tx_state = IDLE then + trans_st.curr_inst.request <= '0'; + trans_st.curr_inst.address <= (others => '0'); + trans_st.curr_inst.seq_mem_access_count <= 0; + trans_st.curr_inst.instruction <= NO_OP; end if; + trans_st.is_first_word <= '0'; when others => end case; end if; end process seq_proc; end architecture rtl; + diff --git a/src/socbridge/socbridge_driver_pkg.vhd b/src/socbridge/socbridge_driver_pkg.vhd index 85385a0..7499277 100644 --- a/src/socbridge/socbridge_driver_pkg.vhd +++ b/src/socbridge/socbridge_driver_pkg.vhd @@ -20,18 +20,13 @@ package socbridge_driver_pkg is (IDLE, ADDR1, ADDR2, ADDR3, ADDR4, TX_AWAIT, TX_HEADER, TX_W_BODY, TX_R_BODY); --- TRANSLATOR --- - type ctrl_inst_state_t is (IDLE, SEND, SEND_ACCEPTED, AWAIT); + type translator_state_t is (IDLE, SEND, SEND_ACCEPTED, AWAIT); - type ctrl_inst_state_rec_t is record + type translator_state_rec_t is record curr_inst : controller_to_socbridge_driver_t; - curr_state : ctrl_inst_state_t; + curr_state : translator_state_t; is_first_word : std_logic; - end record ctrl_inst_state_rec_t; - - type translator_state_t is record - read: ctrl_inst_state_rec_t; - write: ctrl_inst_state_rec_t; - end record translator_state_t; + end record translator_state_rec_t; type ext_protocol_t is record data : std_logic_vector(interface_inst.socbridge.payload_width - 1 downto 0); @@ -166,3 +161,4 @@ package body socbridge_driver_pkg is return val; end function; end package body socbridge_driver_pkg; +