library ieee; use ieee.std_logic_1164.all; use IEEE.STD_LOGIC_ARITH.all; use ieee.STD_LOGIC_UNSIGNED.all; library FACT_FAD_lib; use FACT_FAD_lib.fad_definitions.all; -- library UNISIM; -- use UNISIM.VComponents.all; -- USE IEEE.NUMERIC_STD.all; -- RAM_ADDR_WIDTH_64B is used for -- output ram_start_addr -- RAM_ADDR_WIDTH_16B is used for -- output wiz_ram_start_addr ENTITY memory_manager_2 IS generic( RAM_ADDR_WIDTH_64B : integer := 12; RAM_ADDR_WIDTH_16B : integer := 14 ); PORT( state : OUT std_logic_vector (3 DOWNTO 0); -- state is encoded here ... useful for debugging. clk : IN std_logic; -- CONFIG handshake: config_start : IN std_logic; config_ready : OUT std_logic := '1'; -- output of CONFIG states roi_array : IN roi_array_type; roi_max : OUT roi_max_type := (others => conv_std_logic_vector (0, 11)); package_length : OUT std_logic_vector (15 downto 0) := (others => '0'); wiz_number_of_channels : OUT std_logic_vector (3 downto 0) := (others => '0'); -- interface to DG: dg_start_config : OUT std_logic := '0'; dg_config_done : IN std_logic; ram_write_ready : IN std_logic; ram_write_ea : OUT std_logic := '0'; ram_start_addr : OUT std_logic_vector (RAM_ADDR_WIDTH_64B-1 DOWNTO 0) := (others => '0'); -- interface to W5300: wiz_read_done : IN std_logic; wiz_write_ea : OUT std_logic := '0'; wiz_write_length : OUT std_logic_vector (16 downto 0) := (others => '0'); wiz_ram_start_addr : OUT std_logic_vector (RAM_ADDR_WIDTH_16B-1 downto 0) := (others => '0'); wiz_write_header : OUT std_logic := '0'; wiz_write_end : OUT std_logic := '0'; data_ram_empty : out std_logic -- stupid signal, I need to get rid of it. DN 23.05.2011 ); -- Declarations END memory_manager_2 ; -- ARCHITECTURE beha OF memory_manager_2 IS type state_mm_type is ( MM_CONFIG, MAX_ROI, MAX_ROI1, MAX_ROI2, FIFO_CALC, RAM_CALC, RAM_CALC1, RAM_CALC2, CONFIG_DG, WAIT_FOR_CONFIG_DG, MM_MAIN, WRITE_FIN, READ_FIN, UPDATE_OUTPUT, UPDATE_OUTPUT_2); signal state_mm : state_mm_type := MM_CONFIG; --type roi_array_type is array (0 to 35) of integer range 0 to 1024; type roi_max_array_type is array (0 to 8) of integer range 0 to 1024; type channel_size_type is array (0 to 8) of integer range 0 to W5300_TX_FIFO_SIZE; type fifo_write_length_type is array (0 to 8) of integer range 0 to W5300_TX_FIFO_SIZE; type fifo_channels_array_type is array (0 to 8) of integer range 0 to 9; type fifo_package_size_ram_type is array (0 to 8) of integer range 0 to RAM_SIZE_16B; signal roi_max_array : roi_max_array_type := (others => 0); -- size of channel groups (16 bit) signal channel_size : channel_size_type := (others => 0); -- write length of packages (16 bit) signal fifo_write_length : fifo_write_length_type := (others => 0); -- number of channels per package signal fifo_channels_array : fifo_channels_array_type := (others => 0); -- size of packages in ram (16 bit) signal fifo_package_size_ram : fifo_package_size_ram_type := (others => 0); -- signal event_size_ram : integer range 0 to RAM_SIZE_16B := 0; signal event_size_ram_64b : integer range 0 to RAM_SIZE_64B := 0; signal event_size : integer range 0 to RAM_SIZE_16B := 0; signal drs_id : integer range 0 to 4 := 0; signal channel_id : integer range 0 to 9 := 0; signal channel_index : integer range 0 to 9 := 0; signal package_index : integer range 0 to 9 := 0; signal number_of_packages : integer range 0 to 9 := 0; signal max_events_ram : integer range 0 to 2048; signal events_in_ram : integer range 0 to 2048; signal event_start_addr : integer range 0 to (RAM_SIZE_64B - 1); signal write_start_addr : integer range 0 to (RAM_SIZE_16B - 1); signal roi_index : integer range 0 to 45 := 0; signal temp_roi : integer range 0 to 1024 := 0; -- SYNCH IN INPUT SIGNALS ----------------------------------------- signal config_start_sr : std_logic_vector(1 downto 0) := "00"; signal ram_write_ready_sr : std_logic_vector(1 downto 0) := "00"; signal wiz_read_ready_sr : std_logic_vector(1 downto 0) := "00"; signal dg_config_done_sr : std_logic_vector(1 downto 0) := "00"; -- no shift register, but local copy. signal roi_array_local : roi_array_type; signal state_sig : std_logic_vector( 3 downto 0 ) := "0000"; BEGIN state <= state_sig; data_ram_empty <= '1' when events_in_ram = 0 else '0'; mm : process (clk) begin if rising_edge (clk) then -- here: the synchin in of asynchronous input signals takes place. config_start_sr <= config_start_sr(0) & config_start; ram_write_ready_sr <= ram_write_ready_sr(0) & ram_write_ready; wiz_read_ready_sr <= wiz_read_ready_sr(0) & wiz_read_done; dg_config_done_sr <= dg_config_done_sr(0) & dg_config_done; roi_array_local <= roi_array; case state_mm is when MM_CONFIG => state_sig <= X"1"; config_ready <= '0'; roi_max_array <= (others => 0); channel_size <= (others => 0); fifo_write_length <= (others => 0); fifo_channels_array <= (others => 0); event_size <= 0; ram_write_ea <= '0'; wiz_write_ea <= '0'; state_mm <= MAX_ROI; -- calculate max ROIs and channel sizes when MAX_ROI => state_sig <= X"2"; roi_index <= (drs_id * 9) + channel_id; state_mm <= MAX_ROI1; when MAX_ROI1 => state_sig <= X"3"; temp_roi <= roi_array_local (roi_index); state_mm <= MAX_ROI2; when MAX_ROI2 => state_sig <= X"4"; if (channel_id < 9) then if ( temp_roi > roi_max_array (channel_id)) then roi_max_array (channel_id) <= temp_roi; end if; channel_size (channel_id) <= channel_size (channel_id) + temp_roi + CHANNEL_HEADER_SIZE; drs_id <= drs_id + 1; state_mm <= MAX_ROI; if (drs_id = 3) then drs_id <= 0; channel_id <= channel_id + 1; end if; else drs_id <= 0; channel_id <= 0; channel_size (0) <= channel_size (0) + PACKAGE_HEADER_LENGTH; channel_size (8) <= channel_size (8) + PACKAGE_END_LENGTH; state_mm <= FIFO_CALC; end if; -- calculate number of channels that fit in FIFO when FIFO_CALC => state_sig <= X"5"; if (channel_id < 9) then if ((fifo_write_length (package_index) + channel_size (channel_id)) <= W5300_TX_FIFO_SIZE) then fifo_write_length (package_index) <= fifo_write_length (package_index) + channel_size (channel_id); fifo_channels_array (package_index) <= fifo_channels_array (package_index) + 1; channel_id <= channel_id + 1; event_size <= event_size + channel_size (channel_id); else package_index <= package_index + 1; end if; else number_of_packages <= package_index + 1; package_index <= 0; channel_index <= 0; channel_id <= 0; fifo_package_size_ram <= (others => 0); fifo_package_size_ram (0) <= PACKAGE_HEADER_LENGTH + PACKAGE_HEADER_ZEROS; event_size_ram <= 0; event_size_ram_64b <= 0; max_events_ram <= 0; state_mm <= RAM_CALC; end if; when RAM_CALC => state_sig <= X"6"; if (package_index < number_of_packages) then if (channel_index < fifo_channels_array (package_index)) then fifo_package_size_ram (package_index) <= fifo_package_size_ram (package_index) + ((roi_max_array (channel_id) + CHANNEL_HEADER_SIZE) * NUMBER_OF_DRS); channel_index <= channel_index + 1; channel_id <= channel_id + 1; else package_index <= package_index + 1; event_size_ram <= event_size_ram + fifo_package_size_ram (package_index); channel_index <= 0; end if; else fifo_package_size_ram (package_index - 1) <= fifo_package_size_ram (package_index - 1) + PACKAGE_END_LENGTH + PACKAGE_END_ZEROS; event_size_ram <= event_size_ram + PACKAGE_END_LENGTH + PACKAGE_END_ZEROS; state_mm <= RAM_CALC1; end if; when RAM_CALC1 => state_sig <= X"7"; max_events_ram <= max_events_ram + 1; if ((max_events_ram * event_size_ram) <= RAM_SIZE_16B) then state_mm <= RAM_CALC1; else max_events_ram <= max_events_ram - 1; state_mm <= RAM_CALC2; end if; when RAM_CALC2 => state_sig <= X"8"; event_size_ram_64b <= (event_size_ram / 4); events_in_ram <= 0; event_start_addr <= 0; write_start_addr <= 0; package_index <= 0; channel_id <= 0; ram_start_addr <= (others => '0'); package_length <= conv_std_logic_vector (event_size, 16); for i in 0 to 8 loop roi_max(i) <= conv_std_logic_vector(roi_max_array(i), 11); end loop; state_mm <= CONFIG_DG; when CONFIG_DG => state_sig <= X"9"; dg_start_config <= '1'; state_mm <= CONFIG_DG; if (dg_config_done_sr(1) = '0') then dg_start_config <= '0'; state_mm <= WAIT_FOR_CONFIG_DG; end if; when WAIT_FOR_CONFIG_DG => state_sig <= X"E"; state_mm <= WAIT_FOR_CONFIG_DG; if (dg_config_done_sr(1) = '1') then state_mm <= UPDATE_OUTPUT; end if; when MM_MAIN => state_sig <= X"A"; state_mm <= MM_MAIN; config_ready <= '1'; if (config_start_sr(1) = '1') then state_mm <= MM_CONFIG; elsif (ram_write_ready_sr(1) = '1') then -- this is part of the DG - MM handshake. -- pulling write_ea low shows that MM understood DG is ready ram_write_ea <= '0'; events_in_ram <= events_in_ram + 1; if ((event_start_addr + event_size_ram_64b) < (RAM_SIZE_64B - event_size_ram_64b)) then event_start_addr <= event_start_addr + event_size_ram_64b; else event_start_addr <= 0; end if; state_mm <= WRITE_FIN; elsif (wiz_read_ready_sr(1) = '1') then wiz_write_ea <= '0'; if (package_index = (number_of_packages - 1)) then -- next address if ((write_start_addr + fifo_package_size_ram (package_index)) < (RAM_SIZE_16B - event_size_ram)) then write_start_addr <= write_start_addr + fifo_package_size_ram (package_index); else write_start_addr <= 0; end if; else write_start_addr <= write_start_addr + fifo_package_size_ram (package_index); end if; -- increase pack_index -- the package_index goes from 0..NumOfPack-1 if ( package_index < (number_of_packages - 1)) then package_index <= package_index + 1; else package_index <= 0; events_in_ram <= events_in_ram - 1; end if; state_mm <= READ_FIN; end if; ------------------------- WRITING to MEM was finished ------------------------------------ ------------------------------------------------------------------------------------------ when WRITE_FIN => state_sig <= X"B"; ram_start_addr <= conv_std_logic_vector(event_start_addr, RAM_ADDR_WIDTH_64B); -- 2nd part of hand shake is, that DG pulls low ram_write_ready if (ram_write_ready_sr(1) = '0') then state_mm <= UPDATE_OUTPUT; end if; ------------------------- READING from MEM was finished ---------------------------------- ------------------------------------------------------------------------------------------ when READ_FIN => state_sig <= X"C"; if (wiz_read_ready_sr(1) = '0') then state_mm <= UPDATE_OUTPUT; end if; when UPDATE_OUTPUT => wiz_ram_start_addr <= conv_std_logic_vector(write_start_addr, RAM_ADDR_WIDTH_16B); wiz_write_length <= conv_std_logic_vector(fifo_write_length (package_index), 17); wiz_number_of_channels <= conv_std_logic_vector(fifo_channels_array (package_index), 4); if (package_index = 0) then -- first package -> write header wiz_write_header <= '1'; else wiz_write_header <= '0'; end if; if (package_index = (number_of_packages - 1)) then -- last package -> write end-flag wiz_write_end <= '1'; else wiz_write_end <= '0'; end if; state_mm <= UPDATE_OUTPUT_2; when UPDATE_OUTPUT_2 => state_sig <= X"D"; state_mm <= MM_MAIN; if (events_in_ram > 0) then wiz_write_ea <= '1'; else wiz_write_ea <= '0'; end if; if (events_in_ram < max_events_ram) then ram_write_ea <= '1'; else ram_write_ea <= '0'; end if; when others => state_sig <= X"F"; state_mm <= MM_CONFIG; end case; -- state_mm end if; end process mm; END ARCHITECTURE beha;