W5100 UDP pings but doesn't send data

Hello! I’m trying to send two bytes of data from w5100 chip to PC using UDP protocol. Seems that I have done everything by the datasheet algorithm:

  • Did software reset
  • Set gateway IP address to 192.168.11.3;
  • Set subnet mask to 255.255.255.0
  • Set MAC address of w5100;
  • Set IP address to 192.168.11.4;
  • Wrote S0_MR = 0x02 (UDP mode);
  • S0_Port = 0x07D0 (2000);
  • S0_CR = 0x01 (open)
  • Checked S0_SR, it’s SOCK_UDP, so init is OK
    —Sending:
  • Checked S0_TX_FSR, it’s 0x800;
  • Set S0_DIPR = 192.168.11.198 (my PC), S0_DPORT = 0x0FA0 (4000);
  • Checked TMSR (TX mem size), it’s 0x55;
  • Read S0_TX_WR, it’s zero;
  • Wrote two bytes 0xff, 0xff into start_address, which equals 0x4000 (as gS0_TX_Base) ;
  • Updated S0_TX_WR value, now it’s 2, wrote is back;
  • Set SEND cmd : S0_CR = 0x20;
  • Checked S0_CR, it’s zero, so sending seems to be OK.

Chip pings ok, but data’s not received by PC, monitoring by WireShark. Couple of times got the data though, but only two times out of about 30 launches. What am I doing wrong? Help please

What is MAC address exactly? You shown values for everything except this information.

Of these “couple of times”, did you have correct data arrived? With only two bytes FF FF in packet data field?

What you can do now

  • connect your PC directly to the W5100-based device and try again looking what it shows in Wireshark not setting any filters in there;
  • share your code driving W5100 with us.

Thank you for your reply.

Sorry, didn’t think it mattered. I tried different values, now it’s: aa:bb:cc:dd:ee:ff.

Yes, exactly two bytes that i’ve sent.

When I connect directly I only get responses to ping requests from pc, there are no any other packages coming from w5100 device (except for those couple of lucky packages).

I drive w5100 with FPGA - Kintex-7 of Xilinx (maybe unconventional way to affect chip, but it wasn’t up to me to choose). Anyway, my code is on VHDL (excuse me, not good at this, I’m more cpp guy)

Summary

– functions of wr/rd to registers work fine
VARIABLE source_port : std_logic_vector(15 downto 0) := x"07D0";
begin–p1 process
if (reset = ‘1’) then
nWR <= Inactive;
nRD <= Inactive;
nCS <= Inactive;
done <= ‘0’;
read_data <= x"00";
cnt := 0;
step_of_progr <= 1;
memcpy_fl := false;
step_of_memcpy <= 0;
mem_addrA_sign <= x"0000";
mem_data_inA_sign <= x"00";
NUM_OF_TRIES := 0;

elsif (rising_edge(clk)) then
	if (step_of_progr = 1) then
		cnt := cnt+1;
		Soft_Reset(cnt);
		
	elsif (step_of_progr = 2) then
		cnt := cnt+1;
		ProcReadReg(cnt, MR); -- check if reset bit is gone, and it is
		
	elsif (step_of_progr = 3) then
		cnt := cnt + 1;
		IND_AINC_data_MR := x"03";
		Write_MR(cnt, IND_AINC_data_MR);--set AutoIncrement bit and Indirect addressing(0x03)
----------------------------Actual INIT STEP : GATEWAY, IP, MASK--------------------
	elsif (step_of_progr = (start_1_stage+2)) then
		cnt := cnt + 1;
		temp_16 := x"0001";
		SetAdr_AINC(cnt, temp_16);--set start address to write to
