Skip to content

Get: (a_size = 0)

Muhammad Hadir Khan edited this page Aug 10, 2020 · 2 revisions

This configuration means that the master wants to read a single byte of data. It expects the response AccessAckData to have d_size = 0 which means d_data carries an 8-bit data payload.

For this overview we will assume the following memory organisation

Memory

a_address and a_mask Possibilities

Since we are reading a single byte (a_size = 0) the a_address can not only have word aligned but subword aligned addressing as well. The a_mask selects the byte lane to read from. Which means if we want to read from the zeroth byte lane then a_mask = 'b0001. One HIGH bit of a_mask indicates the active byte lane.

Note: When a_size = 0 which means 2a_size = 20 = 1 byte then a_mask must have only one bit HIGH since we need to read only one byte of data.

a_address[31:0] a_mask[3:0]
'd0 'b0001
'd1 'b0010
'd2 'b0100
'd3 'b1000
'd4 'b0001
'd5 'b0010
'd6 'b0100
'd7 'b1000
. .
. .

Note: The 'd in above table indicates decimal representation and the 'b indicates binary representation.

Example 1: Reading Byte EF from Memory

So if we want to read the zeroth byte E F from the above memory we will set a_address = 'd0 and a_mask = 'b0001.

Example 2: Reading Byte FF from Memory

So if we want to read the second byte F F from the above memory we will set a_address = 'd6 and a_mask = 'b0100.

Functional verification design

Following are the points needed to be considered when dealing with reading one byte (Get: a_size = 0)

  1. a_address can be word aligned as well as subword aligned (0, 1, 2, 3, 4, 5, 6, 7, 8 ...)
  2. a_mask must have only one bit active at any given time.
  3. a_mask must be aligned with a_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) {
  addr_chk := true.B
  mask_chk := ~((a_mask & ~mask).orR)  
}

Here we created our own mask to check against the a_mask we receive from the Host. In the when block we are checking for the one byte condition and we hardwired addr_chk := true.B as discussed above that address can be word as well as subword aligned so by default we pass the check.

For mask_chk we have set up a logic which ensures that at a given time only one bit of a_mask is set and is aligned with the address as shown in the table above.

We will go through some test cases to ensure the logic works well and is lucid.

Test Case: Example 1 (Reading Byte EF from Memory)

Input 1:
a_address[31:0] a_size[1:0] a_mask[3:0]
'h0 'h0 'b0001

With these inputs incoming let's analyse what is happening in the wires we declared mask, addr_chk, mask_chk.

mask

mask = (1 << a_address(1,0))

a_address bits are as follows:

a_address[31] a_address[30] ... a_address[1] a_address[0]
0 0 ... 0 0

Since we extract the first two bits of a_address we get 'b00

So 'b0001 << 'b00 results in the same 'b0001 or 'd1

Which means,

mask := 1.U
addr_chk

Since we have a_size = 0 so our when block executes and addr_chk is set to true. So,

addr_chk := true.B
mask_chk

We are using the mask and a_mask to set this wire. Currently we have mask := 'b0001 and a_mask := 'b0001.

In the first step we do a bitwise AND operation between a_mask and inverted mask as:

a_mask & ~mask

This results in

'b0001 & 'b1110 = 'b0000

The .orR is a Chisel function for OR Reduction. Which returns true if any bit is set. Here it checks if any bit is set or not. As seen above there are no bits set so

'b0000.orR returns false.

Then we invert the result returned from .orR, ~false.B which makes mask_chk := true.B and passes the check.

Which means Input 1 was correct and passes the verification check ✅

Now let's test another input under the same example where we want to read the byte E F from Memory.

Input 2:
a_address[31:0] a_size[1:0] a_mask[3:0]
'h0 'h0 'b0010

With these inputs incoming let's analyse what is happening in the wires we declared mask, addr_chk, mask_chk.

mask

mask = (1 << a_address(1,0))

a_address bits are as follows:

