From: Luke Kenneth Casson Leighton Date: Wed, 23 Sep 2020 16:38:58 +0000 (+0100) Subject: redo litex SDCard to send out data/cmd o/i/en pins X-Git-Tag: 24jan2021_ls180~339 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=bf129c873cad40b8c5ff79acb14361dfefc5f86e;p=soc.git redo litex SDCard to send out data/cmd o/i/en pins --- diff --git a/src/soc/litex/florent/libresoc/ls180.py b/src/soc/litex/florent/libresoc/ls180.py index 4fe580ca..7a04ba5b 100644 --- a/src/soc/litex/florent/libresoc/ls180.py +++ b/src/soc/litex/florent/libresoc/ls180.py @@ -78,8 +78,12 @@ _io = [ # SDCARD0: 6 pins ("sdcard", 0, Subsignal("clk", Pins("J1")), - Subsignal("cmd", Pins("J3"), Misc("PULLMODE=UP")), - Subsignal("data", Pins("K2 K1 H2 H1"), Misc("PULLMODE=UP")), + Subsignal("cmd_i", Pins("J3"), Misc("PULLMODE=UP")), + Subsignal("cmd_o", Pins("J3"), Misc("PULLMODE=UP")), + Subsignal("cmd_oe", Pins("J3"), Misc("PULLMODE=UP")), + Subsignal("data_i", Pins("K2 K1 H2 H1"), Misc("PULLMODE=UP")), + Subsignal("data_o", Pins("K2 K1 H2 H1"), Misc("PULLMODE=UP")), + Subsignal("data_oe", Pins("K2 K1 H2 H1"), Misc("PULLMODE=UP")), Misc("SLEWRATE=FAST"), IOStandard("LVCMOS33"), ), @@ -116,16 +120,11 @@ for i in range(n_gpio): pins = ' '.join(pins) # 16 GPIOs -#_io.append( ("gpio", 0, -# Subsignal("target", Pins(pins), Misc("PULLMODE=UP")), -# IOStandard("LVCMOS33")) ) -#_io.append( ("gpio", n_gpio, Pins(pins), IOStandard("LVCMOS33")) ) _io.append( ("gpio", 0, Subsignal("i", Pins(pins), Misc("PULLMODE=UP")), Subsignal("o", Pins(pins), Misc("PULLMODE=UP")), Subsignal("oe", Pins(pins), Misc("PULLMODE=UP")), IOStandard("LVCMOS33")) ) -#_io.append( ("gpio", n_gpio, Pins(pins), IOStandard("LVCMOS33")) ) # EINT: 3 pins _io.append( ("eint", 3, Pins("E0 E1 E2"), IOStandard("LVCMOS33")) ) diff --git a/src/soc/litex/florent/ls180soc.py b/src/soc/litex/florent/ls180soc.py index 8e8b7d85..6f3a559e 100755 --- a/src/soc/litex/florent/ls180soc.py +++ b/src/soc/litex/florent/ls180soc.py @@ -2,9 +2,11 @@ import os import argparse +from functools import reduce +from operator import or_ from migen import (Signal, FSM, If, Display, Finish, NextValue, NextState, - Record) + Record, ClockSignal, wrap) from litex.build.generic_platform import Pins, Subsignal from litex.build.sim import SimPlatform @@ -46,6 +48,16 @@ SoCCSRHandler.supported_address_width.append(12) from litex.soc.interconnect.csr import CSRStorage, CSRStatus from migen.genlib.cdc import MultiReg +# Imports +from litex.soc.interconnect import wishbone +from litesdcard.phy import (SDPHY, SDPHYClocker, + SDPHYInit, SDPHYCMDW, SDPHYCMDR, + SDPHYDATAW, SDPHYDATAR, + _sdpads_layout) +from litesdcard.core import SDCore +from litesdcard.frontend.dma import SDBlock2MemDMA, SDMem2BlockDMA +from litex.build.io import SDROutput, SDRInput + class GPIOTristateASIC(Module, AutoCSR): def __init__(self, pads): @@ -68,8 +80,86 @@ class GPIOTristateASIC(Module, AutoCSR): for i in range(nbits): self.specials += MultiReg(_pads.i[i], self._in.status[i]) +# SDCard PHY IO ------------------------------------------------------- + +class SDRPad(Module): + def __init__(self, pad, name, sdpad): + clk = ClockSignal() + _o = getattr(pad, "%s_o" % name) + _oe = getattr(pad, "%s_oe" % name) + _i = getattr(pad, "%s_i" % name) + for j in range(len(_o)): + self.specials += SDROutput(clk=clk, i=sdpad.o[j], o=_o[j]) + self.specials += SDROutput(clk=clk, i=sdpad.oe, o=_oe[j]) + self.specials += SDRInput(clk=clk, i=_i[j], o=sdpad.i[j]) + + +class SDPHYIOGen(Module): + def __init__(self, clocker, sdpads, pads): + # Rst + if hasattr(pads, "rst"): + self.comb += pads.rst.eq(0) + + # Clk + self.specials += SDROutput( + clk = ClockSignal(), + i = ~clocker.clk & sdpads.clk, + o = pads.clk + ) + + # Cmd + self.submodules.sd_cmd = SDRPad(pads, "cmd", sdpads.cmd) + + # Data + self.submodules.sd_data = SDRPad(pads, "data", sdpads.data) + + +class SDPHY(Module, AutoCSR): + def __init__(self, pads, device, sys_clk_freq, + cmd_timeout=10e-3, data_timeout=10e-3): + self.card_detect = CSRStatus() # Assume SDCard is present if no cd pin. + self.comb += self.card_detect.status.eq(getattr(pads, "cd", 0)) + + self.submodules.clocker = clocker = SDPHYClocker() + self.submodules.init = init = SDPHYInit() + self.submodules.cmdw = cmdw = SDPHYCMDW() + self.submodules.cmdr = cmdr = SDPHYCMDR(sys_clk_freq, + cmd_timeout, cmdw) + self.submodules.dataw = dataw = SDPHYDATAW() + self.submodules.datar = datar = SDPHYDATAR(sys_clk_freq, + data_timeout) + + # # # + + self.sdpads = sdpads = Record(_sdpads_layout) + + # IOs + sdphy_cls = SDPHYIOGen + self.submodules.io = sdphy_cls(clocker, sdpads, pads) + + # Connect pads_out of submodules to physical pads -------------- + pl = [init, cmdw, cmdr, dataw, datar] + self.comb += [ + sdpads.clk.eq( reduce(or_, [m.pads_out.clk for m in pl])), + sdpads.cmd.oe.eq( reduce(or_, [m.pads_out.cmd.oe for m in pl])), + sdpads.cmd.o.eq( reduce(or_, [m.pads_out.cmd.o for m in pl])), + sdpads.data.oe.eq(reduce(or_, [m.pads_out.data.oe for m in pl])), + sdpads.data.o.eq( reduce(or_, [m.pads_out.data.o for m in pl])), + ] + for m in pl: + self.comb += m.pads_out.ready.eq(self.clocker.ce) -# LibreSoCSim ----------------------------------------------------------------- + # Connect physical pads to pads_in of submodules --------------- + for m in pl: + self.comb += m.pads_in.valid.eq(self.clocker.ce) + self.comb += m.pads_in.cmd.i.eq(sdpads.cmd.i) + self.comb += m.pads_in.data.i.eq(sdpads.data.i) + + + # Speed Throttling ------------------------------------------- + self.comb += clocker.stop.eq(dataw.stop | datar.stop) + +# LibreSoCSim ----------------------------------------------------------- class LibreSoCSim(SoCCore): def __init__(self, cpu="libresoc", debug=False, with_sdram=True, @@ -174,7 +264,7 @@ class LibreSoCSim(SoCCore): memtype = sdram_module.memtype, data_width = sdram_data_width, clk_freq = sdram_clk_freq) - #sdrphy_cls = HalfRateGENSDRPHY + #sdrphy_cls = HalfRateGENSDRPHY sdrphy_cls = GENSDRPHY self.submodules.sdrphy = sdrphy_cls(platform.request("sdram")) #self.submodules.sdrphy = sdrphy_cls(sdram_module, @@ -231,6 +321,38 @@ class LibreSoCSim(SoCCore): self.submodules.i2c = I2CMaster(platform.request("i2c")) self.add_csr("i2c") + # SDCard ----------------------------------------------------- + + # Emulator / Pads + sdcard_pads = self.platform.request("sdcard") + + # Core + self.submodules.sdphy = SDPHY(sdcard_pads, + self.platform.device, self.clk_freq) + self.submodules.sdcore = SDCore(self.sdphy) + self.add_csr("sdphy") + self.add_csr("sdcore") + + # Block2Mem DMA + bus = wishbone.Interface(data_width=self.bus.data_width, + adr_width=self.bus.address_width) + self.submodules.sdblock2mem = SDBlock2MemDMA(bus=bus, + endianness=self.cpu.endianness) + self.comb += self.sdcore.source.connect(self.sdblock2mem.sink) + dma_bus = self.bus if not hasattr(self, "dma_bus") else self.dma_bus + dma_bus.add_master("sdblock2mem", master=bus) + self.add_csr("sdblock2mem") + + # Mem2Block DMA + bus = wishbone.Interface(data_width=self.bus.data_width, + adr_width=self.bus.address_width) + self.submodules.sdmem2block = SDMem2BlockDMA(bus=bus, + endianness=self.cpu.endianness) + self.comb += self.sdmem2block.source.connect(self.sdcore.sink) + dma_bus = self.bus if not hasattr(self, "dma_bus") else self.dma_bus + dma_bus.add_master("sdmem2block", master=bus) + self.add_csr("sdmem2block") + # Debug --------------------------------------------------------------- if not debug: return @@ -518,7 +640,6 @@ def main(): if args.platform == 'ls180': soc = LibreSoCSim(cpu=args.cpu, debug=args.debug, platform=args.platform) - soc.add_sdcard() soc.add_spi_sdcard() builder = Builder(soc, compile_gateware = True) builder.build(run = True)