Problem in reading W5300 registers with Spartan6

Hi! I am using W5300 module and initialing it on TCP mode with Spartan6(FPGA). I can open the socket in TCP mode, and I also can establish it. When I send data to it and read the RX_FIFOR, I just cant read the number of data has been received . I create a loop for buffering data, but I can not read them. What is the problem?

Hello

Did you have problem for establish.
Could you please let me know how to get establish?


please check if you follow this flow.

I don’t know how to implement on your FPGA to receive data.

W5300 normally saves data to the socket RX buffer.

Did you check read/write a regsiters of W5300?

Did you check IP address such as SIPR ?

Did you check the ping to W5300 with the configured SIPR?

I have no problem with establish mode. I go to listen mode and when I click the connect button in the terminal , it goes to establish mode and SSR shows 0x17. For buffering data I am reading RX_FIFOR but I just get number of data that has been received , but in the other sequences when I read that register there is no data.

Yes, I can get ping and I can also connect to the device properly. But I have problem in reading registers. I can just read RX_FIFOR once and when I read it again there is no data in it, while a packet has been received

Did you check the register Sn_RX_RSR value to indicate the received data size?

If possible, can you explain more your read processing logic?

You can refer the read process to ioLibrary (GitHub - Wiznet/ioLibrary_Driver: ioLibrary_Driver can be used for the application design of WIZnet TCP/IP chips as W5500, W5300, W5200, W5100 W5100S.).

Thank you.

My main problem is the reading process. I can not read registers after eachother. I can read on register once or two different registers after each other. I do check Sn_RX_RSR value and it shows the right value, but then I can not read RX_FIFOR. I can just read RX_FIFOR0 once without reading other registers before that.


Sorry, it is difficult to know the cause.
I want to know if you followed that.
Please check it.

Did you share the read process?

Most of all, you shouldn’t read another register while reading Sn_RX_FIFOR.

So, The reading Sn_RX_FIFOR should be protected from another reading register or interrupts.

Thank you.

Thanks for the reply! I do not use Sn_TX_FIFOR in my code at all. I just write in CR and read the result in Sn_SSR. When initializing, listening and establishing are done , I do the reading process of Sn_RX_FIFOR.
I should mention that I also have problem in reading Sn_SSR sequentially

I have a seperate code of reading process( a reading function). I use that for reading any register. First I read Sn_SSR for initializing , listening and establishing.Then I go to Sn_RX_FIFOR reading process.
I have problem in every step. I can just read just one of the registers not all of them sequentially.
.


Sorry I’m confused about Sn_RX_FIFOR and Sn_TX_FIFOR, but the same is true for Sn_RX_FIFOR .

Does it mean that I can not read Sn_RX_FIFOR0 and after a delay read Sn_RX_FIFOR1? Should I read them at the same time? Sorry I am confused :grimacing:

I means that
You should read Sn_RX_FIFOR0 and Sn_RX_FIFOR1 continuously.
While you read data as many as Sn_RX_RSR thru Sn_RX_FIFOR, You can not read another register of W5300 but, you can add some delay without timer interrupt caused to obstruct a continue Sn_RX_FIFOR reading.

For right example,

    for(i = 0;  i < len; i++)
    {
        read Sn_RX_FIFO0
        read Sn_RX_FIFO1
    }

For wrong example,

    for(i = 0;  i < len; i++)
    {
        read Sn_MR // read another register of W5300,  <-- it is wrong.
        read Sn_RX_FIFO0
        read Sn_RX_FIFO1
       for(j = 0;  j < 100; j++);     // you can add some delay by just polling
    }

Thank you.

WiznetReadWrite_Process : process(s_CLK_20M)
begin
if rising_edge(s_CLK_20M) then

		case s_Eth_RW_State is

			when c_Eth_RW_State_Idle =>
				o_Eth_CS 	<= '1';
				o_Eth_WR 	<= '1';
				o_Eth_RD 	<= '1';
				s_W_DATA_In_Des_Rdy <= '0';
				s_W_DATA_Out_Des_Done <= '0';
				if s_WriteTrig = '1' then
					s_W_RD_WRB 	<= '0';
					o_Eth_CS 	<= '0';
					s_W_ADDR		<= s_W_ADDR_Des;
					s_W_DATA_Out	<= s_W_DATA_Out_Des;
					s_Eth_RW_State <= c_Eth_RW_State_W1;
				elsif s_ReadTrig = '1' then
					s_W_RD_WRB 	<= '1';
					s_W_ADDR		<= s_W_ADDR_Des;
					o_Eth_RD 	<= '0';
					o_Eth_CS 	<= '0';
					s_Eth_RW_State <= c_Eth_RW_State_R1;
				end if;

			when c_Eth_RW_State_W1 =>	
				o_Eth_WR <= '0';
				s_W_DATA_Out_Des_Done <= '1';
				s_Eth_RW_State <= c_Eth_RW_State_Idle;
			


			when c_Eth_RW_State_R1 =>
				s_W_DATA_In_Des	<= s_W_DATA_In;	
				s_W_DATA_In_Des_Rdy <= '1';
				s_Eth_RW_State <=c_Eth_RW_State_Idle;

			when others =>
				s_Eth_RW_State <= c_Eth_RW_State_Idle;

		end case;

	end if;
