-
Notifications
You must be signed in to change notification settings - Fork 10
Get: (a_size = 1)
This page deals with the configuration when a_size = 1
. This means that the Host wants to read 2 bytes of data since 21 = 2 bytes.
For this overview we will assume the following memory organisation
Since we are reading two bytes (a_size = 1
) the a_address
will only have even addressing as shown in the figure above. The a_mask
selects the two byte lanes to read from. a_mask
must have two contiguous bits set meaning 'b0011
and 'b1100
are the only options when a_size = 1
. Which means if we want to read from the zeroth and first byte lanes then a_mask = 'b0011
. One HIGH bit of
a_mask
indicates the active byte lane.
a_address[31:0] | a_mask[3:0] |
---|---|
'd0 | 'b0011 |
'd2 | 'b1100 |
'd4 | 'b0011 |
'd6 | 'b1100 |
'd8 | 'b0011 |
. | . |
. | . |
Note: The 'd in above table indicates decimal representation and the 'b indicates binary representation.
If we want to read two bytes 2F FF
from memory the even address to access it will be a_address = 'd6
and mask should be a_mask = 'b1100
. This reads 0x2FFF
from the memory as shown above in the diagram as well.
If we want to read two bytes E0 AB
from memory the even address to access it will be a_address = 'd8
and mask should be a_mask = 'b0011
. This read 0xE0AB
from the memory.
Following are the points needed to be considered when dealing with reading two bytes (Get: a_size = 1
)
-
a_address
should only be even (0, 2, 4, 6, 8, 10, 12, 14, 16 ...) -
a_mask
must have only two bits active and contiguous at any given time. -
a_mask
must be aligned witha_address
at any given time according to the table given above.
// Our own mask created using the a_address
// If data bus width (DBW) is 32-bits then 32/8 = 4 bytes so a_mask uses 4 bits to represent the active byte lane.
val mask = Wire(UInt((DBW/8).W))
mask := (1 << a_address(1,0))
// Creating two wires of Chisel.Bool type in order to set them `true.B` if the check is passed or `false.B` if the check is failed.
val addr_chk = Wire(Bool())
val mask_chk = Wire(Bool())
when(a_size === 0.U) { // 1 Byte covered in Get: (a_size = 0)
addr_chk := true.B
mask_chk := ~((a_mask & ~mask).orR)
} .elsewhen(a_size === 1.U) { // 2 Bytes
addr_chk := ~a_address(0)
mask_chk := Mux(a_address(1), ~((a_mask & "b0011".U).orR), ~((a_mask & "b1100".U).orR))
}
Note: The code above is taken from the previous case where a_size = 0
and was modified to deal with a_size = 1
as well.
This time we need to check the a_address
as well since it must be even. So we extract the zeroth bit of a_address
with a_address(0)
. If this bit is set then the address would be odd and we would invert the result to 'b0
in order to make the addr_chk := false.B
.
The logic for handling mask_chk
ensures that any given time only two bits are HIGH due to a_size = 1
and they must be contiguous and must only be either 'b0011
or 'b1100
according to the address provided.
We will go through some test cases to explain the reasoning for this logic and ensure the logic works well i.e passes the check when inputs are correct and fails them if the inputs are wrong.
a_address[31:0] | a_size[1:0] | a_mask[3:0] |
---|---|---|
'h6 | 'h1 | 'b1100 |
With these inputs incoming let's analyse what is happening in the wires we declared addr_chk
, mask_chk
.
Note: We won't be using the mask
wire in this condition.
The addr_chk
is wired with the logic which ensures that the zeroth bit must not be set in order to ensure even addressing.
Since we extract the zeroth bit and invert it ~a_address(0)
so we get,
addr_chk := true.B
because a_address(0) gives 'b0
in this case and inverting it results in 'b1
or true.B
We know that a_mask in this condition must always have 2 bits HIGH, they must be contiguous and they must be select either the LSB byte lanes 'b0011
or the MSB byte lanes 'b1100
.
In this condition we have a_mask = 'b1100
as input coming in. We use a Mux()
construct of Chisel to control the wiring of mask_chk
. The condition for the Mux
is the first bit of a_address
. If this bit is set it means the address we are getting is not word aligned and can be the following (2, 6, 10, 14, 18, 22 ... ) and we use this logic ~((a_mask & "b0011".U).orR)
to set the mask_chk
. Otherwise, if the first bit of a_address
is not set, we use the next logic ~((a_mask & "b1100".U).orR)
to set the mask_chk
.