NXP / i3c-slave-design

MIPI I3C Basic v1.0 communication Slave source code in Verilog with BSD license to support use in sensors and other devices.
Other
104 stars 33 forks source link

Is support for "read current address" missing? #22

Closed rosholm closed 4 years ago

rosholm commented 4 years ago

I am trying to implement an EEPROM I2C read/write protocol including "read current address". Shouldn't it be possible using this I3C slave?

I'm facing two issues related to Read commands.

  1. How to identify early enough that a Read is requested so that the system can provide the data in due time, and even drive the ACK bit (which immediately follows the RnW bit).

  2. How to know when to stop fetching data in the System. When the end/length of the Read command is controlled by the master sending a NACK (and following Stop) the slave has to decide based on the ACK/NACK whether to transmit data on the following SCL clock. But according to simulations (see attached waveforms), the System has to write data (to WDATAB) so that they are available on the same rising edge of SCL which is also used to sample the value of the ACK/NACK bit. So I see no way to support "endless" Read commands without having to pre-fetch the data in the System, and thus performing reads in the System without knowing if they are requested, which can be fatal if the reads have side effects (reading/popping from a FIFO is an example).

The Read command on the I2C protocol I'm talking about can be described as follows (with an undefined number of 'dddddddda' (read data and master ACK) sequences with the Master driving NACK on the last read byte): SDDDDDDDWaAAAAAAAAaAAAAAAAAaSDDDDDDDRaddddddddaP S is (re)start, D is device address bits, W is the R/W bit driven LOW, R is the R/W bit drive HIGH, a is ack driven by the appropriate source (master or slave), A is the address bits, d is data bits driven by the appropriate source (master or slave) - slave in the read command here, P is the stop bit

I'm missing an indication that a read is requested (when the R bit is identified). In the case of a write I can use the dma_req_fb signal or the RXPEND status bit to identify the operation. But it is only the dma_req_tb signal or TXNOTFULL bit that can be used to indicate a read is requested (as far as I can tell - please correct me if i'm wrong). However, the dma_req_tb signal is asserted by default, so it cannot be used to indicate/trigger a read request (of the first byte). A solution would be to fill the to-FIFO with data from address A (current address) whenever a Start is identified - using irq. This will, however, lead to a lot of unwanted pre-fetching of data in the system, since we don't know if it is a read or a write, or even if this device is addressed. Waiting for a match (using irq - any other way to do it?) will be too late to go fetch data.

By modifying the IP (routing out internal signals - no modification of the behavior of the IP) there is a solution to the first issue (when to begin the Read operation, i.e. fetch data in the System): The was_read signal inside i3c_sdr_slave_engine.v could be used for indicating a read is requested, but it needs to be qualified by a match signal in order not to issue a System read when reads to other devices are requested.

But I don't see any way to prevent having to pre-fetch data since data has to be ready on the rising edge of SCL when the (N)ACK bit from the Master is sampled. The first waveform shows data being written to WDATAB too late, thus tb_data_valid is de-asserted. AckReadTimingFail The second waveform shows data being written just in time (one PCLK cycle earlier than in the failing example above), thus tb_data_valid stays asserted. As can be seen from the waveform, data has to be written before the rising edge of SCL which samples the (N)ACK bit and consequently the (N)ACK bit cannot be used to trigger the fetching of data in the System. AckReadTimingPass

Am I missing something?

Thanks

pkimelman-nxp commented 4 years ago

I am trying to implement an EEPROM I2C read/write protocol including "read current address". Shouldn't it be possible using this I3C slave?

NXP: Yes, of course it should, but only if you are trying to do what is possible for I3C.

I'm facing two issues related to Read commands.

  1. How to identify early enough that a Read is requested so that the system can provide the data in due time, and even drive the ACK bit (which immediately follows the RnW bit).

NXP: Is this a software based scheme (e.g. APB) or Autonomous? That can affect how much time you need along with how fast your local clock is. NXP: I3C has a a GETMXDS scheme to tell the Master that you need more time between Write and Read. So, instead of a back to back Write then read, it can add some delay (delay time or message a different slave in between). That provides a natural method vs. clock stalling in i2c, assuming your protocol is write then read.

1.

  1. How to know when to stop fetching data in the System. When the end/length of the Read command is controlled by the master sending a NACK (and following Stop) the slave has to decide based on the ACK/NACK whether to transmit data on the following SCL clock. But according to simulations (see attached waveforms), the System has to write data (to WDATAB) so that they are available on the same rising edge of SCL which is also used to sample the value of the ACK/NACK bit. So I see no way to support "endless" Read commands without having to pre-fetch the data in the System, and thus performing reads in the System without knowing if they are requested, which can be fatal if the reads have side effects (reading/popping from a FIFO is an example).

NXP: The normal I3C model is that the Slave ends the read when it is done. The Master can terminate the read on each 9th bit, but the normal is that the Slave returns as much data as is wanted. NXP: So, it is assumed you will use WDATAB and WDATABE for the last byte. NXP: You do know they are going to read if they follow the normal protocol model. The normal protocol looks like: NXP: Write: S_or_Sr, Addr/W, reg_addr, data1, data2, data3, … dataN, Sr_or_P NXP: Read: S_or_Sr, Addr/W, reg_addr, Sr, Addr/R, , Sr_or_P

NXP: What you see is that Read always precedes with write of exactly 1 value - the register_address. In some systems with >256 regs, it would be 2 bytes to form reg_addr, but that would be the same for write and read, such that write always has DATA after the address, so cannot be a read. So, as soon as you see only one value in the RX_FIFO, you know it must be a read. NXP: How you know how much they want to read is a different matter. The preferred model is more like SMBus where it tells you how many bytes to read or it is in the nature of the register address. Arbitrary termination is not a preferred method for the reasons you note.

NXP: As a general rule, it is suggested that you at least give the option of a more I3C friendly protocol. But, otherwise you can use GETMXDS for more time and/or a faster PCLK.