------------------GATEWAYs()-------------
	elsif (step_of_progr = (start_1_stage+3)) then
		cnt := cnt + 1;
		GATEWAY_DATA(0) := x"C0";--adr 0001
		SimpleWriteReg(cnt, GATEWAY_DATA(0));
		
	elsif (step_of_progr = (start_1_stage+4)) then
		cnt := cnt + 1;
		GATEWAY_DATA(1) := x"A8";--adr 0002
		SimpleWriteReg(cnt, GATEWAY_DATA(1));
		
	elsif (step_of_progr = (start_1_stage+5)) then
		cnt := cnt + 1;
		GATEWAY_DATA(2) := x"0B";--adr 0003
		SimpleWriteReg(cnt, GATEWAY_DATA(2));
		
	elsif (step_of_progr = (start_1_stage+6)) then
		cnt := cnt + 1;
		GATEWAY_DATA(3) := x"03";--adr 0004
		SimpleWriteReg(cnt, GATEWAY_DATA(3));

	------------------SUBNET masks-------------------
	elsif (step_of_progr = (start_1_stage+7)) then
		cnt := cnt + 1;
		SUBNET_MASK_DATA(0) := x"FF";--adr 0005
		SimpleWriteReg(cnt, SUBNET_MASK_DATA(0));
		
	elsif (step_of_progr = (start_1_stage+8)) then
		cnt := cnt + 1;
		SUBNET_MASK_DATA(1) := x"FF";--adr 0006
		SimpleWriteReg(cnt, SUBNET_MASK_DATA(1));
		
	elsif (step_of_progr = (start_1_stage+9)) then
		cnt := cnt + 1;
		SUBNET_MASK_DATA(2) := x"FF";--adr 0007
		SimpleWriteReg(cnt, SUBNET_MASK_DATA(2));
		
	elsif (step_of_progr = (start_1_stage+10)) then
		cnt := cnt + 1;
		SUBNET_MASK_DATA(3) := x"00";--adr 0008
		SimpleWriteReg(cnt, SUBNET_MASK_DATA(3));
	------------------MAC адрес-------------------
	elsif (step_of_progr = (start_1_stage+11)) then
		cnt := cnt + 1;
		MAC_ADR_DATA(0) := x"aa";--adr 0009
		SimpleWriteReg(cnt, MAC_ADR_DATA(0));
		
	elsif (step_of_progr = (start_1_stage+12)) then
		cnt := cnt + 1;
		MAC_ADR_DATA(1) := x"bb";--adr 000A
		SimpleWriteReg(cnt, MAC_ADR_DATA(1));
		
	elsif (step_of_progr = (start_1_stage+13)) then
		cnt := cnt + 1;
		MAC_ADR_DATA(2) := x"cc";--adr 000B
		SimpleWriteReg(cnt, MAC_ADR_DATA(2));
		
	elsif (step_of_progr = (start_1_stage+14)) then
		cnt := cnt + 1;
		MAC_ADR_DATA(3) := x"dd";--adr 000C
		SimpleWriteReg(cnt, MAC_ADR_DATA(3));
		
	elsif (step_of_progr = (start_1_stage+15)) then
		cnt := cnt + 1;
		MAC_ADR_DATA(4) := x"ee";--adr 000D
		SimpleWriteReg(cnt, MAC_ADR_DATA(4));
		
	elsif (step_of_progr = (start_1_stage+16)) then
		cnt := cnt + 1;
		MAC_ADR_DATA(5) := x"ff";--adr 000E
		SimpleWriteReg(cnt, MAC_ADR_DATA(5));
------------------W5100 IP address---192.168.11.4-----------
	elsif (step_of_progr = (start_1_stage+17)) then
		cnt := cnt + 1;
		temp_8 := x"C0";--adr 000F 
		SimpleWriteReg(cnt, temp_8);
		
	elsif (step_of_progr = (start_1_stage+18)) then
		cnt := cnt + 1;
		temp_8 := x"A8";--adr 0010 
		SimpleWriteReg(cnt, temp_8);
		
	elsif (step_of_progr = (start_1_stage+19)) then
		cnt := cnt + 1;
		temp_8 := x"0B";--adr 0011 
		SimpleWriteReg(cnt, temp_8);
		
	elsif (step_of_progr = (start_1_stage+20)) then
		cnt := cnt + 1;
		temp_8 := x"04";--0012 
		SimpleWriteReg(cnt, temp_8);
