Skip to content

Commit

Permalink
litesdcard: fix handling LONG responses
Browse files Browse the repository at this point in the history
This commit also disables CRC checks as they fail
for some commands. This must be investigated further.

Co-authored-by: Mariusz Glebocki <[email protected]>
  • Loading branch information
2 people authored and mateusz-holenko committed Feb 28, 2020
1 parent 0beb92f commit 8908aa4
Show file tree
Hide file tree
Showing 3 changed files with 161 additions and 58 deletions.
58 changes: 8 additions & 50 deletions litesdcard/clocker.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

from litex.soc.interconnect.csr import *

from litex.soc.cores.clock import S7MMCM


class SDClockerS6(Module, AutoCSR):
def __init__(self, sys_clk_freq=50e6, max_sd_clk_freq=100e6):
Expand Down Expand Up @@ -94,55 +96,11 @@ def __init__(self, sys_clk_freq=50e6, max_sd_clk_freq=100e6):


class SDClockerS7(Module, AutoCSR):
def __init__(self, clkin=ClockSignal(), clkin_freq=100e6):
assert clkin_freq == 100e6
self.clock_domains.cd_sd = ClockDomain()
def __init__(self, sys_clk_freq=100e6, sd_clk_freq=10e6):
self.clock_domains.cd_sd = ClockDomain()
self.clock_domains.cd_sd_fb = ClockDomain()

self._mmcm_reset = CSRStorage()
self._mmcm_read = CSR()
self._mmcm_write = CSR()
self._mmcm_drdy = CSRStatus()
self._mmcm_adr = CSRStorage(7)
self._mmcm_dat_w = CSRStorage(16)
self._mmcm_dat_r = CSRStatus(16)

# # #

mmcm_locked = Signal()
mmcm_fb = Signal()
mmcm_clk0 = Signal()
mmcm_drdy = Signal()

self.specials += [
Instance("MMCME2_ADV",
p_BANDWIDTH="OPTIMIZED",
i_RST=self._mmcm_reset.storage, o_LOCKED=mmcm_locked,

# VCO
p_REF_JITTER1=0.01, p_CLKIN1_PERIOD=1e9/clkin_freq,
p_CLKFBOUT_MULT_F=32, p_CLKFBOUT_PHASE=0.000, p_DIVCLK_DIVIDE=5,
i_CLKIN1=clkin, i_CLKFBIN=mmcm_fb, o_CLKFBOUT=mmcm_fb,

# CLK0
p_CLKOUT0_DIVIDE_F=128, p_CLKOUT0_PHASE=0.000, o_CLKOUT0=mmcm_clk0,

# DRP
i_DCLK = ClockSignal(),
i_DWE = self._mmcm_write.re,
i_DEN = self._mmcm_read.re | self._mmcm_write.re,
o_DRDY = mmcm_drdy,
i_DADDR = self._mmcm_adr.storage,
i_DI = self._mmcm_dat_w.storage,
o_DO = self._mmcm_dat_r.status
),
Instance("BUFG", i_I=mmcm_clk0, o_O=self.cd_sd.clk),
]
self.sync += [
If(self._mmcm_read.re | self._mmcm_write.re,
self._mmcm_drdy.status.eq(0)
).Elif(mmcm_drdy,
self._mmcm_drdy.status.eq(1)
)
]
self.comb += self.cd_sd.rst.eq(~mmcm_locked)
self.submodules.mmcm = mmcm = S7MMCM(speedgrade=-1)
mmcm.register_clkin(ClockSignal(), sys_clk_freq)
mmcm.create_clkout(self.cd_sd, sd_clk_freq)
mmcm.expose_drp()
19 changes: 11 additions & 8 deletions litesdcard/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

class SDCore(Module, AutoCSR):
def __init__(self, phy, csr_data_width=32):
response_length = 136
self.sink = stream.Endpoint([("data", 32)])
self.source = stream.Endpoint([("data", 32)])

Expand All @@ -25,7 +26,7 @@ def __init__(self, phy, csr_data_width=32):
if csr_data_width == 8:
self.issue_cmd = CSRStorage(1)

self.response = CSRStatus(120)
self.response = CSRStatus(response_length)

self.cmdevt = CSRStatus(32)
self.dataevt = CSRStatus(32)
Expand All @@ -44,7 +45,7 @@ def __init__(self, phy, csr_data_width=32):

argument = Signal(32)
command = Signal(32)
response = Signal(120)
response = Signal(response_length)
cmdevt = Signal(32)
dataevt = Signal(32)
blocksize = Signal(16)
Expand All @@ -63,7 +64,7 @@ def __init__(self, phy, csr_data_width=32):
]

# sd to sys cdc
response_cdc = BusSynchronizer(120, "sd", "sys")
response_cdc = BusSynchronizer(response_length, "sd", "sys")
cmdevt_cdc = BusSynchronizer(32, "sd", "sys")
dataevt_cdc = BusSynchronizer(32, "sd", "sys")
self.submodules += response_cdc, cmdevt_cdc, dataevt_cdc
Expand Down Expand Up @@ -92,7 +93,7 @@ def __init__(self, phy, csr_data_width=32):
]

