---------------------------------------------------------------------------------- -- 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 FACT_FAD_lib; use FACT_FAD_lib.fad_definitions.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; write_length : IN std_logic_vector (16 DOWNTO 0); ram_start_addr : IN std_logic_vector (13 DOWNTO 0); ram_data : IN std_logic_vector (15 DOWNTO 0); ram_addr : OUT std_logic_vector (13 DOWNTO 0); data_valid : IN std_logic; busy : OUT std_logic := '1'; write_header_flag, write_end_flag : IN std_logic; fifo_channels : IN std_logic_vector (3 downto 0); s_trigger : OUT std_logic := '0'; new_config : OUT std_logic := '0'; config_started : in std_logic; config_addr : out std_logic_vector (7 downto 0); config_data : inout std_logic_vector (15 downto 0) := (others => 'Z'); config_wr_en : out std_logic := '0'; config_rd_en : out std_logic := '0'; config_busy : in std_logic ); -- Declarations 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, SI, SI1, SI2, SI3, SI4, SI5, SI6, ESTABLISH, EST1, CONFIG, MAIN, CHK_RECEIVED, READ_DATA); type state_write_type is (WR_START, WR_LENGTH, WR_WAIT1, WR_01, WR_02, WR_03, WR_04, WR_05, WR_06, WR_07, WR_08, WR_FIFO, WR_FIFO1, WR_ADC, WR_ADC1, WR_ADC2, WR_ENDFLAG, WR_ENDFLAG1, WR_ENDFLAG2, WR_ENDFLAG3); 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_6, RD_WAIT, RD_WAIT1, RD_END); 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 adc_data_addr : std_logic_vector (13 DOWNTO 0); signal state_init, next_state , next_state_tmp : 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 interrupt_ignore : std_logic := '1'; signal int_flag : std_logic := '0'; signal ram_access : std_logic := '0'; signal zaehler : std_logic_vector (19 downto 0) := (OTHERS => '0'); signal data_cnt : integer := 0; signal drs_cnt : integer :=0; signal channel_cnt : integer range 0 to 9 :=0; signal socket_cnt : std_logic_vector (2 downto 0) := "000"; signal roi_max : std_logic_vector (10 downto 0); signal data_end : integer := 0; 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 rx_packets_cnt : std_logic_vector (15 downto 0); signal next_packet_data : std_logic := '0'; signal new_config_flag : std_logic := '0'; signal trigger_stop : std_logic := '1'; signal local_write_length : std_logic_vector (16 DOWNTO 0); signal local_ram_start_addr : std_logic_vector (13 DOWNTO 0); signal local_ram_addr : std_logic_vector (13 downto 0); signal local_socket_nr : std_logic_vector (2 DOWNTO 0); signal local_write_header_flag, local_write_end_flag : std_logic; signal local_fifo_channels : std_logic_vector (3 downto 0); begin --synthesis translate_off RST_TIME <= X"00120"; --synthesis translate_on w5300_init_proc : process (clk, int) begin if rising_edge (clk) then -- 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"; ram_access <= '0'; 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 = 7) 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 = 7) 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 => zaehler <= zaehler + 1; wiz_reset <= '0'; led <= X"FF"; 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"; ram_access <= '0'; interrupt_ignore <= '0'; rd <= '1'; wr <= '1'; cs <= '1'; state_write <= WR_START; state_init <= INIT; 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"7FFF"; -- 8K RX, 120K TX-Buffer state_init <= WRITE_REG; next_state <= STX; -- Socket TX Memory Size when STX => par_data <= X"0F0F"; -- 15K TX par_addr <= W5300_TMS01R; state_init <=WRITE_REG; next_state <= STX1; when STX1 => 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"0101"; -- 1K RX par_addr <= W5300_RMS01R; state_init <=WRITE_REG; next_state <= SRX1; when SRX1 => 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"; -- ALIGN, TCP 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 = 7) 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 => led <= data_read (7 downto 0); case data_read (7 downto 0) is when X"17" => -- established if (socket_cnt = 7) then socket_cnt <= "000"; busy <= '0'; state_init <= MAIN; else socket_cnt <= socket_cnt + 1; state_init <= ESTABLISH; end if; when others => state_init <= ESTABLISH; end case; when CONFIG => led <= X"F0"; new_config <= '1'; if (config_started = '1') then led <= X"0F"; new_config <= '0'; busy <= '0'; state_init <= MAIN; end if; -- main "loop" when MAIN => if (trigger_stop = '1') then s_trigger <= '0'; end if; if (chk_recv_cntr = 1000) then chk_recv_cntr <= 0; state_read_data <= RD_1; state_init <= READ_DATA; busy <= '1'; else chk_recv_cntr <= chk_recv_cntr + 1; if (data_valid = '1') then local_write_length <= write_length; local_ram_start_addr <= ram_start_addr; local_ram_addr <= (others => '0'); local_write_header_flag <= write_header_flag; local_write_end_flag <= write_end_flag; local_fifo_channels <= fifo_channels; next_state <= MAIN; state_init <= WRITE_DATA; busy <= '1'; end if; end if; -- 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_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 <= RD_6; else state_read_data <= RD_END; -- if (new_config_flag = '1') then -- new_config_flag <= '0'; -- state_init <= CONFIG; -- else -- busy <= '0'; -- state_init <= MAIN; -- end if; end if; when RD_6 => led <= data_read (15 downto 8); -- read command if (next_packet_data = '0') then case data_read (15 downto 8) is when CMD_TRIGGER => trigger_stop <= '1'; s_trigger <= '1'; state_read_data <= RD_WAIT; when CMD_TRIGGER_C => trigger_stop <= '0'; s_trigger <= '1'; state_read_data <= RD_WAIT; when CMD_TRIGGER_S => trigger_stop <= '1'; state_read_data <= RD_WAIT; when CMD_WRITE => next_packet_data <= '1'; config_addr <= data_read (7 downto 0); state_read_data <= RD_5; when others => state_read_data <= RD_5; end case; -- read data else if (config_busy = '0') then config_data <= data_read; config_wr_en <= '1'; new_config_flag <= '1'; next_packet_data <= '0'; state_read_data <= RD_WAIT; end if; end if; when RD_WAIT => state_read_data <= RD_WAIT1; when RD_WAIT1 => config_data <= (others => 'Z'); config_wr_en <= '0'; state_read_data <= RD_5; when RD_END => par_addr <= W5300_S0_CR; par_data <= X"0040"; -- RECV state_init <= WRITE_REG; if (new_config_flag = '1') then new_config_flag <= '0'; next_state <= CONFIG; else busy <= '0'; next_state <= MAIN; end if; end case; -- state_data_read when WRITE_DATA => case state_write is when WR_START => if (local_write_header_flag = '1') then ram_addr <= local_ram_start_addr + 5; -- Address of Trigger-ID (15 downto 0) ???? end if; state_write <= WR_WAIT1; when WR_WAIT1 => state_write <= WR_LENGTH; when WR_LENGTH => if (local_write_header_flag = '1') then local_socket_nr <= ram_data (2 downto 0); end if; next_state_tmp <= next_state; write_length_bytes <= local_write_length (15 downto 0) & '0'; -- shift left (*2) data_cnt <= 0; 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) < write_length_bytes) then state_write <= WR_01; else if (local_write_header_flag = '1') then state_write <= WR_FIFO; else state_write <= WR_ADC; end if; end if; -- Fill FIFO -- Write Header when WR_FIFO => ram_addr <= local_ram_start_addr + local_ram_addr; state_write <= WR_FIFO1; when WR_FIFO1 => data_cnt <= data_cnt + 1; if (data_cnt < PACKAGE_HEADER_LENGTH) then --??? local_ram_addr <= local_ram_addr + 1; if (data_cnt = 2 or data_cnt = 5 or data_cnt = 8 ) then -- skip empty words local_ram_addr <= local_ram_addr + 2; end if; if (data_cnt = 9) then -- skip empty words local_ram_addr <= local_ram_addr + 4; end if; par_addr <= W5300_S0_TX_FIFOR + local_socket_nr * W5300_S_INC; ram_access <= '1'; state_init <= WRITE_REG; next_state <= WRITE_DATA; state_write <= WR_FIFO; else state_write <= WR_ADC; end if; -- End Write Header -- Write ADC-Data ---- Start... when WR_ADC => adc_data_addr <= local_ram_start_addr + local_ram_addr; drs_cnt <= 0; channel_cnt <= 1; data_cnt <= 0; roi_max <= (others => '0'); data_end <= 3; state_write <= WR_ADC1; ---- Write Channel when WR_ADC1 => -- read ROI and set end of Channel-Data if (data_cnt = 3) then data_end <= conv_integer (ram_data) + 3; if (ram_data > roi_max) then roi_max <= ram_data (10 downto 0); end if; end if; ram_addr <= adc_data_addr + drs_cnt + (data_cnt * 4); state_write <= WR_ADC2; when WR_ADC2 => if (data_cnt < data_end) then par_addr <= W5300_S0_TX_FIFOR + local_socket_nr * W5300_S_INC; ram_access <= '1'; state_init <= WRITE_REG; next_state <= WRITE_DATA; data_cnt <= data_cnt + 1; state_write <= WR_ADC1; else -- Next DRS if (drs_cnt < 3) then drs_cnt <= drs_cnt + 1; data_cnt <= 0; data_end <= 3; state_write <= WR_ADC1; else -- Next Channel if (channel_cnt < local_fifo_channels) then channel_cnt <= channel_cnt + 1; roi_max <= (others => '0'); drs_cnt <= 0; data_cnt <= 0; data_end <= 3; adc_data_addr <= adc_data_addr + ((conv_integer(roi_max) + 3) * 4); state_write <= WR_ADC1; else -- Ready if (local_write_end_flag = '1') then state_write <= WR_ENDFLAG; else state_write <= WR_05; end if; end if; end if; end if; -- End Write ADC-Data -- Write End Package Flag when WR_ENDFLAG => ram_addr <= adc_data_addr + ((conv_integer(roi_max) + 3) * 4); state_write <= WR_ENDFLAG1; when WR_ENDFLAG1 => par_addr <= W5300_S0_TX_FIFOR + local_socket_nr * W5300_S_INC; ram_access <= '1'; state_init <= WRITE_REG; next_state <= WRITE_DATA; state_write <= WR_ENDFLAG2; when WR_ENDFLAG2 => ram_addr <= adc_data_addr + ((conv_integer(roi_max) + 3) * 4) + 1; state_write <= WR_ENDFLAG3; when WR_ENDFLAG3 => state_init <= WRITE_REG; next_state <= WRITE_DATA; state_write <= WR_05; -- End Write End Package Flag --Send FIFO when WR_05 => ram_access <= '0'; 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 => busy <= '0'; 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; if (ram_access = '1') then data <= ram_data; else data <= par_data; end if; 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;