Skip to content

Commit

Permalink
[i2c] Require nonzero mask for address match
Browse files Browse the repository at this point in the history
Adjust the address CSR so a given field can be disabled with an address
mask of zero. Only accept target address designations if at least one
bit in the mask is set.

If a user wishes to be the target of *all* I2C traffic, that user can
set the same single bit for each mask, then use all zeroes for one
address and all ones for the other. (Technically, only that single bit
is meaningful, but "all ones" covers whichever bit is selected in the
mask.)

Signed-off-by: Alexander Williams <[email protected]>
  • Loading branch information
a-will committed May 4, 2024
1 parent f623e26 commit 9dc1118
Show file tree
Hide file tree
Showing 4 changed files with 23 additions and 11 deletions.
10 changes: 8 additions & 2 deletions hw/ip/i2c/data/i2c.hjson
Original file line number Diff line number Diff line change
Expand Up @@ -691,15 +691,21 @@
}
{ bits: "13:7"
name: "MASK0"
desc: "I2C target mask number 0"
desc: '''
I2C target mask number 0.
At least one bit in MASK0 must be set to 1 for ADDRESS0 to be used.
'''
}
{ bits: "20:14"
name: "ADDRESS1"
desc: "I2C target address number 1"
}
{ bits: "27:21"
name: "MASK1"
desc: "I2C target mask number 1"
desc: '''
I2C target mask number 1.
At least one bit in MASK1 must be set to 1 for ADDRESS1 to be used.
'''
}
]
}
Expand Down
14 changes: 7 additions & 7 deletions hw/ip/i2c/doc/registers.md
Original file line number Diff line number Diff line change
Expand Up @@ -540,13 +540,13 @@ I2C target address and mask pairs
{"reg": [{"name": "ADDRESS0", "bits": 7, "attr": ["rw"], "rotate": 0}, {"name": "MASK0", "bits": 7, "attr": ["rw"], "rotate": 0}, {"name": "ADDRESS1", "bits": 7, "attr": ["rw"], "rotate": 0}, {"name": "MASK1", "bits": 7, "attr": ["rw"], "rotate": 0}, {"bits": 4}], "config": {"lanes": 1, "fontsize": 10, "vspace": 80}}
```

| Bits | Type | Reset | Name | Description |
|:------:|:------:|:-------:|:---------|:----------------------------|
| 31:28 | | | | Reserved |
| 27:21 | rw | 0x0 | MASK1 | I2C target mask number 1 |
| 20:14 | rw | 0x0 | ADDRESS1 | I2C target address number 1 |
| 13:7 | rw | 0x0 | MASK0 | I2C target mask number 0 |
| 6:0 | rw | 0x0 | ADDRESS0 | I2C target address number 0 |
| Bits | Type | Reset | Name | Description |
|:------:|:------:|:-------:|:---------|:----------------------------------------------------------------------------------------------|
| 31:28 | | | | Reserved |
| 27:21 | rw | 0x0 | MASK1 | I2C target mask number 1. At least one bit in MASK1 must be set to 1 for ADDRESS1 to be used. |
| 20:14 | rw | 0x0 | ADDRESS1 | I2C target address number 1 |
| 13:7 | rw | 0x0 | MASK0 | I2C target mask number 0. At least one bit in MASK0 must be set to 1 for ADDRESS0 to be used. |
| 6:0 | rw | 0x0 | ADDRESS0 | I2C target address number 0 |

## ACQDATA
I2C target acquired data
Expand Down
4 changes: 4 additions & 0 deletions hw/ip/i2c/doc/theory_of_operation.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,10 @@ In other words, address matching is performed only for bits where the mask is "1
Thus, with the masks set to all ones (0x7F), the target device will respond to either of the two assigned unique addresses and no other.
If the mask and the assigned address both have zeros in a particular bit position, that bit will be a match regardless of the value of that bit received from the host.
Note that if, in any bit position, the mask has zero and the assigned address has one, no transaction can match and such mask/address pair is effectively disabled.

Finally, in the special case where the mask is all zeroes (0x00), then that corresponding entry is ignored and will not match.
If the user wishes to have the target respond to *all* addresses, then this can be achieved by setting mask0 and mask1 to 0x01 and setting address0 to 0x00 and address1 to 0x01.

The assigned address and mask pairs are set in registers [`TARGET_ID.ADDRESS0`](registers.md#target_id), [`TARGET_ID.MASK0`](registers.md#target_id), [`TARGET_ID.ADDRESS1`](registers.md#target_id), and [`TARGET_ID.MASK1`](registers.md#target_id).

### Acquired Formatted Data
Expand Down
6 changes: 4 additions & 2 deletions hw/ip/i2c/rtl/i2c_target_fsm.sv
Original file line number Diff line number Diff line change
Expand Up @@ -301,8 +301,10 @@ module i2c_target_fsm import i2c_pkg::*;
end

// Deserializer for a byte read from the bus on the target side
assign address0_match = ((input_byte[7:1] & target_mask0_i) == target_address0_i);
assign address1_match = ((input_byte[7:1] & target_mask1_i) == target_address1_i);
assign address0_match = ((input_byte[7:1] & target_mask0_i) == target_address0_i) &&
(target_mask0_i != '0);
assign address1_match = ((input_byte[7:1] & target_mask1_i) == target_address1_i) &&
(target_mask1_i != '0);
assign address_match = (address0_match || address1_match);

// Shift data in on positive SCL edge
Expand Down

0 comments on commit 9dc1118

Please sign in to comment.