self.submodules.crc7inserter = ClockDomainsRenamer("sd")(CRC(9, 7, 40))
self.submodules.crc7checker = ClockDomainsRenamer("sd")(CRCChecker(9, 7, 120))
self.submodules.crc7checker = ClockDomainsRenamer("sd")(CRCChecker(9, 7, response_length))
self.submodules.crc16inserter = ClockDomainsRenamer("sd")(CRCUpstreamInserter())
self.submodules.crc16checker = ClockDomainsRenamer("sd")(CRCDownstreamChecker())

Expand Down Expand Up @@ -139,7 +140,9 @@ def __init__(self, phy, csr_data_width=32):
cmddone,
C(0, 1),
cerrtimeout,
cerrcrc_en & ~self.crc7checker.valid)),
#FIXME: Disabling CRC check, check why CRC value for CMD41 (and maybe others) is not valid and enable this.
#cerrcrc_en & ~self.crc7checker.valid)),
0)),
dataevt.eq(Cat(
datadone,
derrwrite,
Expand Down Expand Up @@ -210,7 +213,8 @@ def __init__(self, phy, csr_data_width=32):
If(waitresp == SDCARD_CTRL_RESPONSE_SHORT,
phy.sink.data.eq(5) # (5+1)*8 == 48bits
).Elif(waitresp == SDCARD_CTRL_RESPONSE_LONG,
phy.sink.data.eq(16) # (16+1)*8 == 136bits
#FIXME: Setting data to 16 results in missing byte in resposne, find out why and fix this.
phy.sink.data.eq(17) # (17+1)*8 == 144bits
),

If(phy.source.valid, # Wait for resp or timeout coming from phy
Expand All @@ -234,8 +238,7 @@ def __init__(self, phy, csr_data_width=32):
NextState("IDLE")
),
).Else(
NextValue(response,
Cat(phy.source.data, response[0:112]))
NextValue(response, Cat(phy.source.data, response[:-len(phy.source.data)]))
)
)
)
Expand Down
142 changes: 142 additions & 0 deletions litesdcard/data.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
# This file is Copyright (c) 2017-2018 Florent Kermarrec <[email protected]>
# This file is Copyright (c) 2020 Mariusz Glebocki Antmicro <www.antmicro.com>
# License: BSD
# Based on litesdcard/bist.py


from functools import reduce
from operator import xor

from migen import *

from litex.soc.interconnect import stream
from litex.soc.interconnect.csr import *

from litex.gen import *

def with_endianness(endianness, src):
if endianness == "big":
return src
else:
return reverse_bytes(src)


@ResetInserter()
class _SDDataWriter(Module):
def __init__(self, port, endianness):
self.source = source = stream.Endpoint([("data", 32)])
self.start = Signal()
self.done = Signal()

self.endianness = endianness
self.port = port

datcnt = Signal(7)

fsm = FSM(reset_state="IDLE")
self.submodules += fsm
fsm.act("IDLE",
If(self.start,
NextValue(datcnt, 0),
NextState("RUN")
)
)
fsm.act("RUN",
self.port.adr.eq(datcnt),
source.data.eq(with_endianness(self.endianness, self.port.dat_r)),
source.valid.eq(1),
source.last.eq(datcnt == (512//4 - 1)),
If(source.ready,
If(source.last,
NextState("DONE")
).Else(
NextValue(datcnt, datcnt + 1),
NextState("RUN_INC"), # One cycle for memory access
)
)
)
fsm.act("RUN_INC",
self.port.adr.eq(datcnt),
NextState("RUN"))
fsm.act("DONE",
self.done.eq(1)
)


class SDDataWriter(Module, AutoCSR):
def __init__(self, port, endianness):
self.source = source = stream.Endpoint([("data", 32)])
self.reset = CSR()
self.start = CSR()
self.done = CSRStatus()

core = _SDDataWriter(port, endianness)
self.submodules += core

self.comb += [
core.source.connect(source),
core.reset.eq(self.reset.re),
core.start.eq(self.start.re),
self.done.status.eq(core.done),
]


@ResetInserter()
class _SDDataReader(Module):
def __init__(self, port, endianness):
self.sink = sink = stream.Endpoint([("data", 32)])
self.start = Signal()
self.done = Signal()
self.errors = Signal(32)

self.endianness = endianness
self.port = port

datcnt = Signal(7)

fsm = FSM(reset_state="IDLE")
self.submodules += fsm
fsm.act("IDLE",
sink.ready.eq(1),
self.done.eq(1),
If(self.start,
NextValue(datcnt, 0),
NextValue(self.errors, 0),
NextState("RUN")
)
)
fsm.act("RUN",
sink.ready.eq(1),
self.port.adr.eq(datcnt),
self.port.dat_w.eq(with_endianness(self.endianness, sink.data)),
If(sink.valid,
self.port.we.eq(1),
NextValue(datcnt, datcnt + 1),
If(sink.last | (datcnt == (512//4 - 1)),
NextState("DONE")
)
)
)
fsm.act("DONE",
self.done.eq(1)
)


class SDDataReader(Module, AutoCSR):
def __init__(self, port, endianness):
self.sink = sink = stream.Endpoint([("data", 32)])
self.reset = CSR()
self.start = CSR()
self.done = CSRStatus()
self.errors = CSRStatus(32)

core = _SDDataReader(port, endianness)
self.submodules += core

self.comb += [
sink.connect(core.sink),
core.reset.eq(self.reset.re),
core.start.eq(self.start.re),
self.done.status.eq(core.done),
self.errors.status.eq(core.errors)
]

0 comments on commit 8908aa4

Please sign in to comment.