-------------------INIT : Sn_MR = 0x02------------------------------
	elsif (step_of_progr = (start_1_stage+21)) then -- 0x17
		cnt := cnt + 1;
		S0_MR := x"0400";
		SetAdr_AINC(cnt, S0_MR);--установили начальный адрес
		
	elsif (step_of_progr = (start_1_stage+22)) then
		cnt := cnt + 1;
		SimpleWriteReg(cnt, data_to_S0_MR);
---------------------INIT: S0_PORT = source_port (2+2 bytes)-------------------
	elsif (step_of_progr = (start_1_stage+23)) then
		cnt := cnt + 1;
		S0_PORT(0) := x"0404";
		SetAdr_AINC(cnt, S0_PORT(0));--set address to write 
	
	elsif (step_of_progr = (start_1_stage+24)) then 
		cnt := cnt+1;
		SimpleWriteReg(cnt, source_port(15 downto 8));--0404
			
	elsif (step_of_progr = (start_1_stage+25)) then 
		cnt := cnt+1;
		SimpleWriteReg(cnt, source_port(7 downto 0));--0405
---------------------INIT: S0_CR = OPEN----------------------------
	elsif (step_of_progr = (start_1_stage+26)) then
		cnt := cnt + 1;
		SetAdr_AINC(cnt, S0_CR);--set address to write
		
	elsif (step_of_progr = (start_1_stage+27)) then
		cnt := cnt+1;
		OPENn := x"01";
		SimpleWriteReg(cnt, OPENn);
	
	elsif (step_of_progr = (start_1_stage + 28)) then
		cnt := cnt + 1;
		SetAdr_AINC(cnt, S0_CR);--set address to read
	
	elsif (step_of_progr = (start_1_stage + 29)) then
		cnt := cnt + 1;
		SimpleReadReg(cnt);
----------------------INIT : READ S0_SR----------------------------
	elsif (step_of_progr = (start_1_stage+30)) then
		cnt := cnt + 1;
		SetAdr_AINC(cnt, S0_SR);--set address to read
		
	elsif (step_of_progr = (start_1_stage+31)) then
		cnt := cnt+1;
		SimpleReadReg(cnt);
	
	elsif (step_of_progr = (start_1_stage+32)) then
		if (temp_read_data_08 /= SOCK_UDP) then 
			step_of_progr <= step_of_progr + 1; -- finish init and retry
		else
			Done <= '1'; -- initialization is done successfully
			step_of_progr <= (start_4_stage); -- GOTO Sending stage
		end if;
	----------unsuccessfull INIT : S0_CR = CLOSE-----------------------------------
	elsif (step_of_progr = (start_1_stage+33)) then
		cnt := cnt + 1;
		Write_MR(cnt, IND_AINC_data_MR);--установка косв адресации и бита автоинкремента (0x03)
		
	elsif (step_of_progr = (start_1_stage+34)) then
		cnt := cnt + 1;
		SetAdr_AINC(cnt, S0_CR);--set address to write
		
	elsif (step_of_progr = (start_1_stage+35)) then
		cnt := cnt + 1;
		CLOSEe := x"10";
		SimpleWriteReg(cnt, CLOSEe);
		
	elsif (step_of_progr = (start_1_stage+36)) then
		step_of_progr <= (start_1_stage + 21); -- retry to init

