Skip to content

i2c proxy bug 2: State machine could get stuck, then playback_bits overflows the data_bits index #497

@nathanaelhuffman

Description

@nathanaelhuffman

In PLAY_STORED_DATA, the only exit conditions on playback_scl_fedge are:

-- line 346-357
elsif playback_scl_fedge = '1' and mux_r.playback_bits < sample_r.bit_count then
    ...  -- output next bit
elsif playback_scl_fedge = '1' and mux_r.playback_bits = sample_r.bit_count and cpu_scl_in = '0' then
    ...  -- hand off
end if;

The case playback_scl_fedge = '1' and mux_r.playback_bits = sample_r.bit_count and cpu_scl_in = '1' is entirely unhandled. Since playback runs considerably faster than the CPU SCL, this is the common case: playback finishes all buffered bits while the CPU SCL is still in its high phase.

What happens: the state machine sits in PLAY_STORED_DATA as the playback counter keeps running. On the next playback_scl_redge, v.playback_bits becomes bit_count + 1. Now neither fedge condition ever fires again (playback_bits < bit_count is false; playback_bits = bit_count is false). The machine is stuck, and each subsequent playback_scl_redge increments playback_bits further. Eventually it indexes sample_r.data_bits(7) or higher — out of bounds on a unsigned(6 downto 0).

Possible Fix: when playback has caught up (mux_r.playback_bits >= sample_r.bit_count), the right trigger for handoff is the CPU's own falling edge (cpu_scl_fedge), not a playback falling edge. Add a branch:

elsif cpu_scl_fedge = '1' and mux_r.playback_bits >= sample_r.bit_count then
    v.state := ENSURE_PLAYBACK_HOLD;
    ...
end if;

This also eliminates the need to check cpu_scl_in on the playback edges for handoff: just wait for the actual CPU SCL falling edge.

Also by analysis and simulation, I haven't caught this in real hardware, but it is a class of bug totally dependent on data patterns and timing

Metadata

Metadata

Labels

No labels
No labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions