CONTROL, IRQ_ENABLE, and the two LIMIT shadow words all consume the same expanded byte mask. That shared derivation keeps a narrow software store from changing adjacent fields.
Read each column from top to bottom: one strobe bit becomes eight mask bits, and the mask picks either the old byte or the new one.
Strobe to mask: strobe bit 2 is 1, so mask byte 2 is FF; the other mask bytes are 00.
Merge: the result takes BB from the write data in byte 2 and keeps 11, 33 and 44 from the old value.
W1C uses the same mask: its clear mask is wdata & write_mask, so ones written in unselected bytes clear nothing.
// snippet: 32-bit write mask from four byte strobes
logic [31:0] write_mask;
always_comb
for (int b = 0; b < 4; b++) write_mask[b*8 +: 8] = {8{wstrb[b]}};
assign rw_next = (rw_q & ~write_mask) | (wdata & write_mask);
assign w1c_mask = wdata & write_mask;The same mask feeds RW replacement, W1C clear masks, and command qualification. Centralizing it prevents each register from interpreting strobes differently.
Write | Result |
|---|---|
WSTRB=0001 | Only bits 7:0 may change |
WSTRB=0100 | Only bits 23:16 may change |
WSTRB=0000 | No state change |
Unaligned access | Reject or split in the adapter; never reinterpret silently |
The tool starts on the figure above: an RW field holding 11223344, write data AABBCCDD and WSTRB 0100, so only byte 2 is replaced and the result is 11BB3344.
Loading register field tool…
Turn on WSTRB[0] (strobe 0101): bytes 2 and 0 are replaced and the result is 11BB33DD.
Choose W1C, set the current value and the write data to FFFFFFFF and the strobe to 0010: only bits 15:8 clear, giving FFFF00FF, as in the check below.
Set the strobe to 0000: no access type changes the field, whatever the write data.
Only bits 15:8. Written ones outside the selected byte are not part of the transfer.