However, here, I want to test it with multiple transactions. The master is 64 bits and the slave is 32 bits.
While randomly generating all possible combinations of AWSIZE, AWLEN, and WSTRB for testing, a transmission error was encountered.
Master:
awaddr[35:0] = 0x642_0860
awburst[1:0] = 0x1
awlen[7:0] = 0x3
awsize[2:0] = 0x1
wdata[63:0] = 0xefa9_d2c9_2f96_d822
wstrb[7:0] = 0x3 0x30 0xc0 0x0c
Slave:
wdata[31:0] = 0xd822 0x0 0xefa9_0000 0x0
wstrb[3:0] = 0x3 0x0 0xc 0x0
As you can see, the slave's wdata[31:0] does not correctly receive the data from the master. Specifically, the master's wdata[47:40] and wdata[39:32] are not correctly received by the slave.
wdata[31:0]
wdata[47:40]
wdata[39:32]
I’m confused because it works when the master's wstrb[7:0] = 0xf0 or 0x0f, but when I choose different wstrb values, the slave can't receive the data. Is there a restriction rule for wstrb, or did I misunderstand? Could you guide me, please?
wstrb[7:0] = 0xf0
0x0f
wstrb
[update]
Through several experiments, I found that when a 64-bit Master sends data to a 32-bit slave bus, the data must always be sent in 32-bit chunks. Since the Master is 64-bit, the wstrb can be either 8'hf or 8'hf0.
8'hf
8'hf0
If I send the 64-bit data with wstrb = 'hf0 first and then wstrb = 'hf, the slave does not receive the data correctly. However, if I send the 64-bit data with wstrb = 'hf first and then wstrb = 'hf0, the slave receives the data correctly.
wstrb = 'hf0
wstrb = 'hf
I originally thought that when splitting 64-bit data into two 32-bit parts to send to the slave, as long as I match the 32-bit boundaries with any wstrb combination, it should work without issues. However, from my experiments, it seems that when sending the data, the wstrb must first send the lower 32-bit part and then the upper 32-bit part. Is this the correct behavior? Does the lower 32 bits always need to be sent before the upper 32 bits?
Can’t I first send wstrb = 8'h1001_1010 and then send wstrb = 8'h0110_0101? I'm quite confused and would like some help understanding this.
wstrb = 8'h1001_1010
wstrb = 8'h0110_0101
4214.Bus Issue-1.PDF
I think possibly the issue you are facing is a more basic one in that you are not following the rules for WSTRB and which bits can be asserted. See section A4.2.1 for a description of how the WSTRB signal, and importantly, section A4.2.2 for examples of how WSTRB can be used in "Narrow transfers" such as you are performing here.
For any write transaction the AWADDR, AWBURST, AWLEN and AWSIZE signals define which byte lanes can be used for each transfer. AWSIZE tells you the maximum number of WSTRB bits that can be asserted for each transfer, and AWADDR tells you which AWSIZE width (and AWSIZE aligned) part of the data bus can be used for the first transfer. AWBURST then tells you how the AWSIZE width range of WSTRB bits might change for each of the AWLEN transfers in the transaction.
So if we look at your example, the 64-bit manager is signalling a transaction starting at AWADDR=0x642_0860, and AWSIZE=0x1 (16-bit). AWLEN=0x3 (4 transfers) and AWBURST=0x1 (INCR).
The first transfer starts at a 64-bit aligned address, so active data bus bits are WDATA[15:0] and the byte lanes that could be used are WSTRB[1:0] for the 16-bit transfer. So WSTRB[7:0] could indicate 0x03, 0x02, 0x01 or 0x00 (any combination that only uses the byte lanes described by AWADDR and AWSIZE).
As this is an INCR burst, the next transfer uses WDATA[31:16] and WSTRB[3:2], so WSTRB can be 0x0C, 0x08, 0x04 or 0x00.
The 3rd transfer in the transaction can use WDATA[47:32] and WSTRB[5:4], so WSTRB can be 0x30, 0x20, 0x10 or 0x00.
And the final transfer would use WDATA[63:48] and WSTRB[7:6], so possible WSTRB values of 0xC0, 0x80, 0x40 or 0x00.
You can only ever use WSTRB bits that are covered by the AWADDR/AWSIZE/AWBURST controls, and any other WSTRB bits must be 0 as they are not addressed by this transfer.
So the WSTRB bit patterns you show in your example of 0x03, 0x30, 0xC0 and 0x0C are only actually legal for the first transfer, and it looks like the 64-32 bit conversion logic you have is attempting to route the relevant half of the WSTRB[7:0] bus onto WSTRB[3:0], hence seeing 0x03 for the first transfer, 0x0 for the second (because WSTRB[3:0] was 0x0 on the 64-bit side), 0xC for the third (because that is what was on WSTRB[7:4]) and 0x0 (again because that was what was on WSTRB[7:4] for the 4th transfer).
Throughout your description of what you have been trying, the WSTRB values are mostly illegally trying to use bits not covered by the AWADDR/AWSIZE/AWBURST controls (with AWSIZE=0x1 you can only have a max of 2 bits per transfer), so please check your AXI manager implementation to see why it is generating illegal WSTRB values.
Looking at your very last line in your question, if you wanted to drive WSTRB to 8'b1001_1010 or 8'b0110_0101, this would need AWSIZE to indicate a 64-bit transfer (as you are trying to use all 8 byte lanes - or at least byte lanes within the 64-bit aligned range of byte lanes).
Thank you for your detailed response.
In the example I showed, the WSTRB bit patterns 0x03, 0x30, 0xC0, and 0x0C were an attempt to send only one byte of data at a time. I thought that as long as I was activating only 16 bits, no matter how I combined the WSTRB values for the data I wanted to send from the bus master, it would be fine.
Based on what you've explained, it seems that from the master's perspective, I must send WSTRB[1:0], then WSTRB[3:2], followed by WSTRB[5:4], and finally WSTRB[7:6] in order. However, I was trying to send WSTRB[1:0], then WSTRB[3:2], followed by WSTRB[5:4], and then WSTRB[7:6] because the master has 64 bits of data, and I thought I could control which byte I wanted to send just by adjusting the WSTRB. But after applying your explanation, it seems that I must always send WSTRB[1:0], then WSTRB[3:2], WSTRB[5:4], and WSTRB[7:6] in sequence from the master's perspective.
I performed another test this time. I set AWBURST=1, AWLEN=1, AWSIZE=2 from the master and tried to send WSTRB=0xF0, followed by 0x0F, along with the 64-bit data to the slave, but I found that the data was not properly transferred to the slave. However, when I set WSTRB=0x0F followed by 0xF0, the data was successfully transferred. This seems to contradict what you mentioned.
Hopefully it doesn't contradict anything I said. Re-reading my reply I can't see where I might have contradicted what you are seeing, but if I have been unclear I apologise.
0x0F and then 0xF0 would be valid WSTRB values for 32-bit transfers on a 64-bit bus IF the start address is ending with 0x0 or 0x8 as that would indicate the lower half of the data bus is being used for the first transfer.
If the start address ended with 0x4 or 0xC then the upper half of the data bus is being used for the first transfer, and so 0xF0 and then 0x0F would be valid WSTRB values.