From 446819fafed27aa465506a7954219609b0eaf2a0 Mon Sep 17 00:00:00 2001 From: Larry Ruckman Date: Tue, 18 Aug 2026 15:42:04 -0700 Subject: [PATCH] fix(i2c): saturate I2cMaster timeout counter The timer field is declared as integer range 0 to TIMEOUT_C, but the WAIT_ADDR_ACK_S, WAIT_READ_DATA_S, and WAIT_WRITE_ACK_S states incremented it unconditionally. Because the timeout check compares r.timer against TIMEOUT_C, the increment evaluates TIMEOUT_C+1 one cycle before the timeout is detected, which trips a range violation in VCS simulation (SIMERR_CONSTERR_INDEXEDRANGE). Guard each increment so the counter saturates at TIMEOUT_C. The registered value is unchanged: when the guard blocks the increment, v.timer keeps its default of 0 and the timeout logic also forces 0, so the timeout error still fires on the same clock cycle as before. --- protocols/i2c/rtl/I2cMaster.vhd | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/protocols/i2c/rtl/I2cMaster.vhd b/protocols/i2c/rtl/I2cMaster.vhd index 026e84cbe0..6507eac4c5 100644 --- a/protocols/i2c/rtl/I2cMaster.vhd +++ b/protocols/i2c/rtl/I2cMaster.vhd @@ -260,7 +260,10 @@ begin when WAIT_ADDR_ACK_S => - v.timer := r.timer + 1; + -- Saturate the timer to prevent an out of range value + if (r.timer /= TIMEOUT_C) then + v.timer := r.timer + 1; + end if; if (byteCtrlOut.cmdAck = '1') then -- Master sent the command if (byteCtrlOut.ackOut = '0') then -- Slave ack'd the transfer @@ -302,7 +305,10 @@ begin when WAIT_READ_DATA_S => - v.timer := r.timer + 1; + -- Saturate the timer to prevent an out of range value + if (r.timer /= TIMEOUT_C) then + v.timer := r.timer + 1; + end if; v.byteCtrlIn.stop := r.byteCtrlIn.stop; -- Hold stop or it wont get seen v.byteCtrlIn.ackIn := r.byteCtrlIn.ackIn; -- This too @@ -331,7 +337,10 @@ begin end if; when WAIT_WRITE_ACK_S => - v.timer := r.timer + 1; + -- Saturate the timer to prevent an out of range value + if (r.timer /= TIMEOUT_C) then + v.timer := r.timer + 1; + end if; v.byteCtrlIn.stop := r.byteCtrlIn.stop; if (byteCtrlOut.cmdAck = '1') then -- Master sent the command