Merge pull request #125 from daveshah1/trellis_sdram

ecp5 soc hat wip
This commit is contained in:
enjoy-digital 2018-11-12 08:11:57 +01:00 committed by GitHub
commit 1be6762dfe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 315 additions and 19 deletions

View File

@ -34,10 +34,14 @@ _io = [
Subsignal("cke", Pins("F20")),
Subsignal("ba", Pins("P19 N20")),
Subsignal("dm", Pins("U19 E20")),
IOStandard("LVCMOS33")
IOStandard("LVCMOS33"), Misc("SLEWRATE=FAST")
),
("wifi_gpio0", 0, Pins("L2"), IOStandard("LVCMOS33")),
("ext0p", 0, Pins("B11"), IOStandard("LVCMOS33")),
("ext1p", 0, Pins("A10"), IOStandard("LVCMOS33")),
]

View File

@ -0,0 +1,152 @@
# This file is Copyright (c) 2017 Serge 'q3k' Bazanski <serge@bazanski.pl>
# License: BSD
from litex.build.generic_platform import *
from litex.build.lattice import LatticePlatform
from litex.build.lattice.programmer import LatticeProgrammer
_io = [
("clk100", 0, Pins("P3"), IOStandard("LVDS")),
("rst_n", 0, Pins("T1"), IOStandard("LVCMOS33")),
("user_led", 0, Pins("E16"), IOStandard("LVCMOS25")),
("user_led", 1, Pins("D17"), IOStandard("LVCMOS25")),
("user_led", 2, Pins("D18"), IOStandard("LVCMOS25")),
("user_led", 3, Pins("E18"), IOStandard("LVCMOS25")),
("user_led", 4, Pins("F17"), IOStandard("LVCMOS25")),
("user_led", 5, Pins("F18"), IOStandard("LVCMOS25")),
("user_led", 6, Pins("E17"), IOStandard("LVCMOS25")),
("user_led", 7, Pins("F16"), IOStandard("LVCMOS25")),
("user_dip_btn", 0, Pins("H2"), IOStandard("LVCMOS15")),
("user_dip_btn", 1, Pins("K3"), IOStandard("LVCMOS15")),
("user_dip_btn", 2, Pins("G3"), IOStandard("LVCMOS15")),
("user_dip_btn", 3, Pins("F2"), IOStandard("LVCMOS15")),
("user_dip_btn", 4, Pins("J18"), IOStandard("LVCMOS25")),
("user_dip_btn", 5, Pins("K18"), IOStandard("LVCMOS25")),
("user_dip_btn", 6, Pins("K19"), IOStandard("LVCMOS25")),
("user_dip_btn", 7, Pins("K20"), IOStandard("LVCMOS25")),
("serial", 0,
Subsignal("rx", Pins("C11"), IOStandard("LVCMOS33")),
Subsignal("tx", Pins("A11"), IOStandard("LVCMOS33")),
),
("sdram_clock", 0, Pins("E14"), IOStandard("LVCMOS33")),
("sdram", 0,
Subsignal("a", Pins("C6 E15 A16 B16 D15 C15 B15 E12 D12 B10 C7 A9 C10")),
Subsignal("dq", Pins("B19 B12 B9 E6 D6 E7 D7 B11 C14 A14 E13 D13 C13 B13 A13 A12")),
Subsignal("we_n", Pins("E9")),
Subsignal("ras_n", Pins("B8")),
Subsignal("cas_n", Pins("D9")),
Subsignal("cs_n", Pins("C8")),
Subsignal("cke", Pins("D11")),
Subsignal("ba", Pins("D8 E8")),
Subsignal("dm", Pins("B6 D14")),
IOStandard("LVCMOS33"), Misc("SLEWRATE=FAST")
),
("eth_clocks", 0,
Subsignal("tx", Pins("P19")),
Subsignal("rx", Pins("L20")),
IOStandard("LVCMOS25")
),
("eth", 0,
Subsignal("rst_n", Pins("U17")),
Subsignal("mdio", Pins("U18")),
Subsignal("mdc", Pins("T18")),
Subsignal("rx_ctl", Pins("U19")),
Subsignal("rx_data", Pins("T20 U20 T19 R18")),
Subsignal("tx_ctl", Pins("R20")),
Subsignal("tx_data", Pins("N19 N20 P18 P20")),
IOStandard("LVCMOS25")
),
("eth_clocks", 1,
Subsignal("tx", Pins("C20")),
Subsignal("rx", Pins("J19")),
IOStandard("LVCMOS25")
),
("eth", 1,
Subsignal("rst_n", Pins("F20")),
Subsignal("mdio", Pins("H20")),
Subsignal("mdc", Pins("G19")),
Subsignal("rx_ctl", Pins("F19")),
Subsignal("rx_data", Pins("G18 G16 H18 H17")),
Subsignal("tx_ctl", Pins("E19")),
Subsignal("tx_data", Pins("J17 J16 D19 D20")),
IOStandard("LVCMOS25")
),
]
class Platform(LatticePlatform):
default_clk_name = "clk100"
default_clk_period = 10
def __init__(self, **kwargs):
LatticePlatform.__init__(self, "LFE5UM5G-45F-8BG381C", _io, **kwargs)
def do_finalize(self, fragment):
LatticePlatform.do_finalize(self, fragment)
try:
self.add_period_constraint(self.lookup_request("eth_clocks", 0).rx, 8.0)
except ConstraintError:
pass
try:
self.add_period_constraint(self.lookup_request("eth_clocks", 1).rx, 8.0)
except ConstraintError:
pass
def create_programmer(self):
_xcf_template = """
<?xml version='1.0' encoding='utf-8' ?>
<!DOCTYPE ispXCF SYSTEM "IspXCF.dtd" >
<ispXCF version="3.4.1">
<Comment></Comment>
<Chain>
<Comm>JTAG</Comm>
<Device>
<SelectedProg value="TRUE"/>
<Pos>1</Pos>
<Vendor>Lattice</Vendor>
<Family>ECP5UM5G</Family>
<Name>LFE5UM5G-45F</Name>
<IDCode>0x81112043</IDCode>
<File>{bitstream_file}</File>
<Operation>Fast Program</Operation>
</Device>
<Device>
<SelectedProg value="FALSE"/>
<Pos>2</Pos>
<Vendor>Lattice</Vendor>
<Family>ispCLOCK</Family>
<Name>ispPAC-CLK5406D</Name>
<IDCode>0x00191043</IDCode>
<Operation>Erase,Program,Verify</Operation>
<Bypass>
<InstrLen>8</InstrLen>
<InstrVal>11111111</InstrVal>
<BScanLen>1</BScanLen>
<BScanVal>0</BScanVal>
</Bypass>
</Device>
</Chain>
<ProjectOptions>
<Program>SEQUENTIAL</Program>
<Process>ENTIRED CHAIN</Process>
<OperationOverride>No Override</OperationOverride>
<StartTAP>TLR</StartTAP>
<EndTAP>TLR</EndTAP>
<VerifyUsercode value="FALSE"/>
</ProjectOptions>
<CableOptions>
<CableName>USB2</CableName>
<PortAdd>FTUSB-0</PortAdd>
<USBID>LATTICE ECP5_5G VERSA BOARD A Location 0000 Serial Lattice ECP5_5G VERSA Board A</USBID>
</CableOptions>
</ispXCF>
"""
return LatticeProgrammer(_xcf_template)