end process;

This is my reading process

And here is a part of main process which I start initializing in TCP mode after setting all socket registers and IP, MAC , PORT , … :

			when 	c_Eth_Start_State =>

				s_W_ADDR_Des 		<= c_WIZNET_START_ADDR(s_Index);
				s_W_DATA_Out_Des	<= c_WIZNET_START_DATA(s_Index);
				s_WriteTrig <= '1';
				if s_Index < c_WIZNET_START_ADDR_LENGTH-1 then
					s_Eth_Config_State <= c_Eth_Start_State2;
				else
					s_Eth_Config_State <= c_Eth_START_State_End;
				end if;	
				s_Index <= s_Index + 1;

			when c_Eth_Start_State2 =>	
				if s_W_DATA_Out_Des_Done = '1' then
					s_Eth_Config_State <= c_Eth_START_State;
				end if;
			When c_Eth_START_State_End =>
					s_Index<=0;
					s_Eth_Config_State <= c_Eth_check1_State;
					
			when c_Eth_check1_State=>
					s_W_ADDR_Des 		<="10"&x"09"; --S0_SSR
					s_ReadTrig <= '1';
					if s_W_DATA_In_Des_Rdy='1' then
						mode<=s_W_DATA_In_Des;
				
						if mode=x"13" then
							s_Index <=0;
							s_LEDs<=x"00" & mode ;
							s_Eth_Config_State <=c_Eth_listen_State;
						else
							s_W_ADDR_Des 		<= c_WIZNET_START_ADDR(3); --CR1
							s_W_DATA_Out_Des	<= x"10"; --close
							s_WriteTrig <= '1';
							if s_W_DATA_Out_Des_Done = '1' then
								s_Index <=0;
								s_Eth_Config_State <=c_Eth_Start_State;
							end if;
						end if;
					end if;

					
			when c_Eth_listen_State =>
					s_W_ADDR_Des 	<= c_WIZNET_START_ADDR(3); --cr1
					s_W_DATA_Out_Des	<= x"02";
					s_WriteTrig <= '1';
					if s_W_DATA_Out_Des_Done='1' then
						s_Eth_Config_State <= c_Eth_delay_State;
					end if;
			when c_Eth_delay_State	=>
					counter<=counter+1;
					if (counter<4) then 
						s_Eth_Config_State <= c_Eth_delay_State;
					else 
						s_Eth_Config_State <= c_Eth_check_State;
					end if;
			When c_Eth_check_State =>
					s_W_ADDR_Des 		<="10" & x"09"; --S0_SSR
					s_ReadTrig <= '1';
					if s_W_DATA_In_Des_Rdy='1' then 
						listen<=s_W_DATA_In_Des;
						if listen=x"14" then
							s_LEDs<=x"ff" & listen ;
							s_Index <=1;
							s_Eth_Config_State <= c_Eth_establish_State;
						else
							s_W_ADDR_Des 		<= c_WIZNET_START_ADDR(3); --CR1
							s_W_DATA_Out_Des	<= x"10"; --close
							s_WriteTrig <= '1';
							if s_W_DATA_Out_Des_Done = '1' then
								s_Index <=0;
								s_Eth_Config_State <=c_Eth_Start_State;
							end if;
						end if;
					end if;
			when c_Eth_establish_State =>
					s_W_ADDR_Des 		<=c_WIZNET_START_ADDR(4); --S0_SSR
					s_ReadTrig <= '1';
					if s_W_DATA_In_Des_Rdy='1' then
						establish<=s_W_DATA_In_Des;
						if establish=x"17" then
							s_Index <=0;
							s_Eth_Config_State <= c_Eth_Receive_Process_State;
						else
							s_Index <=0;
							s_Eth_Config_State <=c_Eth_establish_State;

						end if;
					end if;

			when c_Eth_Receive_Process_State =>
					
					s_W_ADDR_Des <= c_WIZNET_RXPACK_ADDR(1); --S0_RSR
					s_ReadTrig <= '1';
					s_Index<= s_Index+1;
					if s_W_DATA_In_Des_Rdy='1' then
						if (s_Index<c_WIZNET_RX_ADDR_LENGTH) then
							rsr<=s_W_DATA_In_Des;
							s_Eth_Config_State <=c_Eth_delay4_State;
						else 
							s_Index<=0;
							s_Eth_Config_State <=c_Eth_Receive_Process_State;
						end if;
					end if;
					
			when c_Eth_delay4_State	=>
					counter<=counter+1;
					if (counter<4) then 
						s_Eth_Config_State <= c_Eth_delay4_State;
					else 
						s_Eth_Config_State <=c_Eth_cheksize_State;
					end if;
					
			when c_Eth_cheksize_State =>
					rsr<=s_W_DATA_In_Des;
					if(rsr/=x"00") then
						s_Eth_Config_State <=c_Eth_receive1_State;
					else 
					
						s_Eth_Config_State <=c_Eth_Receive_Process_State;	
					end if;
			when c_Eth_receive1_State =>
					s_W_ADDR_Des <= "10" & x"30";
					s_ReadTrig <= '1';
					if s_W_DATA_In_Des_Rdy='1' then
						data1<=s_W_DATA_In_Des;
						buff(step1)<=data;
						s_Eth_Config_State <=c_Eth_receive2_State;
					end if;
			when c_Eth_receive2_State =>
					s_W_ADDR_Des <= "10" & x"31";
					s_ReadTrig <= '1';
					if s_W_DATA_In_Des_Rdy='1' then
						data2<=s_W_DATA_In_Des;
						buff(step2)<=data;
						s_Eth_Config_State <=c_Eth_Receive_Data_State;
					end if;
			when c_Eth_Receive_Data_State =>
					s_LEDs<=x"00" & buff(step);
					step1<=step1+2;
					step2<=step2+2;
					if(step2>10) then
						step1<=0;
						step2<=1;
						s_Eth_Config_State <= c_Eth_REC_State;
					else
						s_Eth_Config_State <=c_Eth_delay5_State;
					end if;	

			when c_Eth_delay5_State	=>
					counter<=counter+1;
					if (counter<4) then 
						s_Eth_Config_State <= c_Eth_delay5_State;
					else 
						s_Eth_Config_State <= c_Eth_receive1_State;
					end if;

