---------------------------------------------------------------------------------- -- Company: -- Engineer: -- -- Create Date: 11:48:48 11/10/2009 -- Design Name: -- Module Name: w5300_modul - Behavioral -- Project Name: -- Target Devices: -- Tool versions: -- Description: -- -- Dependencies: -- -- Revision: -- Revision 0.01 - File Created -- Additional Comments: -- ---------------------------------------------------------------------------------- LIBRARY IEEE; USE IEEE.STD_LOGIC_1164.all; USE IEEE.STD_LOGIC_ARITH.all; USE IEEE.STD_LOGIC_UNSIGNED.all; library ftm_definitions; USE ftm_definitions.ftm_array_types.all; USE ftm_definitions.ftm_constants.all; -- Uncomment the following library declaration if instantiating -- any Xilinx primitives in this code. library UNISIM; use UNISIM.VComponents.all; ENTITY w5300_modul IS PORT( clk : IN std_logic; wiz_reset : OUT std_logic := '1'; addr : OUT std_logic_vector (9 DOWNTO 0); data : INOUT std_logic_vector (15 DOWNTO 0); cs : OUT std_logic := '1'; wr : OUT std_logic := '1'; led : OUT std_logic_vector (7 DOWNTO 0) := (others => '0'); rd : OUT std_logic := '1'; int : IN std_logic; busy : OUT std_logic := '1'; new_config : OUT std_logic := '0'; config_started : IN std_logic; config_started_ack : OUT std_logic := '0'; -- ping_ftu_start : OUT std_logic := '0'; ping_ftu_started : IN std_logic; ping_ftu_ready : IN std_logic; -- sd_addr : OUT std_logic_vector (11 DOWNTO 0); sd_data_out : OUT std_logic_vector (15 DOWNTO 0) := (others => '0'); sd_data_in : IN std_logic_vector (15 DOWNTO 0); sd_write : OUT std_logic := '0'; sd_read : OUT std_logic := '0'; sd_started : IN std_logic; sd_ready : IN std_logic; sd_busy : IN std_logic; -- dd_block_start : OUT std_logic := '0'; dd_block_start_ack : IN std_logic; dd_block_ready : OUT std_logic := '1'; dd_send : IN std_logic; dd_send_ack : OUT std_logic := '1'; dd_send_ready : OUT std_logic := '1'; dd_addr : OUT std_logic_vector (11 DOWNTO 0); dd_data_in : IN std_logic_vector (15 DOWNTO 0); dd_read : OUT std_logic := '0'; dd_started : IN std_logic; dd_ready : IN std_logic; dd_busy : IN std_logic; dd_write_general : OUT std_logic := '0'; dd_write_general_started : IN std_logic; dd_write_general_ready : IN std_logic; -- fl_addr : OUT std_logic_vector (11 DOWNTO 0); fl_data_in : IN std_logic_vector (15 DOWNTO 0); fl_read : OUT std_logic := '0'; fl_started : IN std_logic; fl_ready : IN std_logic; fl_busy : IN std_logic; -- ftu_error_send : IN std_logic; ftu_error_send_ack : OUT std_logic := '1'; ftu_error_send_ready : OUT std_logic := '1'; ftu_error_calls : IN std_logic_vector (15 DOWNTO 0); ftu_error_data : IN std_logic_vector (223 DOWNTO 0); -- (28 * 8) - 1 -- get_header : OUT std_logic := '0'; get_header_started : IN std_logic; get_header_ready : IN std_logic; header_board_id : IN std_logic_vector (63 DOWNTO 0); header_firmware_id : IN std_logic_vector (15 DOWNTO 0); header_trigger_counter : IN std_logic_vector (31 DOWNTO 0); header_timestamp_counter : IN std_logic_vector (47 DOWNTO 0); header_current_state : IN std_logic_vector (15 DOWNTO 0); -- start_run : OUT std_logic := '0'; start_run_ack : IN std_logic; start_run_param : OUT std_logic_vector (15 DOWNTO 0) := (others => '0'); start_run_num_events : OUT std_logic_vector (31 DOWNTO 0) := (others => '0'); stop_run : OUT std_logic := '0'; stop_run_ack : IN std_logic; crate_reset : OUT std_logic := '0'; crate_reset_ack : IN std_logic; crate_reset_param : OUT std_logic_vector (15 DOWNTO 0) := (others => '0'); new_config_ftu : OUT std_logic := '0'; new_config_ftu_ack : IN std_logic; new_config_ftu_param : OUT std_logic_vector (15 DOWNTO 0) := (others => '0') ); END w5300_modul ; architecture Behavioral of w5300_modul is type state_init_type is (INTERRUPT, RESET, WRITE_REG, READ_REG, WRITE_DATA, INIT, IM, MT, STX, STX1, STX2, STX3, SRX, SRX1, SRX2, SRX3, MAC, MAC1, MAC2, GW, GW1, SNM, SNM1, IP, IP1, TIMEOUT, RETRY, SI, SI0, SI1, SI2, SI3, SI4, SI5, SI6, ESTABLISH, EST1, CONFIG, MAIN, MAIN1, MAIN2, MAIN3, CHK_RECEIVED, SEND_FTU_ERROR, READ_DATA, WRITE_TO_SD_ADDR, READ_FTU_ERROR, READ_DD_BLOCK, READ_FROM_SD_ADDR, READ_FROM_DD_ADDR, READ_FROM_FL_ADDR, READ_FROM_HEADER_MODUL); type state_write_type is (WR_START, WR_LENGTH, WR_01, WR_02, WR_03, WR_04, WR_05, WR_06, WR_07, WR_08, WR_WRITE_START_DEL, WR_GET_HEADER, WR_GET_HEADER_WAIT, WR_SD_ADDR, WR_FIFO_DATA, WR_FIFO_DATA_01, WR_FIFO_HEADER, WR_FIFO_HEADER_01, WR_WRITE_END_DEL); type state_interrupt_1_type is (IR1_01, IR1_02, IR1_03, IR1_04); type state_interrupt_2_type is (IR2_01, IR2_02, IR2_03, IR2_04, IR2_05, IR2_06); type state_read_data_type is (RD_1, RD_2, RD_3, RD_4, RD_5, RD_CMD, RD_CMD_PARSE, RD_PING, RD_WRITE_SD_ADDR, RD_READ_SD_ADDR, RD_READ_SD_BLOCK, RD_WRITE_SD_BLOCK, RD_X_EVNTS,RD_END); type state_write_sd_type is (WRITE_SD_START, WRITE_SD_WAIT, WRITE_SD_END); type state_read_sd_type is (READ_SD_START, READ_SD_WAIT, READ_SD_END); type state_read_fl_type is (READ_FL_START, READ_FL_WAIT, READ_FL_END); type state_ping_type is (PING_START, PING_WAIT, PING_WRITE_LIST); type state_read_dd_type is (READ_DD_START, READ_DD_WAIT, READ_DD_END); type state_read_dd_block_type is (READ_DD_BLOCK_START, READ_DD_BLOCK_WRITE_GENERAL, READ_DD_BLOCK_WRITE, READ_DD_BLOCK_END, READ_DD_BLOCK_INTERN); type state_send_ftu_error_type is (SFE_START, SFE_END); type state_rd_x_evnts_type is (RD_X_01, RD_X_02, RD_X_03); signal RST_TIME : std_logic_vector(19 downto 0) := X"7A120"; signal par_addr : std_logic_vector (9 downto 0) := (others => '0'); signal par_data : std_logic_vector (15 downto 0) := (others => '0'); signal data_read : std_logic_vector (15 downto 0) := (others => '0'); signal state_init, next_state , next_state_tmp : state_init_type := RESET; signal read_addr_state : state_init_type := RESET; signal count : std_logic_vector (2 downto 0) := "000"; signal state_write : state_write_type := WR_START; signal state_interrupt_1 : state_interrupt_1_type := IR1_01; signal state_interrupt_2 : state_interrupt_2_type := IR2_01; signal state_read_data : state_read_data_type := RD_1; signal next_state_read_data : state_read_data_type := RD_CMD; signal state_write_sd : state_write_sd_type := WRITE_SD_START; signal state_read_sd : state_read_sd_type := READ_SD_START; signal state_read_fl : state_read_fl_type := READ_FL_START; signal state_ping : state_ping_type := PING_START; signal state_read_dd : state_read_dd_type := READ_DD_START; signal state_read_dd_block : state_read_dd_block_type := READ_DD_BLOCK_START; signal state_send_ftu_error : state_send_ftu_error_type := SFE_START; signal state_rd_x_evnts : state_rd_x_evnts_type := RD_X_01; signal interrupt_ignore : std_logic := '1'; signal int_flag : std_logic := '0'; signal zaehler : std_logic_vector (19 downto 0) := (others => '0'); signal data_cnt : integer := 0; signal header_cnt : std_logic_vector (7 DOWNTO 0) := X"00"; signal socket_cnt : std_logic_vector (2 downto 0) := "000"; signal socket_tx_free : std_logic_vector (31 downto 0) := (others => '0'); signal write_length_bytes : std_logic_vector (16 downto 0); signal socket_rx_received : std_logic_vector (31 downto 0) := (others => '0'); signal chk_recv_cntr : integer range 0 to 10000 := 0; signal next_packet_data_cnt : integer range 0 to 4095 := 0; signal rx_packets_cnt : std_logic_vector (15 downto 0) := X"0000"; signal new_config_flag : std_logic := '0'; signal local_write_length : std_logic_vector (16 downto 0); signal local_socket_nr : std_logic_vector (2 downto 0); type cmd_array_type is array (0 to 4) of std_logic_vector (15 downto 0); signal cmd_array : cmd_array_type; signal internal_cmd : std_logic := '0'; signal wait_for_data_flag : std_logic := '0'; signal autosend_flag : std_logic := '1'; -- -- -- signal led_int : std_logic_vector (7 downto 0) := X"00"; signal led_cnt : integer range 0 to 2**22 := 0; -- -- -- signal local_sd_addr : std_logic_vector (11 downto 0); signal local_sd_data : std_logic_vector (15 downto 0); signal data_package_type : std_logic_vector (15 downto 0) := X"0000"; signal data_package_length : std_logic_vector (15 downto 0) := X"0000"; begin --synthesis translate_off RST_TIME <= X"00120"; --synthesis translate_on w5300_init_proc : process (clk, int) begin if rising_edge (clk) then -- -- -- led <= led_int; -- -- -- -- Interrupt low if (int = '0') and (interrupt_ignore = '0') then case state_interrupt_1 is when IR1_01 => int_flag <= '1'; busy <= '1'; state_interrupt_1 <= IR1_02; when IR1_02 => state_interrupt_1 <= IR1_03; when IR1_03 => state_init <= INTERRUPT; socket_cnt <= "000"; zaehler <= X"00000"; count <= "000"; int_flag <= '0'; interrupt_ignore <= '1'; state_interrupt_1 <= IR1_04; when others => null; end case; end if; -- int = '0' if int_flag = '0' then case state_init is -- Interrupt when INTERRUPT => case state_interrupt_2 is when IR2_01 => par_addr <= W5300_IR; state_init <= READ_REG; next_state <= INTERRUPT; state_interrupt_2 <= IR2_02; when IR2_02 => if (data_read (conv_integer(socket_cnt)) = '1') then -- Sx Interrupt state_interrupt_2 <= IR2_03; else socket_cnt <= socket_cnt + 1; if (socket_cnt = W5300_LAST_SOCKET) then state_interrupt_2 <= IR2_06; else state_interrupt_2 <= IR2_02; end if; end if; when IR2_03 => par_addr <= W5300_S0_IR + socket_cnt * W5300_S_INC; -- Sx Interrupt Register state_init <= READ_REG; next_state <= INTERRUPT; state_interrupt_2 <= IR2_04; when IR2_04 => par_addr <= W5300_S0_IR + socket_cnt * W5300_S_INC; par_data <= data_read; -- clear Interrupts state_init <= WRITE_REG; next_state <= INTERRUPT; state_interrupt_2 <= IR2_05; when IR2_05 => par_addr <= W5300_S0_CR + socket_cnt * W5300_S_INC; par_data <= X"0010"; -- CLOSE state_init <= WRITE_REG; next_state <= INTERRUPT; socket_cnt <= socket_cnt + 1; if (socket_cnt = W5300_LAST_SOCKET) then state_interrupt_2 <= IR2_06; else state_interrupt_2 <= IR2_01; end if; when IR2_06 => state_interrupt_1 <= IR1_01; state_interrupt_2 <= IR2_01; socket_cnt <= "000"; state_init <= RESET; end case; -- reset W5300 when RESET => busy <= '1'; zaehler <= zaehler + 1; wiz_reset <= '0'; if (zaehler >= X"00064") then -- wait 2µs wiz_reset <= '1'; end if; if (zaehler = RST_TIME) then -- wait 10ms zaehler <= X"00000"; socket_cnt <= "000"; count <= "000"; interrupt_ignore <= '0'; rd <= '1'; wr <= '1'; cs <= '1'; -- reset states state_write <= WR_START; state_init <= INIT; state_read_data <= RD_1; next_state_read_data <= RD_CMD; state_write_sd <= WRITE_SD_START; state_read_sd <= READ_SD_START; state_read_fl <= READ_FL_START; state_ping <= PING_START; state_read_dd <= READ_DD_START; state_read_dd_block <= READ_DD_BLOCK_START; state_send_ftu_error <= SFE_START; -- reset output signals new_config <= '0'; config_started_ack <= '1'; ping_ftu_start <= '0'; sd_write <= '0'; sd_read <= '0'; dd_block_start <= '0'; dd_block_ready <= '1'; dd_send_ack <= '1'; dd_send_ready <= '1'; dd_read <= '0'; dd_write_general <= '0'; fl_read <= '0'; ftu_error_send_ack <= '1'; ftu_error_send_ready <= '1'; -- start_run <= '0'; stop_run <= '0'; crate_reset <= '0'; new_config_ftu <= '0'; -- set internal signals new_config_flag <= '0'; chk_recv_cntr <= 0; next_packet_data_cnt <= 0; internal_cmd <= '0'; -- -- -- led_int <= X"00"; -- -- -- end if; -- Init when INIT => par_addr <= W5300_MR; par_data <= X"0000"; state_init <= WRITE_REG; next_state <= IM; -- Interrupt Mask when IM => par_addr <= W5300_IMR; par_data <= X"00FF"; -- S0-S7 Interrupts state_init <= WRITE_REG; next_state <= MT; -- Memory Type when MT => par_addr <= W5300_MTYPER; par_data <= X"00FF"; -- 64K RX, 64K TX-Buffer state_init <= WRITE_REG; next_state <= STX; -- Socket TX Memory Size when STX => par_data <= X"4000"; -- 64K TX for socket 0, others 0 par_addr <= W5300_TMS01R; state_init <= WRITE_REG; next_state <= STX1; when STX1 => par_data <= X"0000"; par_addr <= W5300_TMS23R; state_init <= WRITE_REG; next_state <= STX2; when STX2 => par_addr <= W5300_TMS45R; state_init <= WRITE_REG; next_state <= STX3; when STX3 => par_addr <= W5300_TMS67R; state_init <= WRITE_REG; next_state <= SRX; -- Socket RX Memory Size when SRX => par_data <= X"4000"; -- 64K RX for socket 0, others 0 par_addr <= W5300_RMS01R; state_init <= WRITE_REG; next_state <= SRX1; when SRX1 => par_data <= X"0000"; par_addr <= W5300_RMS23R; state_init <= WRITE_REG; next_state <= SRX2; when SRX2 => par_addr <= W5300_RMS45R; state_init <= WRITE_REG; next_state <= SRX3; when SRX3 => par_addr <= W5300_RMS67R; state_init <= WRITE_REG; next_state <= MAC; -- MAC when MAC => par_addr <= W5300_SHAR; par_data <= MAC_ADDRESS (0); state_init <= WRITE_REG; next_state <= MAC1; when MAC1 => par_addr <= W5300_SHAR + 2; par_data <= MAC_ADDRESS (1); state_init <= WRITE_REG; next_state <= MAC2; when MAC2 => par_addr <= W5300_SHAR + 4; par_data <= MAC_ADDRESS (2); state_init <= WRITE_REG; next_state <= GW; -- Gateway when GW => par_addr <= W5300_GAR; par_data (15 downto 8) <= conv_std_logic_vector(GATEWAY (0), 8); par_data (7 downto 0) <= conv_std_logic_vector(GATEWAY (1), 8); state_init <= WRITE_REG; next_state <= GW1; when GW1 => par_addr <= W5300_GAR + 2; par_data (15 downto 8) <= conv_std_logic_vector(GATEWAY (2), 8); par_data (7 downto 0) <= conv_std_logic_vector(GATEWAY (3), 8); state_init <= WRITE_REG; next_state <= SNM; -- Subnet Mask when SNM => par_addr <= W5300_SUBR; par_data (15 downto 8) <= conv_std_logic_vector(NETMASK (0), 8); par_data (7 downto 0) <= conv_std_logic_vector(NETMASK (1), 8); state_init <= WRITE_REG; next_state <= SNM1; when SNM1 => par_addr <= W5300_SUBR + 2; par_data (15 downto 8) <= conv_std_logic_vector(NETMASK (2), 8); par_data (7 downto 0) <= conv_std_logic_vector(NETMASK (3), 8); state_init <= WRITE_REG; next_state <= IP; -- Own IP-Address when IP => par_addr <= W5300_SIPR; par_data (15 downto 8) <= conv_std_logic_vector(IP_ADDRESS (0), 8); par_data (7 downto 0) <= conv_std_logic_vector(IP_ADDRESS (1), 8); state_init <= WRITE_REG; next_state <= IP1; when IP1 => par_addr <= W5300_SIPR + 2; par_data (15 downto 8) <= conv_std_logic_vector(IP_ADDRESS (2), 8); par_data (7 downto 0) <= conv_std_logic_vector(IP_ADDRESS (3), 8); state_init <= WRITE_REG; next_state <= SI; -- Socket Init when SI => par_addr <= W5300_S0_MR + socket_cnt * W5300_S_INC; par_data <= X"0101"; -- 0x0101: ALIGN, TCP state_init <= WRITE_REG; next_state <= SI0; -- keep alive when SI0 => par_addr <= W5300_S0_KPALVTR + socket_cnt * W5300_S_INC; par_data <= X"0C00"; -- 12 * 5s = 60s state_init <= WRITE_REG; next_state <= SI1; -- Sx Interrupt Mask when SI1 => par_addr <= W5300_S0_IMR + socket_cnt * W5300_S_INC; par_data <= X"000A"; -- TIMEOUT, DISCON state_init <= WRITE_REG; next_state <= SI2; when SI2 => par_addr <= W5300_S0_PORTR + socket_cnt * W5300_S_INC; par_data <= conv_std_logic_vector(FIRST_PORT + unsigned (socket_cnt), 16); state_init <= WRITE_REG; next_state <= SI3; when SI3 => par_addr <= W5300_S0_CR + socket_cnt * W5300_S_INC; par_data <= X"0001"; -- OPEN state_init <= WRITE_REG; next_state <= SI4; when SI4 => par_addr <= W5300_S0_SSR + socket_cnt * W5300_S_INC; state_init <= READ_REG; next_state <= SI5; when SI5 => if (data_read (7 downto 0) = X"13") then -- is open? state_init <= SI6; else state_init <= SI4; end if; when SI6 => par_addr <= W5300_S0_CR + socket_cnt * W5300_S_INC; par_data <= X"0002"; -- LISTEN state_init <= WRITE_REG; socket_cnt <= socket_cnt + 1; if (socket_cnt = W5300_LAST_SOCKET) then socket_cnt <= "000"; next_state <= ESTABLISH; -- All Sockets open else next_state <= SI; -- Next Socket end if; -- End Socket Init when ESTABLISH => par_addr <= W5300_S0_SSR + socket_cnt * W5300_S_INC; state_init <= READ_REG; next_state <= EST1; when EST1 => case data_read (7 downto 0) is when X"17" => -- established if (socket_cnt = W5300_LAST_SOCKET) then socket_cnt <= "000"; busy <= '0'; state_init <= MAIN; -- -- -- config_started_ack <= '0'; dd_block_ready <= '0'; dd_send_ack <= '0'; dd_send_ready <= '0'; ftu_error_send_ack <= '0'; ftu_error_send_ready <= '0'; led_int <= X"00"; wait_for_data_flag <= '0'; -- -- -- else socket_cnt <= socket_cnt + 1; state_init <= ESTABLISH; end if; when others => state_init <= ESTABLISH; -- -- -- -- Just for fun... if (led_cnt = 1100000) then if (led_int = X"00") then led_int <= X"18"; else led_int (7 downto 4) <= led_int (6 downto 4) & '0'; led_int (3 downto 0) <= '0' & led_int (3 downto 1); end if; led_cnt <= 0; else led_cnt <= led_cnt + 1; end if; -- -- -- end case; when CONFIG => new_config <= '1'; config_started_ack <= '0'; state_init <= MAIN; -- main "loop" when MAIN => if (config_started = '1') then new_config <= '0'; config_started_ack <= '1'; end if; chk_recv_cntr <= chk_recv_cntr + 1; if (chk_recv_cntr = 1000) then chk_recv_cntr <= 0; state_init <= READ_DATA; busy <= '1'; elsif ((dd_send = '1') and (wait_for_data_flag = '0')) then internal_cmd <= '1'; dd_send_ack <= '1'; dd_send_ready <= '0'; if (autosend_flag = '0') then state_read_dd_block <= READ_DD_BLOCK_END; end if; state_init <= READ_DD_BLOCK; elsif ((ftu_error_send = '1') and (wait_for_data_flag = '0')) then ftu_error_send_ack <= '1'; ftu_error_send_ready <= '0'; if (autosend_flag = '0') then state_send_ftu_error <= SFE_END; end if; state_init <= SEND_FTU_ERROR; end if; -- read dynamic data block and write it to ethernet when READ_DD_BLOCK => case state_read_dd_block is when READ_DD_BLOCK_START => dd_block_start <= '1'; dd_block_ready <= '0'; if (dd_block_start_ack = '1') then dd_block_start <= '0'; state_read_dd_block <= READ_DD_BLOCK_WRITE_GENERAL; end if; -- write on-time counter and tempertures to dd-block when READ_DD_BLOCK_WRITE_GENERAL => dd_write_general <= '1'; if (dd_write_general_started = '1') then dd_write_general <= '0'; state_read_dd_block <= READ_DD_BLOCK_WRITE; end if; -- write dd-block to ethernet when on-time counter and temperatures are ready when READ_DD_BLOCK_WRITE => if (dd_write_general_ready = '1') then data_package_type <= FTM_PACKAGE_TYPE_DD; data_package_length <= X"0" & (DD_BLOCK_SIZE + 1); -- +1 := package end read_addr_state <= READ_FROM_DD_ADDR; local_sd_addr <= X"000"; -- start at address 0x000 local_write_length <= "00000" & DD_BLOCK_SIZE; state_read_dd_block <= READ_DD_BLOCK_END; next_state <= READ_DD_BLOCK; state_init <= WRITE_DATA; end if; when READ_DD_BLOCK_END => dd_block_ready <= '1'; if (internal_cmd = '1') then state_read_dd_block <= READ_DD_BLOCK_INTERN; else next_state_read_data <= RD_CMD; state_read_dd_block <= READ_DD_BLOCK_START; state_init <= READ_DATA; state_read_data <= RD_5; end if; when READ_DD_BLOCK_INTERN => if (dd_send = '0') then dd_send_ready <= '1'; dd_send_ack <= '0'; internal_cmd <= '0'; state_read_dd_block <= READ_DD_BLOCK_START; state_init <= MAIN; end if; end case; -- state_read_dd_block -- send FTU error message when SEND_FTU_ERROR => case state_send_ftu_error is when SFE_START => next_state <= SEND_FTU_ERROR; data_package_type <= FTM_PACKAGE_TYPE_FTU_ERR; data_package_length <= X"0" & (FTU_ERROR_LENGTH + 1); -- +1 := package end read_addr_state <= READ_FTU_ERROR; local_sd_addr <= X"000"; local_write_length <= "00000" & FTU_ERROR_LENGTH; state_send_ftu_error <= SFE_END; state_init <= WRITE_DATA; when SFE_END => if (ftu_error_send = '0') then ftu_error_send_ack <= '0'; ftu_error_send_ready <= '1'; state_send_ftu_error <= SFE_START; state_init <= MAIN; end if; end case; -- read data from socket 0 when READ_DATA => case state_read_data is when RD_1 => par_addr <= W5300_S0_RX_RSR; state_init <= READ_REG; next_state <= READ_DATA; state_read_data <= RD_2; when RD_2 => socket_rx_received (31 downto 16) <= data_read; par_addr <= W5300_S0_RX_RSR + X"2"; state_init <= READ_REG; next_state <= READ_DATA; state_read_data <= RD_3; when RD_3 => socket_rx_received (15 downto 0) <= data_read; state_read_data <= RD_4; when RD_4 => if (socket_rx_received (16 downto 0) > ('0' & X"000")) then rx_packets_cnt <= socket_rx_received (16 downto 1); -- socket_rx_received / 2 state_read_data <= RD_5; else busy <= '0'; state_read_data <= RD_1; state_init <= MAIN; end if; when RD_5 => if (rx_packets_cnt > 0) then rx_packets_cnt <= rx_packets_cnt - '1'; par_addr <= W5300_S0_RX_FIFOR; state_init <= READ_REG; next_state <= READ_DATA; state_read_data <= next_state_read_data; else state_read_data <= RD_END; end if; when RD_END => state_read_data <= RD_1; if (new_config_flag = '1') then new_config_flag <= '0'; next_state <= CONFIG; else next_state <= MAIN; end if; par_addr <= W5300_S0_CR; par_data <= X"0040"; -- RECV state_init <= WRITE_REG; ------------------------- -- command handling ------------------------- -- read command (5 words) when RD_CMD => cmd_array (next_packet_data_cnt) <= data_read; next_packet_data_cnt <= next_packet_data_cnt + 1; -- look for command start if (next_packet_data_cnt = 0) then if (data_read /= CMD_START_DELIMITER) then next_packet_data_cnt <= 0; end if; end if; -- last command-word if (next_packet_data_cnt = 4) then next_packet_data_cnt <= 0; state_read_data <= RD_CMD_PARSE; else state_read_data <= RD_5; end if; -- process commands and parameters when RD_CMD_PARSE => case cmd_array (1) is when CMD_TLED => led_int <= NOT led_int; state_read_data <= RD_5; when CMD_START => case cmd_array (2) is -- start "normal" run when PAR_START_RUN => start_run <= '1'; start_run_param <= cmd_array (2); if (start_run_ack = '1') then start_run <= '0'; state_read_data <= RD_5; else state_init <= MAIN; end if; -- start run an take X events when PAR_START_X_EVNTS => next_state_read_data <= RD_X_EVNTS; wait_for_data_flag <= '1'; state_read_data <= RD_5; when others => state_read_data <= RD_5; end case; when CMD_STOP => stop_run <= '1'; if (stop_run_ack = '1') then stop_run <= '0'; state_read_data <= RD_5; else state_init <= MAIN; end if; when CMD_CRESET => crate_reset <= '1'; crate_reset_param <= cmd_array (2); -- led_int <= cmd_array (2) (7 downto 0); if (crate_reset_ack = '1') then crate_reset <= '0'; state_read_data <= RD_5; else state_init <= MAIN; end if; when CMD_CONFIG_FTU => new_config_ftu <= '1'; new_config_ftu_param <= cmd_array (2); -- led_int <= cmd_array (2) (7 downto 0); if (new_config_ftu_ack = '1') then new_config_ftu <= '0'; state_read_data <= RD_5; else state_init <= MAIN; end if; when CMD_WRITE => case cmd_array (2) is -- write to address in static data block when PAR_WRITE_SD_ADDR => wait_for_data_flag <= '1'; next_state_read_data <= RD_WRITE_SD_ADDR; state_read_data <= RD_5; -- write static data block when PAR_WRITE_SD => wait_for_data_flag <= '1'; next_state_read_data <= RD_WRITE_SD_BLOCK; state_read_data <= RD_5; when others => state_read_data <= RD_5; end case; -- cmd_array (2) when CMD_READ => case cmd_array (2) is -- read from address in static data block when PAR_READ_SD_ADDR => wait_for_data_flag <= '1'; next_state_read_data <= RD_READ_SD_ADDR; state_read_data <= RD_5; -- read static data block when PAR_READ_SD => state_read_data <= RD_READ_SD_BLOCK; -- read dynamic data block when PAR_READ_DD => state_init <= READ_DD_BLOCK; state_read_data <= RD_5; when others => state_read_data <= RD_5; end case; -- cmd_array (2) when CMD_PING => state_ping <= PING_START; state_read_data <= RD_PING; when CMD_AUTOSEND => state_read_data <= RD_5; case cmd_array (2) is when PAR_AUTOSEND_EA => autosend_flag <= '1'; when PAR_AUTOSEND_DA => autosend_flag <= '0'; when others => null; end case; when others => state_read_data <= RD_5; end case; -- cmd_array (1) -- ping all FTUs and write FTU-list to ethernet when RD_PING => case state_ping is when PING_START => ping_ftu_start <= '1'; if (ping_ftu_started = '1') then ping_ftu_start <= '0'; state_ping <= PING_WAIT; else state_init <= MAIN; end if; when PING_WAIT => if (ping_ftu_ready = '1') then state_ping <= PING_WRITE_LIST; else state_init <= MAIN; end if; when PING_WRITE_LIST => state_read_data <= RD_5; data_package_type <= FTM_PACKAGE_TYPE_FTU_LIST; data_package_length <= X"0" & (FL_BLOCK_SIZE + 1); -- +1 := package end read_addr_state <= READ_FROM_FL_ADDR; local_sd_addr <= X"000"; --start at address 0x000 local_write_length <= "00000" & FL_BLOCK_SIZE; next_state_read_data <= RD_CMD; next_state <= READ_DATA; state_init <= WRITE_DATA; end case; -- read static data block and write it to ethernet when RD_READ_SD_BLOCK => data_package_type <= FTM_PACKAGE_TYPE_SD; data_package_length <= X"0" & (SD_BLOCK_SIZE + 1); -- +1 := package end state_read_data <= RD_5; read_addr_state <= READ_FROM_SD_ADDR; local_sd_addr <= X"000"; -- start at address 0x000 local_write_length <= "00000" & SD_BLOCK_SIZE; next_state_read_data <= RD_CMD; next_state <= READ_DATA; state_init <= WRITE_DATA; -- read from address in static data ram and write data to ethernet when RD_READ_SD_ADDR => data_package_type <= FTM_PACKAGE_TYPE_SD_WORD; data_package_length <= X"0" & (SD_SINGLE_WORD_SIZE + 1); -- +1 := package end state_read_data <= RD_5; read_addr_state <= READ_FROM_SD_ADDR; local_sd_addr <= data_read (11 downto 0); local_write_length <= '0' & X"0001"; -- one word will be written to ethernet next_state_read_data <= RD_CMD; wait_for_data_flag <= '0'; next_state <= READ_DATA; state_init <= WRITE_DATA; -- read static data block from ethernet and write it to static data ram when RD_WRITE_SD_BLOCK => state_read_data <= RD_5; next_packet_data_cnt <= next_packet_data_cnt + 1; local_sd_addr <= conv_std_logic_vector (next_packet_data_cnt, 12); local_sd_data <= data_read; next_state <= READ_DATA; state_init <= WRITE_TO_SD_ADDR; -- last word if (next_packet_data_cnt = (SD_BLOCK_SIZE - 1)) then next_packet_data_cnt <= 0; wait_for_data_flag <= '0'; next_state_read_data <= RD_CMD; new_config_flag <= '1'; end if; -- write to address in static data ram when RD_WRITE_SD_ADDR => state_read_data <= RD_5; next_packet_data_cnt <= next_packet_data_cnt + 1; if (next_packet_data_cnt = 0) then local_sd_addr <= data_read (11 downto 0); else local_sd_data <= data_read; next_packet_data_cnt <= 0; wait_for_data_flag <= '0'; new_config_flag <= '1'; next_state_read_data <= RD_CMD; next_state <= READ_DATA; state_init <= WRITE_TO_SD_ADDR; end if; -- read X events when RD_X_EVNTS => case state_rd_x_evnts is when RD_X_01 => start_run_num_events (31 downto 16) <= data_read; state_read_data <= RD_5; state_rd_x_evnts <= RD_X_02; when RD_X_02 => start_run_num_events (15 downto 0) <= data_read; start_run_param <= cmd_array (2); start_run <= '1'; wait_for_data_flag <= '0'; state_rd_x_evnts <= RD_X_03; when RD_X_03 => if (start_run_ack = '1') then start_run <= '0'; state_rd_x_evnts <= RD_X_01; next_state_read_data <= RD_CMD; state_read_data <= RD_5; else state_init <= MAIN; end if; end case; end case; -- state_read_data -- read FTU errors when READ_FTU_ERROR => state_init <= next_state; if (data_cnt = 0) then local_sd_data <= ftu_error_calls; else local_sd_data <= X"00" & ftu_error_data (((data_cnt * 8) - 1) DOWNTO ((data_cnt * 8) - 8)); end if; -- read from header modul when READ_FROM_HEADER_MODUL => state_init <= next_state; case header_cnt is when X"00" => local_sd_data <= data_package_type; when X"01" => local_sd_data <= data_package_length; when X"02" => local_sd_data <= header_current_state; when X"03" => local_sd_data <= header_board_id (63 DOWNTO 48); when X"04" => local_sd_data <= header_board_id (47 DOWNTO 32); when X"05" => local_sd_data <= header_board_id (31 DOWNTO 16); when X"06" => local_sd_data <= header_board_id (15 DOWNTO 0); when X"07" => local_sd_data <= header_firmware_id; when X"08" => local_sd_data <= header_trigger_counter (31 DOWNTO 16); when X"09" => local_sd_data <= header_trigger_counter (15 DOWNTO 0); when X"0A" => local_sd_data <= X"0000"; when X"0B" => local_sd_data <= header_timestamp_counter (47 DOWNTO 32); when X"0C" => local_sd_data <= header_timestamp_counter (31 DOWNTO 16); when X"0D" => local_sd_data <= header_timestamp_counter (15 DOWNTO 0); when others => null; end case; -- read from ftu list ram when READ_FROM_FL_ADDR => case state_read_fl is when READ_FL_START => if (fl_busy = '0') then fl_addr <= local_sd_addr; fl_read <= '1'; state_read_fl <= READ_FL_WAIT; end if; when READ_FL_WAIT => if (fl_started = '1') then state_read_fl <= READ_FL_END; end if; when READ_FL_END => if (fl_ready = '1') then local_sd_data <= fl_data_in; fl_read <= '0'; state_read_fl <= READ_FL_START; state_init <= next_state; end if; end case; -- read from dynamic data block when READ_FROM_DD_ADDR => case state_read_dd is when READ_DD_START => if (dd_busy = '0') then dd_addr <= local_sd_addr; dd_read <= '1'; state_read_dd <= READ_DD_WAIT; end if; when READ_DD_WAIT => if (dd_started = '1') then state_read_dd <= READ_DD_END; end if; when READ_DD_END => if (dd_ready = '1') then local_sd_data <= dd_data_in; dd_read <= '0'; state_read_dd <= READ_DD_START; state_init <= next_state; end if; end case; -- read from static data block when READ_FROM_SD_ADDR => case state_read_sd is when READ_SD_START => if (sd_busy = '0') then sd_addr <= local_sd_addr; sd_read <= '1'; state_read_sd <= READ_SD_WAIT; end if; when READ_SD_WAIT => if (sd_started = '1') then state_read_sd <= READ_SD_END; end if; when READ_SD_END => if (sd_ready = '1') then local_sd_data <= sd_data_in; sd_read <= '0'; state_read_sd <= READ_SD_START; state_init <= next_state; end if; end case; -- write to static data block when WRITE_TO_SD_ADDR => case state_write_sd is when WRITE_SD_START => if (sd_busy = '0') then sd_addr <= local_sd_addr; sd_data_out <= local_sd_data; sd_write <= '1'; state_write_sd <= WRITE_SD_WAIT; end if; when WRITE_SD_WAIT => if (sd_started = '1') then sd_write <= '0'; state_write_sd <= WRITE_SD_END; end if; when WRITE_SD_END => if (sd_ready = '1') then state_write_sd <= WRITE_SD_START; state_init <= next_state; end if; end case; -- write to ethernet interface when WRITE_DATA => case state_write is when WR_START => state_write <= WR_LENGTH; when WR_LENGTH => local_socket_nr <= "000"; next_state_tmp <= next_state; -- Write Length: 2 := START and END of package write_length_bytes <= (2 + FTM_HEADER_LENGTH + local_write_length (15 downto 0)) & '0'; -- shift left (*2) data_cnt <= 0; header_cnt <= X"00"; state_write <= WR_01; -- Check FIFO Size when WR_01 => par_addr <= W5300_S0_TX_FSR + local_socket_nr * W5300_S_INC; state_init <= READ_REG; next_state <= WRITE_DATA; state_write <= WR_02; when WR_02 => socket_tx_free (31 downto 16) <= data_read; par_addr <= W5300_S0_TX_FSR + (local_socket_nr * W5300_S_INC) + X"2"; state_init <= READ_REG; next_state <= WRITE_DATA; state_write <= WR_03; when WR_03 => socket_tx_free (15 downto 0) <= data_read; state_write <= WR_04; when WR_04 => if (socket_tx_free (16 downto 0) < W5300_TX_FIFO_SIZE_8B) then state_write <= WR_01; else state_write <= WR_WRITE_START_DEL; end if; -- write package start delimiter when WR_WRITE_START_DEL => par_addr <= W5300_S0_TX_FIFOR + local_socket_nr * W5300_S_INC; par_data <= FTM_PACKAGE_START; state_init <= WRITE_REG; next_state <= WRITE_DATA; state_write <= WR_GET_HEADER; -- get header data when WR_GET_HEADER => get_header <= '1'; if (get_header_started = '1') then get_header <= '0'; state_write <= WR_GET_HEADER_WAIT; end if; when WR_GET_HEADER_WAIT => if (get_header_ready = '1') then state_write <= WR_FIFO_HEADER; end if; -- Fill FIFO -- write header when WR_FIFO_HEADER => state_init <= READ_FROM_HEADER_MODUL; next_state <= WRITE_DATA; state_write <= WR_FIFO_HEADER_01; when WR_FIFO_HEADER_01 => header_cnt <= header_cnt + 1; if (header_cnt < FTM_HEADER_LENGTH) then par_addr <= W5300_S0_TX_FIFOR + local_socket_nr * W5300_S_INC; par_data <= local_sd_data; state_init <= WRITE_REG; next_state <= WRITE_DATA; state_write <= WR_FIFO_HEADER; else if (data_package_type = FTM_PACKAGE_TYPE_SD_WORD) then state_write <= WR_SD_ADDR; else state_write <= WR_FIFO_DATA; end if; end if; -- write static data ram address (only for single address request) when WR_SD_ADDR => write_length_bytes <= write_length_bytes + 2; -- one extra word to write par_addr <= W5300_S0_TX_FIFOR + local_socket_nr * W5300_S_INC; par_data <= "0000" & local_sd_addr; state_init <= WRITE_REG; next_state <= WRITE_DATA; state_write <= WR_FIFO_DATA; -- write data when WR_FIFO_DATA => state_init <= read_addr_state; next_state <= WRITE_DATA; state_write <= WR_FIFO_DATA_01; when WR_FIFO_DATA_01 => data_cnt <= data_cnt + 1; if (data_cnt < local_write_length) then local_sd_addr <= local_sd_addr + 1; par_addr <= W5300_S0_TX_FIFOR + local_socket_nr * W5300_S_INC; par_data <= local_sd_data; state_init <= WRITE_REG; next_state <= WRITE_DATA; state_write <= WR_FIFO_DATA; else state_write <= WR_WRITE_END_DEL; end if; -- write package end delimiter when WR_WRITE_END_DEL => par_addr <= W5300_S0_TX_FIFOR + local_socket_nr * W5300_S_INC; par_data <= FTM_PACKAGE_END; state_init <= WRITE_REG; next_state <= WRITE_DATA; state_write <= WR_05; -- Send FIFO when WR_05 => par_addr <= W5300_S0_TX_WRSR + local_socket_nr * W5300_S_INC; par_data <= (0 => write_length_bytes (16), others => '0'); state_init <= WRITE_REG; state_write <= WR_06; when WR_06 => par_addr <= W5300_S0_TX_WRSR + (local_socket_nr * W5300_S_INC) + X"2"; par_data <= write_length_bytes (15 downto 0); state_init <= WRITE_REG; state_write <= WR_07; when WR_07 => par_addr <= W5300_S0_CR + local_socket_nr * W5300_S_INC; par_data <= X"0020"; -- Send state_init <= WRITE_REG; state_write <= WR_08; when others => state_init <= next_state_tmp; state_write <= WR_START; end case; -- End WRITE_DATA when READ_REG => case count is when "000" => cs <= '0'; rd <= '0'; wr <= '1'; data <= (others => 'Z'); -- !!!!!!!!!! count <= "001"; addr <= par_addr; when "001" => count <= "010"; when "010" => count <= "100"; when "100" => data_read <= data; count <= "110"; when "110" => count <= "111"; when "111" => cs <= '1'; rd <= '1'; count <= "000"; state_init <= next_state; when others => null; end case; when WRITE_REG => case count is when "000" => cs <= '0'; wr <= '0'; rd <= '1'; addr <= par_addr; data <= par_data; count <= "100"; when "100" => count <= "101"; when "101" => count <= "110"; when "110" => cs <= '1'; wr <= '1'; state_init <= next_state; count <= "000"; when others => null; end case; when others => null; end case; end if; -- int_flag = '0' end if; -- rising_edge (clk) end process w5300_init_proc; end Behavioral;