From 5824ea5d9a34632b0f250eeb132b1ea261e76b07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20=C3=96rtenberg?= Date: Wed, 28 May 2025 17:02:46 +0200 Subject: [PATCH] added all required functionality for correct execution (except for read buffer aware reads) --- src/fifo_buffer/fifo_buffer.vhd | 150 ++++++++++++++++++++++---- src/fifo_buffer/fifo_deserializer.vhd | 74 +++++++++++++ src/fifo_buffer/fifo_serializer.vhd | 76 +++++++++++++ src/ganimede/ganimede.vhd | 11 +- src/manager/management_unit.vhd | 4 +- src/socbridge/socbridge_driver.vhd | 30 ++++-- 6 files changed, 312 insertions(+), 33 deletions(-) create mode 100644 src/fifo_buffer/fifo_deserializer.vhd create mode 100644 src/fifo_buffer/fifo_serializer.vhd diff --git a/src/fifo_buffer/fifo_buffer.vhd b/src/fifo_buffer/fifo_buffer.vhd index 9b16421..bf6453f 100644 --- a/src/fifo_buffer/fifo_buffer.vhd +++ b/src/fifo_buffer/fifo_buffer.vhd @@ -20,7 +20,8 @@ entity fifo_buffer is valid_in : in std_logic; valid_out : out std_logic; data_in : in std_logic_vector(data_width - 1 downto 0); - data_out : out std_logic_vector(data_width - 1 downto 0) + data_out : out std_logic_vector(data_width - 1 downto 0); + used_slots : out integer range 0 to buffer_size ); end entity fifo_buffer; @@ -34,26 +35,11 @@ architecture rtl of fifo_buffer is signal inverted_in_clock : std_logic; signal customout : std_logic_vector(0 downto 0); -- techmap needs customout and it is does not have a default value for some reason begin - --- DECLARATION OF NX_SYNCRAM ---entity nx_syncram_be is --- generic ( abits : integer := 6; --- dbits : integer := 8 --- ); --- port ( --- clk : in std_ulogic; --- address : in std_logic_vector (abits -1 downto 0); --- datain : in std_logic_vector (dbits -1 downto 0); --- dataout : out std_logic_vector (dbits -1 downto 0); --- enable : in std_logic_vector (dbits/8-1 downto 0); --- write : in std_logic_vector (dbits/8-1 downto 0) --- ); ---end; techmap_ram_inst : entity techmap.syncram_2p generic map(tech => tech, abits => address_bits, - dbits => fifo_width, + dbits => data_width, sepclk => 1 ) port map( @@ -73,6 +59,11 @@ begin comb_proc: process(write_pointer, read_pointer, buffer_full, valid_in, rst) variable write_pointer_inc : unsigned(address_bits - 1 downto 0); begin + if write_pointer >= read_pointer then + used_slots <= to_integer(unsigned(write_pointer) - unsigned(read_pointer)); + else + used_slots <= buffer_size - to_integer(unsigned(read_pointer)) + to_integer(unsigned(write_pointer)); + end if; ready_out <= not buffer_full; write_signal <= (valid_in and not buffer_full) or rst; write_pointer_inc := unsigned(write_pointer) + 1; @@ -95,11 +86,13 @@ begin read_pointer <= (others => '0'); write_pointer <= (others => '0'); else - if rising_edge(in_clk) and valid_in = '1' and buffer_full = '0' then - write_pointer <= std_logic_vector(unsigned(write_pointer) + 1); + if rising_edge(in_clk) then + if valid_in = '1' and buffer_full = '0'then + write_pointer <= std_logic_vector(unsigned(write_pointer) + 1); + end if; end if; - if falling_edge(out_clk) then - if ready_in = '1' and buffer_empty = '0' then + if rising_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 @@ -110,3 +103,118 @@ begin end process seq_proc; end architecture rtl; + + + +--library IEEE; +--use IEEE.std_logic_1164.all; +--use IEEE.MATH_REAL.all; +--use ieee.numeric_std.all; +--library gan_ganimede; +--use gan_ganimede.io_types.all; +--library techmap; +--use techmap.gencomp.all; +-- +--entity fifo_buffer is +-- generic ( +-- buffer_size : natural := 64; +-- tech : integer := 0; +-- data_width : natural := 8 +-- ); +-- port ( +-- rst, in_clk, out_clk : in std_logic; +-- ready_in : in std_logic; +-- ready_out : out std_logic; +-- valid_in : in std_logic; +-- valid_out : out std_logic; +-- data_in : in std_logic_vector(data_width - 1 downto 0); +-- data_out : out std_logic_vector(data_width - 1 downto 0) +-- ); +--end entity fifo_buffer; +-- +--architecture rtl of fifo_buffer is +-- constant address_bits : natural := integer(ceil(log2(real(buffer_size)))); +-- signal read_pointer : std_logic_vector(address_bits - 1 downto 0); +-- signal write_pointer : std_logic_vector(address_bits - 1 downto 0); +-- signal write_signal : std_logic; +-- signal buffer_full : std_logic; +-- signal buffer_empty : std_logic; +-- signal inverted_in_clock : std_logic; +-- signal customout : std_logic_vector(0 downto 0); -- techmap needs customout and it is does not have a default value for some reason +--begin +-- +---- DECLARATION OF NX_SYNCRAM +----entity nx_syncram_be is +---- generic ( abits : integer := 6; +---- dbits : integer := 8 +---- ); +---- port ( +---- clk : in std_ulogic; +---- address : in std_logic_vector (abits -1 downto 0); +---- datain : in std_logic_vector (dbits -1 downto 0); +---- dataout : out std_logic_vector (dbits -1 downto 0); +---- enable : in std_logic_vector (dbits/8-1 downto 0); +---- write : in std_logic_vector (dbits/8-1 downto 0) +---- ); +----end; +-- +-- techmap_ram_inst : entity techmap.syncram_2p +-- generic map(tech => tech, +-- abits => address_bits, +-- dbits => data_width, +-- sepclk => 1 +-- ) +-- port map( +-- rclk => out_clk, +-- renable => '1', +-- raddress => read_pointer, +-- dataout => data_out, +-- wclk => inverted_in_clock, +-- write => write_signal, +-- waddress => write_pointer, +-- datain => data_in, +-- customclk => in_clk, --NOTE: No clue what this does but it has to be set to something +-- customout => customout +-- ); +-- +-- inverted_in_clock <= not in_clk; +--comb_proc: process(write_pointer, read_pointer, buffer_full, valid_in, rst) +-- variable write_pointer_inc : unsigned(address_bits - 1 downto 0); +--begin +-- ready_out <= not buffer_full; +-- write_signal <= (valid_in and not buffer_full) or rst; +-- write_pointer_inc := unsigned(write_pointer) + 1; +-- customout <= "0"; +-- if write_pointer_inc = unsigned(read_pointer) then +-- buffer_full <= '1'; +-- else +-- buffer_full <= '0'; +-- end if; +-- if write_pointer = read_pointer then +-- buffer_empty <= '1'; +-- else +-- buffer_empty <= '0'; +-- end if; +--end process comb_proc; +-- +--seq_proc: process(rst, in_clk, out_clk, buffer_full, valid_in, ready_in, buffer_empty, write_pointer, read_pointer) +--begin +-- if rst = '1' then +-- read_pointer <= (others => '0'); +-- write_pointer <= (others => '0'); +-- else +-- 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 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 +-- valid_out <= '0'; +-- end if; +-- end if; +-- end if; +--end process seq_proc; +-- +--end architecture rtl; diff --git a/src/fifo_buffer/fifo_deserializer.vhd b/src/fifo_buffer/fifo_deserializer.vhd new file mode 100644 index 0000000..0b51657 --- /dev/null +++ b/src/fifo_buffer/fifo_deserializer.vhd @@ -0,0 +1,74 @@ +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.MATH_REAL.all; +use ieee.numeric_std.all; + +entity fifo_deserializer is + generic ( + output_width : natural := 8; + input_width : natural := 8; + endianess : integer := 0 -- 0: little endian, 1: big endian + ); + port ( + rst, clk : in std_logic; + ready_in : in std_logic; + ready_out : out std_logic; + valid_in : in std_logic; + valid_out : out std_logic; + data_in : in std_logic_vector(input_width - 1 downto 0); + data_out : out std_logic_vector(output_width - 1 downto 0) + ); +end entity fifo_deserializer; + +architecture rtl of fifo_deserializer is + +constant out_over_in : natural := output_width / input_width - 1; +type state_t is record + count : integer; + data : std_logic_vector(output_width - 1 downto 0); + full_word : std_logic; + prev_ready : std_logic; +end record state_t; +signal st : state_t; +begin + +comb_proc: process(rst,clk,valid_in,ready_in,data_in,st) +begin + if st.full_word = '1' and ready_in = '1' then + valid_out <= '1'; + else + valid_out <= '0'; + end if; + ready_out <= ready_in; + data_out <= st.data; +end process comb_proc; + +seq_proc: process(clk, rst) +begin + if rst = '1' then + st.count <= 0; + st.data <= (others => '0'); + st.full_word <= '0'; + st.prev_ready <= '0'; + elsif (rising_edge(clk)) then + st.prev_ready <= ready_in; + if valid_in = '1' and st.prev_ready = '1' then + if endianess = 0 then + st.data((out_over_in + 1 - st.count) * input_width - 1 downto (out_over_in - st.count) * input_width) <= data_in; + else + st.data((st.count + 1) * input_width - 1 downto st.count * input_width) <= data_in; + end if; + end if; + if st.full_word = '1' and ready_in = '1' then + st.full_word <= '0'; + end if; + if st.count = out_over_in and valid_in = '1' then + st.full_word <= '1'; + st.count <= 0; + elsif valid_in = '1' then + st.count <= st.count + 1; + end if; + end if; +end process seq_proc; + +end architecture rtl; diff --git a/src/fifo_buffer/fifo_serializer.vhd b/src/fifo_buffer/fifo_serializer.vhd new file mode 100644 index 0000000..be860d3 --- /dev/null +++ b/src/fifo_buffer/fifo_serializer.vhd @@ -0,0 +1,76 @@ +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.MATH_REAL.all; +use ieee.numeric_std.all; + +entity fifo_serializer is + generic ( + output_width : natural := 8; + input_width : natural := 8; + endianess : integer := 0 -- 0: little endian, 1: big endian + ); + port ( + rst, clk : in std_logic; + ready_in : in std_logic; + ready_out : out std_logic; + valid_in : in std_logic; + valid_out : out std_logic; + data_in : in std_logic_vector(input_width - 1 downto 0); + data_out : out std_logic_vector(output_width - 1 downto 0) + ); +end entity fifo_serializer; + +architecture rtl of fifo_serializer is + +constant in_over_out : natural := input_width / output_width - 1; +type state_t is record + count : integer; + valid : std_logic; + data : std_logic_vector(input_width - 1 downto 0); +end record state_t; +signal st : state_t; +begin + +comb_proc: process(rst,clk,valid_in,ready_in,data_in,st) +begin + if st.valid = '0' and valid_in = '0' then + ready_out <= '1'; + else + ready_out <= '0'; + end if; + valid_out <= st.valid; + if st.count <= in_over_out and st.valid = '1' then + if endianess = 0 then + data_out <= st.data((input_width - st.count * output_width) - 1 downto input_width - (st.count + 1) * output_width); + else + data_out <= st.data((st.count + 1) * output_width - 1 downto st.count * output_width); + end if; + else + data_out <= (others => '0'); + end if; +end process comb_proc; + +seq_proc: process(clk, rst) +begin + if rst = '1' then + st.count <= 0; + st.valid <= '0'; + st.data <= (others => '0'); + elsif (rising_edge(clk)) then + if valid_in = '1' and st.count = 0 then + st.valid <= '1'; + st.data <= data_in; + elsif valid_in = '1' and st.count = in_over_out and ready_in = '1' then + st.count <= 0; + st.valid <= '1'; + st.data <= data_in; + elsif st.count = in_over_out and ready_in = '1' then + st.valid <= '0'; + st.count <= 0; + elsif ready_in = '1' and st.valid = '1' then + st.count <= st.count + 1; + end if; + end if; +end process seq_proc; + +end architecture rtl; diff --git a/src/ganimede/ganimede.vhd b/src/ganimede/ganimede.vhd index ee9318f..1ea4ba4 100644 --- a/src/ganimede/ganimede.vhd +++ b/src/ganimede/ganimede.vhd @@ -30,6 +30,7 @@ architecture rtl of ganimede_toplevel is signal socbridge_driver_to_buffer : fifo_interface_t; signal buffer_to_socbridge_driver : fifo_interface_t; signal socbridge_clk : std_logic; + signal used_slots : integer; --signal gan_socbridge_WE_in : std_logic; --signal gan_socbridge_WE_out : std_logic; @@ -52,7 +53,8 @@ begin ext_to_socbridge_driver => ext_to_ganimede.socbridge, socbridge_driver_to_ext => ganimede_to_ext.socbridge, ip_to_socbridge_driver => buffer_to_socbridge_driver, - socbridge_driver_to_ip => socbridge_driver_to_buffer + socbridge_driver_to_ip => socbridge_driver_to_buffer, + used_slots => used_slots ); controller_inst: entity gan_controller.control_unit @@ -77,7 +79,7 @@ begin fifo_buffer_to_ip_inst : entity gan_buffer.fifo_buffer generic map ( - buffer_size => 1024 + buffer_size => 2*1024 ) port map( in_clk => socbridge_clk, @@ -93,7 +95,7 @@ begin fifo_buffer_from_ip_inst : entity gan_buffer.fifo_buffer generic map ( - buffer_size => 1024 + buffer_size => 2*1024 ) port map( in_clk => clk, @@ -104,7 +106,8 @@ begin valid_in => ip_to_ganimede.socbridge.valid, valid_out => buffer_to_socbridge_driver.valid, data_in => ip_to_ganimede.socbridge.data, - data_out => buffer_to_socbridge_driver.data + data_out => buffer_to_socbridge_driver.data, + used_slots => used_slots ); --- LATER WE ADD OPTIMIZATIONS HERE --- diff --git a/src/manager/management_unit.vhd b/src/manager/management_unit.vhd index cd4cac4..f83e407 100644 --- a/src/manager/management_unit.vhd +++ b/src/manager/management_unit.vhd @@ -45,7 +45,7 @@ begin read_address <= manager_state.memory(0); write_address <= manager_state.memory(1); -comb_proc: process(controller_to_manager, socbridge_driver_to_manager,manager_state) +comb_proc: process(controller_to_manager, socbridge_driver_to_manager,manager_state, cmd) variable local_word_address : natural; begin local_word_address := to_integer(shift_right(unsigned(socbridge_driver_to_manager.address), address_shift)) mod mem_words; @@ -91,7 +91,7 @@ begin 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; + manager_to_controller.seq_mem_access_count <= 2**to_integer(unsigned(write_address.size)) * 2**10; cmd <= "01"; else -- No instruction present in memory, all zeroes to control unit diff --git a/src/socbridge/socbridge_driver.vhd b/src/socbridge/socbridge_driver.vhd index 88c9c66..e4ac8fa 100644 --- a/src/socbridge/socbridge_driver.vhd +++ b/src/socbridge/socbridge_driver.vhd @@ -11,7 +11,7 @@ use gan_manager.management_types.all; entity socbridge_driver is generic( - MAX_PKT_SIZE : integer range 1 to 128 := 32 + MAX_PKT_SIZE : integer range 1 to 128 := 8 ); port( clk : in std_logic; @@ -24,7 +24,8 @@ entity socbridge_driver is 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 + socbridge_driver_to_ip : out socbridge_driver_to_ip_t; + used_slots : in integer ); end entity socbridge_driver; @@ -55,7 +56,7 @@ 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, - valid_out) + valid_out, used_slots) variable curr_response_bits : std_logic_vector(4 downto 0); variable local_next_rx_transaction : transaction_t; variable local_next_tx_transaction : transaction_t; @@ -226,10 +227,17 @@ begin 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 + if st.curr_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 and ip_to_socbridge_driver.valid = '1' then local_next_data_out := ip_to_socbridge_driver.data; + else + local_next_data_out := (others => '0'); end if; when TX_R_BODY => if st.tx_stage > 0 then @@ -244,6 +252,9 @@ begin local_next_data_out := st.curr_tx_addr(15 downto 8); when ADDR4 => local_next_data_out := st.curr_tx_addr(7 downto 0); + if st.curr_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'; @@ -294,7 +305,7 @@ begin when AWAIT => 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 + elsif st.curr_tx_state = IDLE and not (trans_st.curr_inst.instruction = WRITE and used_slots < MAX_PKT_SIZE)then trans_next_state <= SEND; else trans_next_state <= AWAIT; @@ -479,8 +490,12 @@ begin end if; trans_st.is_first_word <= '1'; when SEND => + if trans_st.curr_inst.seq_mem_access_count mod 256 = 0 then + trans_st.is_first_word <= '1'; + end if; when SEND_ACCEPTED => trans_st.curr_inst.seq_mem_access_count <= trans_st.curr_inst.seq_mem_access_count - MAX_PKT_SIZE; + trans_st.curr_inst.address <= std_logic_vector(unsigned(trans_st.curr_inst.address) + MAX_PKT_SIZE); when AWAIT => if trans_st.curr_inst.seq_mem_access_count <= 0 and st.curr_tx_state = IDLE then trans_st.curr_inst.request <= '0'; @@ -489,6 +504,9 @@ begin trans_st.curr_inst.instruction <= NO_OP; end if; trans_st.is_first_word <= '0'; + if trans_st.curr_inst.seq_mem_access_count mod 256 = 0 then + trans_st.is_first_word <= '1'; + end if; when others => end case; end if;