Skip to content

HS400-DS: CRC status token times out at ckspd==1 #27

Description

@yoxcu

Setup:

  • eMMC HS400-DS, 8-bit DDR, OPT_SERDES, OPT_CRCTOKEN=1, i_cfg_expect_ack=1
  • 100 MHz controller clock, SanDisk iNAND 7550
  • the code below is unmodified upstream, identical in master (rtl/sdtxframe.v) and dev
    (rtl/sdio/sdtxframe.v), same line numbers

Every multi-block DMA write at ckspd==1 aborts within about 2 ms. sd_cmd reads 0x0501930c,
so bit24 dma_error is set and bit23 r_ecode is 0, i.e. ercode 2'b10, a timeout rather than
a NAK. CMD13 afterwards shows the card in rcv with no error bits. The same writes work at
ckspd==0.

The card is acking normally. ILA on i_ds shows exactly 5 DS posedges after the block and then
a hold, which is the 5-bit status token and matches atok_sreg self-stopping after 5 shifts of
00101. i_dma_err and i_cmd_err are 0 in every sample of the window, so i_tx_err is the
only term that can satisfy the abort equation in sdaxil.v.

We probed the delay from tx_valid falling (the event that reloads r_timeout) to i_crcack.
It is 15 controller clocks at ckspd==1 and 9 at ckspd==0. r_timeout (:135) reloads to 15
(:939) and errors at r_timeout <= 1 (:978), so the window is 14, and 100 MHz misses it by
one clock.

In HS400-DS the token rides the card's DS strobe, so besides N_CRC and the 5 token bits the
host also pays the clock-out/DS-in round trip and the two-flop DS to i_clk sync in
sdfrontend. Only the card-clock part of that scales: at ckspd==1 one i_ckstb is one card
clock, at ckspd==0 it is two. We have only measured those two speeds.

Separately, at :978 the timeout is scored against r_ackd, but r_ackd only latches on the
next edge (:968). If the token lands on the cycle the timeout expires, i_crcack is already
high at the input and the error still wins.

Our fix, if the shape looks right we can send a PR:

  • widen r_timeout to [5:0] and reload (i_cfg_expect_ack) ? CRCTOKEN_TIMEOUT : 6'd15, with
    CRCTOKEN_TIMEOUT a parameter defaulting to 63, so only the expect-ack wait lengthens and
    o_done's minimum quiet window is unchanged
  • add && !i_crcack && !i_crcnak at :978 so a same-cycle token wins

100 MHz writes have worked since, and nothing gets slower because r_done still fires on the
ack. We also have a small testbench that drives sdtxframe through a 512 B block at ckspd==1
and sweeps the ack arrival time. Against unmodified upstream it accepts an ack at 14 controller
clocks and rejects 15. Happy to post it.

Is 15 i_ckstb meant to be a fixed budget, or should it scale with i_cfg_spd? A DS-strobed
token seems to cost more than the SDR path it was sized for, and it is invisible at every speed
except ckspd==1.

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions