[Cryptech-Commits] [core/i2c] 01/01: fix i2c read buffer overrun

git at cryptech.is git at cryptech.is
Wed Sep 3 14:08:55 UTC 2014


This is an automated email from the git hooks/post-receive script.

paul at psgd.org pushed a commit to branch master
in repository core/i2c.

commit a768072bbe3ea9762ee3325ffb5c42c3156e7859
Author: Paul Selkirk <pselkirk at isc.org>
Date:   Wed Sep 3 10:07:59 2014 -0400

    fix i2c read buffer overrun
    
    If a client requests data beyond the end of the coretest response,
    i2c_core could wait forever for txd_syn to be asserted, locking up the
    system. The current solution is to assume that data will be available
    by the time the client sends the READ_CMD and then issues the i2c read
    request; if no data is available, i2c_core returns 0x00. Given the
    relative speeds of the i2c bus and the FPGA, this seems justifiable,
    but it could use more scrutiny.
---
 src/rtl/i2c_core.v | 17 ++++++-----------
 1 file changed, 6 insertions(+), 11 deletions(-)

diff --git a/src/rtl/i2c_core.v b/src/rtl/i2c_core.v
index 3e2772a..a026545 100644
--- a/src/rtl/i2c_core.v
+++ b/src/rtl/i2c_core.v
@@ -175,14 +175,12 @@ module i2c_core (
 	   I2C_nstate = ((SDA_cstate == SDA_FALL) && (SCL_cstate == SCL_HIGH)) ? I2C_RESTART : // repeated start
 			((I2C_bitcnt > 4'h7) && (SCL_cstate == SCL_FALL)) ? I2C_RXD_SYN : I2C_WR_DATA;
 	end
-	// vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
 	I2C_RXD_SYN: begin // put data on the coretest bus
 	   I2C_nstate = I2C_RXD_ACK;
 	end
 	I2C_RXD_ACK: begin // wait for coretest ack
            I2C_nstate = rxd_ack ? I2C_ACK_WR : I2C_RXD_ACK;
 	end
-	// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 	I2C_ACK_WR: begin // trigger the ack response (pull SDA low until next falling edge)
 	   // and stay in this state until the next falling edge of SCL
 	   I2C_nstate = (SCL_cstate == SCL_FALL) ? I2C_END_WR : I2C_ACK_WR;
@@ -192,14 +190,15 @@ module i2c_core (
 	end
 
 	// read branch
-	// vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
-	I2C_TXD_SYN: begin // get data from the coretest bus
-           I2C_nstate = txd_syn ? I2C_TXD_ACK : I2C_TXD_SYN;
+	I2C_TXD_SYN: begin // get data from the coretest bus 
+	   // if data isn't available (txd_syn isn't asserted) by the time we
+	   // get to this state, it probably never will be, so skip it
+           I2C_nstate = txd_syn ? I2C_TXD_ACK : I2C_RD_DATA;
 	end
 	I2C_TXD_ACK: begin // send coretest ack
+	   // hold ack high until syn is lowered
 	   I2C_nstate = txd_syn ? I2C_TXD_ACK : I2C_RD_DATA;
 	end
-	// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 	I2C_RD_DATA: begin // 8 bits to get the read data
 	   I2C_nstate = ((SDA_cstate == SDA_FALL) && (SCL_cstate == SCL_HIGH)) ? I2C_RESTART : // repeated start
 			((I2C_bitcnt > 4'h7) && (SCL_cstate == SCL_FALL)) ? I2C_ACK_RD : I2C_RD_DATA;
@@ -300,8 +299,7 @@ module i2c_core (
 	      I2C_daddr <= I2C_daddr;
 	      I2C_rdata <= I2C_rdata;
 	   end // case: I2C_WR_DATA
-	   // vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
-	   I2C_RXD_SYN: begin // put data on the coretest bus
+	   I2C_RXD_SYN: begin // put data on the coretest bus and raise syn
               rxd_syn_reg <= 1;
 	   end
 	   I2C_RXD_ACK: begin // wait for coretest ack
@@ -310,7 +308,6 @@ module i2c_core (
 		   rxd_syn_reg <= 0;
 		end
 	   end
-	   // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 	   I2C_ACK_WR: begin
 	      SDA_pd <= 1'b1;  // active pull down ACK
 	      I2C_daddr <= I2C_daddr;
@@ -327,7 +324,6 @@ module i2c_core (
 	   end
 
 	   // read branch
-	   // vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
 	   I2C_TXD_SYN: begin // get data from the coretest bus
               if (txd_syn)
 		begin
@@ -341,7 +337,6 @@ module i2c_core (
                    txd_ack_reg <= 0;
 		end
 	   end
-	   // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 	   I2C_RD_DATA: begin // shift out data on falling edges of clock
 	      SDA_pd <= I2C_rdata[7] ? 1'b0 : 1'b1;
 	      if( SCL_cstate == SCL_RISE ) begin



More information about the Commits mailing list