About Sn_TX_WR value

Hello, I am writing an FPGA code to connect my board to ethernet using W5100S. I am using an UDP connection.

My all socket buffers are set as default values which is 2KB. I am using the socket 0 to communicate.

In the FPGA code I read the Sn_TX_WR for socket 0, write my data to Tx memory and then set the Sn_TX_WR pointer with the new value which is incremented by a 32 for 32Bytes transmit. After that I set the Sn_CR to transmit the data. Data is transmitted correctly. After a while Sn_TX_WR pointer is reached to a value of 0x7FE0. Than I put my data on the buffer and transmit a 32B data and update the Sn_TX_WR pointer to 0x8000. This time W5100S chip transmits 32800 bytes data instead of 32B. It dumps all tx memory and after that sets the Sn_TX_WR pointer to 0x0000.

I have checked the driver codes to make sure if i am doing the right thing. The wiz_send_data function also increments the pointer Sn_TX_WR after writing to tx buffer. So what am i doing wrong? What should I do?

Here is related code in w5100s.c :

void wiz_send_data(uint8_t sn, uint8_t *wizdata, uint16_t len)
{
uint16_t ptr;
uint16_t size;
uint16_t dst_mask;
uint16_t dst_ptr;

ptr = getSn_TX_WR(sn);

dst_mask = ptr & getSn_TxMASK(sn);
dst_ptr = getSn_TxBASE(sn) + dst_mask;

if (dst_mask + len > getSn_TxMAX(sn))
{
size = getSn_TxMAX(sn) - dst_mask;
WIZCHIP_WRITE_BUF(dst_ptr, wizdata, size);
wizdata += size;
size = len - size;
dst_ptr = getSn_TxBASE(sn);
WIZCHIP_WRITE_BUF(dst_ptr, wizdata, size);
}
else
{
WIZCHIP_WRITE_BUF(dst_ptr, wizdata, len);
}

ptr += len;

setSn_TX_WR(sn, ptr);
}

UDP is networking protocol, your connection is wired Ethernet.

Sounds you do things correctly, and there’s something wrong here. Like register gets 0xFFE0. Are you sure that your software/hardware handles bit 15 properly - as it looks like bit 15 is being always reset, thus causing 0x7FE0+0x20=0x0000.

Register does not gets 0xFFE0 it gets 0x7FE0 and than after adding a value I set it to 0x8000. After data transmission is complete it gets 0x0000. It does not get 0x8020 or other values greater than 0x8000.

How can I prevent it from growing up to 0x8000? It starts at 0x0000 after reset.

You can not. It is a cyclical pointer/byte counter.

First you must prove that you really write 0x8000 in there with bit 15 set.

You said that yoy “write FPGA code … W5100s”, and then append code in C. Not sure C can be compiled to hardware. SystemVerilog can. Thus I suspect there’s a layer of another software/firmware and hardware between your C program and W5100s SPI write cycle. You may have simply lose bit 15 somewhere.

Here is the proof, it take time to find the data on the logic analyzer but finally i did.

As I said I am writing FPGA code for W5100S. To make myself sure, I have inspected the C code which was given in “w5100s.c”.

I am writing my code in vhdl and it is running on a real hardware.

So as i have proved that I am not losing bit 15 do you have any other idea?

Good. Can you, as a test, perform pointer write in two steps - two SPI frames, a byte at a time? First frame F0 04 24 80 and second F0 04 25 00? Also try using SEND command instead of SEND_MAC. I do not know solution to your exact problem, thus we must experiment to see the difference.

This is for SEND_MAC command:

This is for SEND command:

And? Still the same issue with pointer going 0x0 rather than 0x8000?

I am afraid yes. Are we expecting to have 0x8000 and even 0x8020 maybe in the next transmit and up to 0xFFFF right?

I have an idea. I will keep a Sn_TX_WR pointer on my side (host/FPGA). After each transmit I will update my register and write the content to Sn_TX_WR. So there will be no need to read Sn_TX_WR pointer. I will just write it with the new value. Because when I write 0x8000 and than read it back again after writing my data to tx memory, it gives 0x0000 instead of 0x8000. So eventually I am updating it to 0x0020 instead of 0x8020 and it dumps tx memory… I will try it and keep you informed.

Yes, I would expect this behavior. At least other chips from the family behaves this way. The pointer is 16-bit, however it is not explicitly stated in the datasheets. Anyway having 15-bit pointer would be a nightmare (must be a multiple of byte otherwise bit-wise operations are required).

You seem to perform properly, thus there must be something else. Please check SPI timing against datasheet (pages 102-104), try lowering clock speed and increaseing time between chip selects.

1 Like

The thread - old but - exists and I’m tinkering with one of these so -
Anyone who happens to step into here looking for answers.

  1. If Sn_TX_WR really IS a “POINTER” ( which - yeah - I’d buy that), Then setting it to 0x8000 sets it exactly 1 step OUT OF THE MEMORY MAP for this W5100S.
    (Hint - that’s probably going to get some interesting results.! I know. the Version 1.2.5 datasheet says 0x8000). I just think probably - NOT. Maybe 0x7FFF Making Hex 8000 counts. But not Index or address 0x8000. I might try to prove this when I get time but a decent support person can easily confirm or deny it.
  2. Everybody likes to WRITE to a register and then READ the register to make sure it GOT THERE. Right?
    You can write to the Sn_TX_WR register all you want! Seems it wont show you that register content that you just wrote until you do an network SEND command. Then you can read it! Important little detail that can help. Acts like a POINTER! Right?