Compare commits

...

3 Commits

6 changed files with 95 additions and 188 deletions

View File

@ -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);

View File

@ -53,7 +53,8 @@ begin
techmap_ram_inst : entity techmap.syncram_2p
generic map(tech => tech,
abits => address_bits,
dbits => fifo_width
dbits => fifo_width,
sepclk => 1
)
port map(
rclk => out_clk,
@ -97,8 +98,8 @@ begin
if rising_edge(in_clk) and valid_in = '1' and buffer_full = '0' then
write_pointer <= std_logic_vector(unsigned(write_pointer) + 1);
end if;
if rising_edge(out_clk) then
if ready_in = '1' and buffer_empty = '0' and unsigned(read_pointer) + 1 /= unsigned(write_pointer) then
if falling_edge(out_clk) then
if ready_in = '1' and buffer_empty = '0' then
read_pointer <= std_logic_vector(unsigned(read_pointer) + 1);
valid_out <= '1';
else

View File

@ -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

View File

@ -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 = "10" 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 = "01" 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;

View File

@ -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;

View File

@ -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;