In PLAY_STORED_DATA, the playback_scl_redge branch transitions to ENSURE_PLAYBACK_HOLD when v.playback_bits = sample_r.bit_count and cpu_scl_in = '1':
-- line 335-345
if playback_scl_redge = '1' then
v.playback_bits := mux_r.playback_bits + 1;
if v.playback_bits = sample_r.bit_count and cpu_scl_in = '1' then
v.state := ENSURE_PLAYBACK_HOLD;
...
v.dimm_sda_oe := not cpu_sda_in; -- <--maybe problem
end if;
mux_r.dimm_sda_oe changes in the cycle after the rising playback SCL edge — but playback_r.scl_out will still be '1' (SCL is high). Changing SDA while SCL is high is a start/stop condition to any I2C target watching the bus. The same class of bug possibly exists in the corresponding branch at lines 349–357 (the fedge branch with cpu_scl_in = '0' is fine; the redge branch is not).
Possible fix:
only transition to ENSURE_PLAYBACK_HOLD on playback_scl_fedge branches — never on playback_scl_redge. If cpu_scl_in = '1' on the rising edge, just let the playback counter run to the next falling edge and re-evaluate. The ENSURE_PLAYBACK_HOLD hold timer gives the glitch margin; you don't need to also move the transition to the rising edge.
Note that this is by analysis and sim only, I haven't managed to capture this bug actually occurring in hw, but that doesn't mean it can't or doesn't!
In
PLAY_STORED_DATA, theplayback_scl_redgebranch transitions toENSURE_PLAYBACK_HOLDwhenv.playback_bits = sample_r.bit_countandcpu_scl_in = '1':mux_r.dimm_sda_oechanges in the cycle after the rising playback SCL edge — butplayback_r.scl_outwill still be '1' (SCL is high). Changing SDA while SCL is high is a start/stop condition to any I2C target watching the bus. The same class of bug possibly exists in the corresponding branch at lines 349–357 (the fedge branch withcpu_scl_in = '0'is fine; the redge branch is not).Possible fix:
only transition to
ENSURE_PLAYBACK_HOLDonplayback_scl_fedgebranches — never onplayback_scl_redge. Ifcpu_scl_in = '1'on the rising edge, just let the playback counter run to the next falling edge and re-evaluate. TheENSURE_PLAYBACK_HOLDhold timer gives the glitch margin; you don't need to also move the transition to the rising edge.Note that this is by analysis and sim only, I haven't managed to capture this bug actually occurring in hw, but that doesn't mean it can't or doesn't!