–=======================================================================
–=============SENDING PROCESS → 4 stage==========================-------
–=======================================================================
– check FRee memory size
elsif (step_of_progr = start_4_stage) then
cnt := cnt + 1;
SetAdr_AINC(cnt, S0_TX_FSR_0);–set adr to read

	elsif (step_of_progr = (start_4_stage + 1)) then 
		cnt := cnt + 1;
		SimpleReadReg(cnt);
		S0_TX_FSR_contents(15 downto 8) := temp_read_data_08;
		
	elsif (step_of_progr = (start_4_stage + 2)) then
		cnt := cnt + 1;
		SimpleReadReg(cnt);
		S0_TX_FSR_contents(7 downto 0) := temp_read_data_08;
		
	elsif (step_of_progr = (start_4_stage + 3)) then
		get_free_size_vect := S0_TX_FSR_contents;
		get_free_size := to_integer(unsigned(get_free_size_vect));
		if (get_free_size < send_size) then
			step_of_progr <= start_4_stage;
		else
			step_of_progr <= (start_4_stage + 11);
		end if;
		
	-- ========= Sn_DIPR = remote_ip; =======
	elsif (step_of_progr = (start_4_stage + 11)) then
		cnt := cnt + 1;
		temp_16 := x"040c";--S0_DIPR(0)
		SetAdr_AINC(cnt, temp_16);--set addr to write to

	elsif (step_of_progr = (start_4_stage + 12)) then
		cnt := cnt + 1;
		remote_IP(0) := x"C0";
		SimpleWriteReg(cnt, remote_IP(0));
		
	elsif (step_of_progr = (start_4_stage + 13)) then
		cnt := cnt + 1;
		remote_IP(1) := x"A8";
		SimpleWriteReg(cnt, remote_IP(1));
		
	elsif (step_of_progr = (start_4_stage + 14)) then
		cnt := cnt + 1;
		remote_IP(2) := x"0B";
		SimpleWriteReg(cnt, remote_IP(2));
		
	elsif (step_of_progr = (start_4_stage + 15)) then
		cnt := cnt + 1;
		remote_IP(3) := x"C6";
		SimpleWriteReg(cnt, remote_IP(3));
	-- ========= Sn_DPORT = remote_port; =======
	elsif (step_of_progr = (start_4_stage + 9 + 7)) then
		cnt := cnt + 1;
		temp_16 := x"0410";--S0_DPORT0
		SetAdr_AINC(cnt, temp_16);--set address to write
		
	elsif (step_of_progr = (start_4_stage + 10 + 7)) then
		cnt := cnt + 1;
		remote_PORT(0) := x"0f";
		SimpleWriteReg(cnt, remote_PORT(0));
		
	elsif (step_of_progr = (start_4_stage + 11 + 7)) then
		cnt := cnt + 1;
		remote_PORT(1) := x"a0";
		SimpleWriteReg(cnt, remote_PORT(1));


– ============ REading S0_TX_WR =======
elsif (step_of_progr = (start_4_stage + 12 + 7)) then
cnt := cnt + 1;
SetAdr_AINC(cnt, S0_TX_WR_0);–set address to read

	elsif (step_of_progr = (start_4_stage + 13 + 7)) then
		cnt := cnt + 1;
		SimpleReadReg(cnt);
		S0_TX_WR_contents_v(15 downto 8) := temp_read_data_08;
	
	elsif (step_of_progr = (start_4_stage + 14 + 7)) then
		cnt := cnt + 1;
		SimpleReadReg(cnt);
		S0_TX_WR_contents_v(7 downto 0) := temp_read_data_08;


– --==== /* calculate offset address */ ======
elsif (step_of_progr = (start_4_stage + 15 + 7)) then --0x57
cnt := cnt + 1;
temp_16 := x"001B"; – TMSR
SetAdr_AINC(cnt, temp_16);–set address to read

	elsif (step_of_progr = (start_4_stage + 16 + 7)) then
		cnt := cnt + 1;
		SimpleReadReg(cnt); -- this value equals 0x55
		
	elsif (step_of_progr = (start_4_stage + 17 + 7)) then --0x59
		get_offset_vect := S0_TX_WR_contents_v and gS0_TX_MASK_vect;
		get_offset := to_integer(unsigned(get_offset_vect));
		step_of_progr <= step_of_progr + 1;