View File

@ -26,38 +26,65 @@ class _CRG(Module):
rst = platform.request("rst")
# sys_clk
self.comb += self.cd_sys.clk.eq(clk25)
# FIXME: AsyncResetSynchronizer needs FD1S3BX support.
#self.specials += AsyncResetSynchronizer(self.cd_sys, rst)
self.comb += self.cd_sys.rst.eq(rst)
self.comb += self.cd_sys_ps.rst.eq(rst)
# sys_clk phase shifted (for sdram)
sdram_ps_clk = self.cd_sys.clk
# FIXME: phase shift with luts, needs PLL support.
sdram_ps_luts = 5
for i in range(sdram_ps_luts):
new_sdram_ps_clk = Signal()
self.specials += Instance("LUT4",
p_INIT=2,
i_A=sdram_ps_clk,
i_B=0,
i_C=0,
i_D=0,
o_Z=new_sdram_ps_clk)
sdram_ps_clk = new_sdram_ps_clk
sys_clk = Signal()
sdram_ps_clk = Signal()
self.specials += Instance(
"EHXPLLL",
i_CLKI=clk25,
i_CLKFB=sys_clk,
i_PHASESEL1=0,
i_PHASESEL0=0,
i_PHASEDIR=0,
i_PHASESTEP=0,
i_PHASELOADREG=0,
i_STDBY=0,
i_PLLWAKESYNC=0,
i_RST=0,
i_ENCLKOP=0,
i_ENCLKOS=0,
o_CLKOP=sys_clk,
o_CLKOS=sdram_ps_clk,
p_CLKOS_FPHASE=2,
p_CLKOS_CPHASE=15,
p_CLKOP_FPHASE=0,
p_CLKOP_CPHASE=12,
p_PLL_LOCK_MODE=0,
p_OUTDIVIDER_MUXB="DIVB",
p_CLKOS_ENABLE="ENABLED",
p_CLKOP_ENABLE="ENABLED",
p_CLKOS_DIV=13,
p_CLKOP_DIV=13,
p_CLKFB_DIV=2,
p_CLKI_DIV=1,
p_FEEDBK_PATH="CLKOP",
attr=[("ICP_CURRENT", "6"), ("LPF_RESISTOR", "16"), ("MFG_ENABLE_FILTEROPAMP", "1"), ("MFG_GMCREF_SEL", "2")]
)
self.comb += self.cd_sys.clk.eq(sys_clk)
self.comb += self.cd_sys_ps.clk.eq(sdram_ps_clk)
sdram_clock = platform.request("sdram_clock")
self.comb += sdram_clock.eq(sdram_ps_clk)
self.comb += sdram_clock.eq(sys_clk)
# Stop ESP32 from resetting FPGA
wifi_gpio0 = platform.request("wifi_gpio0")
self.comb += wifi_gpio0.eq(1)
ext0p = platform.request("ext0p")
self.comb += ext0p.eq(sdram_ps_clk)
ext1p = platform.request("ext1p")
self.comb += ext1p.eq(self.cd_sys.clk)
class BaseSoC(SoCSDRAM):
def __init__(self, **kwargs):
platform = ulx3s.Platform(toolchain="prjtrellis")
sys_clk_freq = int(25e6)
sys_clk_freq = int(50e6)
SoCSDRAM.__init__(self, platform, clk_freq=sys_clk_freq,
l2_size=32,
integrated_rom_size=0x8000,

View File

@ -0,0 +1,113 @@
#!/usr/bin/env python3
import argparse
from migen import *
from migen.genlib.resetsync import AsyncResetSynchronizer
from litex.boards.platforms import versaecp55g_sdram
from litex.soc.integration.soc_sdram import *
from litex.soc.integration.builder import *
from litedram.modules import AS4C32M16
from litedram.phy import GENSDRPHY
class _CRG(Module):
def __init__(self, platform):
self.clock_domains.cd_sys = ClockDomain()
self.clock_domains.cd_sys_ps = ClockDomain()
# # #
clk100 = platform.request("clk100")
rst_n = platform.request("rst_n")
rst = Signal()
self.comb += rst.eq(~rst_n)
# sys_clk
# FIXME: AsyncResetSynchronizer needs FD1S3BX support.
#self.specials += AsyncResetSynchronizer(self.cd_sys, rst)
self.comb += self.cd_sys.rst.eq(rst)
self.comb += self.cd_sys_ps.rst.eq(rst)
sys_clk = Signal()
sdram_ps_clk = Signal()
lock = Signal()
self.specials += Instance(
"EHXPLLL",
i_CLKI=clk100,
i_CLKFB=sys_clk,
i_PHASESEL1=0,
i_PHASESEL0=0,
i_PHASEDIR=0,
i_PHASESTEP=0,
i_PHASELOADREG=0,
i_STDBY=0,
i_PLLWAKESYNC=0,
i_RST=0,
i_ENCLKOP=0,
i_ENCLKOS=0,
o_CLKOP=sys_clk,
o_CLKOS=sdram_ps_clk,
o_LOCK=lock,
p_CLKOS_FPHASE=0,
p_CLKOS_CPHASE=17,
p_CLKOP_FPHASE=0,
p_CLKOP_CPHASE=11,
p_PLL_LOCK_MODE=0,
p_OUTDIVIDER_MUXB="DIVB",
p_OUTDIVIDER_MUXA="DIVA",
p_CLKOS_ENABLE="ENABLED",
p_CLKOP_ENABLE="ENABLED",
p_CLKOS_DIV=12,
p_CLKOP_DIV=12,
p_CLKFB_DIV=1,
p_CLKI_DIV=2,
p_FEEDBK_PATH="CLKOP",
attr=[("ICP_CURRENT", "12"), ("LPF_RESISTOR", "8"), ("MFG_ENABLE_FILTEROPAMP", "1"), ("MFG_GMCREF_SEL", "2")]
)
self.comb += self.cd_sys.clk.eq(sys_clk)
self.comb += self.cd_sys_ps.clk.eq(sdram_ps_clk)
sdram_clock = platform.request("sdram_clock")
self.comb += sdram_clock.eq(sdram_ps_clk)
led0 = platform.request("user_led", 0)
self.comb += led0.eq(~lock)
class BaseSoC(SoCSDRAM):
def __init__(self, **kwargs):
platform = versaecp55g_sdram.Platform(toolchain="prjtrellis")
sys_clk_freq = int(50e6)
SoCSDRAM.__init__(self, platform, clk_freq=sys_clk_freq,
l2_size=32,
integrated_rom_size=0x8000,
**kwargs)
self.submodules.crg = _CRG(platform)
if not self.integrated_main_ram_size:
self.submodules.sdrphy = GENSDRPHY(platform.request("sdram"))
sdram_module = AS4C32M16(sys_clk_freq, "1:1")
self.register_sdram(self.sdrphy,
sdram_module.geom_settings,
sdram_module.timing_settings)
def main():
parser = argparse.ArgumentParser(description="LiteX SoC port to the ECP5 Versa board with SDRAM hat")
builder_args(parser)
soc_sdram_args(parser)
args = parser.parse_args()
soc = BaseSoC(**soc_sdram_argdict(args))
builder = Builder(soc, **builder_argdict(args))
builder.build()
if __name__ == "__main__":
main()

View File

@ -33,7 +33,7 @@ def _format_constraint(c):
elif isinstance(c, IOStandard):
return ("IOBUF PORT ", " IO_TYPE=" + c.name)
elif isinstance(c, Misc):
return c.misc
return ("IOBUF PORT ", " " + c.misc)
def _format_lpf(signame, pin, others, resname):