a_address[31] a_address[30] ... a_address[1] a_address[0]
0 0 ... 0 0

Since we extract the first two bits of a_address we get 'b00

So 'b0001 << 'b00 results in the same 'b0001 or 'd1

Which means,

mask := 1.U
addr_chk

Since we have a_size = 0 so our when block executes and addr_chk is set to true. So,

addr_chk := true.B
mask_chk

We are using the mask and a_mask to set this wire. Currently we have mask := 'b0001 and a_mask := 'b0010.

In the first step we do a bitwise AND operation between a_mask and inverted mask as:

a_mask & ~mask

This results in

'b0010 & 'b1110 = 'b0010

This time the .orR returns true since a bit is set.

'b0010.orR returns true.

Then we invert the result returned from .orR, ~true.B which makes mask_chk := false.B and fails the check.

This is rightly so, since we are providing the a_address = 0 we need to read the zeroth byte lane not the first byte lane which means the a_mask must have been 'b0001 instead of b0010 which is incorrect and our logic implementation catches this error and fails the test pass resulting in error being generated.

Which means Input 2 was incorrect and fails in the verification check ❌

Test Case: Example 2 (Reading Byte FF from Memory)

Input 1:
a_address[31:0] a_size[1:0] a_mask[3:0]
'h6 'h0 'b0100

With these inputs incoming let's analyse what is happening in the wires we declared mask, addr_chk, mask_chk.

mask

mask = (1 << a_address(1,0))

a_address bits are as follows:

a_address[31] a_address[30] ... a_address[1] a_address[0]
0 0 ... 1 0

Since we extract the first two bits of a_address we get 'b10

So 'b0001 << 'b10 results in 'b0100 or 'd4

Which means,

mask := 4.U
addr_chk

Since we have a_size = 0 so our when block executes and addr_chk is set to true. So,

addr_chk := true.B
mask_chk

We are using the mask and a_mask to set this wire. Currently we have mask := 'b0100 and a_mask := 'b0100.

In the first step we do a bitwise AND operation between a_mask and inverted mask as:

a_mask & ~mask

This results in

'b0100 & 'b1011 = 'b0000

The .orR returns false since no bit is set.

'b0000.orR returns false.B

Then we invert the result returned from .orR, ~false.B which makes mask_chk := true.B and passes the check.

This test passes correctly as if you see the memory diagram above the byte F F is at subword address location 'h6 and the a_mask = 'b0100 correctly activates the second byte lane where F F is present which means there are no errors in the inputs passed.

Which means Input 1 was correct and passes in the verification check ✅

Let's try with another input.

Input 2:
a_address[31:0] a_size[1:0] a_mask[3:0]
'h6 'h0 'b1100

With these inputs incoming let's analyse what is happening in the wires we declared mask, addr_chk, mask_chk.

mask

mask = (1 << a_address(1,0))

a_address bits are as follows:

a_address[31] a_address[30] ... a_address[1] a_address[0]
0 0 ... 1 0

Since we extract the first two bits of a_address we get 'b10

So 'b0001 << 'b10 results in 'b0100 or 'd4

Which means,

mask := 4.U
addr_chk

Since we have a_size = 0 so our when block executes and addr_chk is set to true. So,

addr_chk := true.B
mask_chk

We are using the mask and a_mask to set this wire. Currently we have mask := 'b0100 and a_mask := 'b1100.

In the first step we do a bitwise AND operation between a_mask and inverted mask as:

a_mask & ~mask

This results in

'b1100 & 'b1011 = 'b1000

The .orR returns true since a bit is set.

'b1000.orR returns true.B

Then we invert the result returned from .orR, ~true.B which makes mask_chk := false.B and fails the check.

The check rightly fails since we have a_size = 0 which means we need to read only one byte of data at any given time and while giving the inputs we set a_mask = 'b1100 which tells to read two bytes lanes and this is not allowed under the provided circumstances, so our logic correctly fails the test.

Which means Input 2 was incorrect and fails in the verification check ❌