– /* calculate start address(physical address) */ ==
elsif (step_of_progr = (start_4_stage + 18 + 7)) then
gS0_TX_BASE := chip_base_address + TX_memory_base_adr;
get_start_address := gS0_TX_Base + get_offset;
get_start_address_vect := std_logic_vector(to_unsigned(get_start_address, get_start_address_vect’length));
step_of_progr <= step_of_progr + 1;

– – /* if overflow socket TX memory */ –
elsif (step_of_progr = (start_4_stage + 19 + 7)) then
step_of_progr <= start_4_stage + 21 + 7;

	elsif (step_of_progr = (start_4_stage + 21 + 7)) then
		cnt := cnt + 1;
		SetAdr_AINC(cnt, get_start_address_vect);--set address to write

	elsif (step_of_progr = (start_4_stage + 22 + 7)) then
		cnt := cnt + 1;
		temp_8 := x"ff";
		SimpleWriteReg(cnt, temp_8);
		
	elsif (step_of_progr = (start_4_stage + 23 + 7)) then
		cnt := cnt + 1;
		temp_8 := x"ff";
		SimpleWriteReg(cnt, temp_8);

	-- increase Sn_TX_WR as length of send_size -- 
	elsif (step_of_progr = (start_4_stage + 24 + 7)) then --0x
		S0_TX_WR_contents := to_integer(unsigned(S0_TX_WR_contents_v));
		S0_TX_WR_contents := S0_TX_WR_contents + send_size;
		S0_TX_WR_contents_v := std_logic_vector(to_unsigned(S0_TX_WR_contents, S0_TX_WR_contents_v'length));
		step_of_progr <= step_of_progr + 1;

		-- write back to Sn_TX_WR--
	elsif (step_of_progr = (start_4_stage + 25 + 7)) then
		cnt := cnt + 1;
		SetAdr_AINC(cnt, S0_TX_WR_0);--set addr to write
		
	elsif (step_of_progr = (start_4_stage + 26 + 7)) then
		cnt := cnt + 1;
		SimpleWriteReg(cnt, S0_TX_WR_contents_v(15 downto 8));
		
	elsif (step_of_progr = (start_4_stage + 27 + 7)) then
		cnt := cnt + 1;
		SimpleWriteReg(cnt, S0_TX_WR_contents_v(7 downto 0));

	--/* set SEND command */ 
	elsif (step_of_progr = (start_4_stage + 28 + 7)) then
		cnt := cnt + 1;
		SetAdr_AINC(cnt, S0_CR);--set addr to write
		
	elsif (step_of_progr = (start_4_stage + 29 + 7)) then
		cnt := cnt + 1;
		SENDd := x"20";
		SimpleWriteReg(cnt, SENDd);


–======= Complete Sending? ============
– If (Sn_CR == 0x00) transmission is completed. –
elsif (step_of_progr = (start_4_stage + 30 + 7)) then
cnt := cnt + 1;
SetAdr_AINC(cnt, S0_CR);–set addr to read

	elsif (step_of_progr = (start_4_stage + 31 + 7)) then 
		cnt := cnt + 1;
		SimpleReadReg(cnt); -- has to become 0х00
		
	elsif (step_of_progr = (start_4_stage + 32 + 7)) then
		if (temp_read_data_08 = x"00") then
			step_of_progr <= start_5_stage; -- it is 0х00 indeed 
		end if;

I am not sure I am going to read and trace it. Why not use case statement for state machine? What you currently have is totally non-readable. I bet you simply mess state of the machine during operation.

Where’s waiting for MR’s bit 7 to become 0? What is the purpose of cnt?

I agree that the code is difficult to read, but on time diagrams it’s more obvious, that it writes into registers fine, and reads what is expected.

I check MR right after reset, and it’s zero. No need to wait. Besides, there is expected value in status register after initialization, so the problem at least is not before that.

That’s all you can help me with?

Make a dump of states machine passes through. Thus should be the easiest thing to do on your code. After dump you look into the states, and ensure that the sequence is correct.

Thank you, problem is solved. Turned out a time delay was needed between chip initialization and sending procedure. For some reason chip couldn’t send data right after initialization