I am difficult to your code because I don’t know what usage is your signal.

I guess your code have some logical error.

s_ReadTrig is always ‘1’, This means cs rd is always 0 by your read/write process, but only address is changed.

W5300 can not know address change when cs or rd signal is no change.
So, I will recommend to add one state that change s_ReadTrig 1 to 0.

At fifo0 & fifo1 access process,

	when c_Eth_receive1_State =>
					s_W_ADDR_Des <= "10" & x"30";
					s_ReadTrig <= '1';
					if s_W_DATA_In_Des_Rdy='1' then
						data1<=s_W_DATA_In_Des;
						buff(step1)<=data;
						s_Eth_Config_State <=c_Eth_receive2_State;
					end if;
        //
        //<<-- Here, Add state to change s_ReadTrig 1 to 0
        //
	when c_Eth_receive2_State =>
					s_W_ADDR_Des <= "10" & x"31";
					s_ReadTrig <= '1';
					if s_W_DATA_In_Des_Rdy='1' then
						data2<=s_W_DATA_In_Des;
						buff(step2)<=data;
						s_Eth_Config_State <=c_Eth_Receive_Data_State;
					end if;

Thank you.

I wonder that c_WIZNET_RXPACK_ADDR(1) is increased by 1 at every clock.
If not, rsr signal maybe always 0.
Sn_RX_RSR have 4 bytes , Sn_RX_RSR0 (the lowest address) value is always 0.

and I believe s_ReadTrig is changed to 0 in another states.

Please, Remind that.
Thank you.

Thank you for the idea! I will change s_read_trig to 0 in other states and check the result. I will let you know

Hi

If you could interface w5300 with spartan-6 then kindly let me know. Did you interfaced using microblaze or did u used HDL for interfacing.