From 389e8aa13adba3885123b8f3b04c12345e3af243 Mon Sep 17 00:00:00 2001 From: Dave Marples Date: Tue, 14 Apr 2020 13:53:46 +0100 Subject: [PATCH] Addition of USB ACM for ECP5 --- litex_boards/platforms/colorlight_5a_75b.py | 7 +++ litex_boards/platforms/ulx3s.py | 7 +++ litex_boards/targets/README.colorlight_5a_75b | 26 ++++++++++ litex_boards/targets/README.ulx3s | 11 ++++ litex_boards/targets/colorlight_5a_75b.py | 51 +++++++++++++++---- litex_boards/targets/ulx3s.py | 18 +++++-- 6 files changed, 104 insertions(+), 16 deletions(-) create mode 100644 litex_boards/targets/README.colorlight_5a_75b create mode 100644 litex_boards/targets/README.ulx3s diff --git a/litex_boards/platforms/colorlight_5a_75b.py b/litex_boards/platforms/colorlight_5a_75b.py index 944338d..27afe03 100644 --- a/litex_boards/platforms/colorlight_5a_75b.py +++ b/litex_boards/platforms/colorlight_5a_75b.py @@ -172,6 +172,13 @@ _io_v7_0 = [ # Documented by @miek Subsignal("tx_data", Pins("T14 R12 R13 R14")), IOStandard("LVCMOS33") ), + + ("usb", 0, + Subsignal("d_p", Pins("M8")), + Subsignal("d_n", Pins("R2")), + Subsignal("pullup", Pins("P4")), + IOStandard("LVCMOS33") + ), ] # from https://github.com/miek/chubby75/blob/5a-75b-v7_pinout/5a-75b/hardware_V6.1.md diff --git a/litex_boards/platforms/ulx3s.py b/litex_boards/platforms/ulx3s.py index 20640fc..87feeb3 100644 --- a/litex_boards/platforms/ulx3s.py +++ b/litex_boards/platforms/ulx3s.py @@ -84,6 +84,13 @@ _io = [ Subsignal("n", Pins("C10")), IOStandard("LVCMOS33") ), + + ("usb", 0, + Subsignal("d_p", Pins("D15")), + Subsignal("d_n", Pins("E15")), + Subsignal("pullup", Pins("B12 C12")), + IOStandard("LVCMOS33") + ), ] # Platform ----------------------------------------------------------------------------------------- diff --git a/litex_boards/targets/README.colorlight_5a_75b b/litex_boards/targets/README.colorlight_5a_75b new file mode 100644 index 0000000..8663810 --- /dev/null +++ b/litex_boards/targets/README.colorlight_5a_75b @@ -0,0 +1,26 @@ +USB +=== +USB support has been integrated for the V7.0 this board. Supporting other +versions should be trivial and just need pinning changes. To build with +usb support just do; + +./colourlight_5a_75b.py --uart-name=usb_cdc + +To install onto the board; + +./colourlight_5a_75b.py --load + +The USB Serial connection will appear as /dev/ttyACMx, or equivalent on your OS. + +Pinning for V7.0; + +* Replace U23 with a SN74CBT3245APWR, or remove U23 and place jumper wires. + (You're basically making the ports Bi-directional). + +* Place a 15K resistor between J4 pin 2 and J4 pin 4. + +* Place a 15K resistor between J4 pin 3 and J4 pin 4. + +* Place a 1.5K resistor between J4 pin 1 and J4 pin 3. + +* Connect USB DP (Green) to J4 pin 3, USB DN (White) to J4 pin 2. diff --git a/litex_boards/targets/README.ulx3s b/litex_boards/targets/README.ulx3s new file mode 100644 index 0000000..d565499 --- /dev/null +++ b/litex_boards/targets/README.ulx3s @@ -0,0 +1,11 @@ +USB +=== +USB support has been integrated and tested for V3.0.3 this board. Revisions +higher than this should be supported. The USB connection is on US2. + +To build with usb support just do; + +./ulx3s.py --uart-name=usb_cdc + +The USB Serial connection will appear as /dev/ttyACMx, or equivalent on your OS. + diff --git a/litex_boards/targets/colorlight_5a_75b.py b/litex_boards/targets/colorlight_5a_75b.py index da89d8f..64288c9 100755 --- a/litex_boards/targets/colorlight_5a_75b.py +++ b/litex_boards/targets/colorlight_5a_75b.py @@ -48,7 +48,7 @@ from liteeth.phy.ecp5rgmii import LiteEthPHYRGMII # CRG ---------------------------------------------------------------------------------------------- class _CRG(Module): - def __init__(self, platform, sys_clk_freq, with_rst=True): + def __init__(self, platform, sys_clk_freq, with_usb_pll=False, with_rst=True): self.clock_domains.cd_sys = ClockDomain() self.clock_domains.cd_sys_ps = ClockDomain() @@ -67,22 +67,34 @@ class _CRG(Module): pll.create_clkout(self.cd_sys_ps, sys_clk_freq, phase=180) # Idealy 90° but needs to be increased. self.specials += AsyncResetSynchronizer(self.cd_sys, ~pll.locked | ~rst_n) + # USB PLL + if with_usb_pll: + self.submodules.usb_pll = usb_pll = ECP5PLL() + usb_pll.register_clkin(clk25, 25e6) + self.clock_domains.cd_usb_12 = ClockDomain() + self.clock_domains.cd_usb_48 = ClockDomain() + usb_pll.create_clkout(self.cd_usb_12, 12e6, margin=0) + usb_pll.create_clkout(self.cd_usb_48, 48e6, margin=0) + #self.comb += self.cd_usb_48.clk.eq(self.cd_sys.clk) + # SDRAM clock self.specials += DDROutput(1, 0, platform.request("sdram_clock"), ClockSignal("sys_ps")) # BaseSoC ------------------------------------------------------------------------------------------ class BaseSoC(SoCCore): - def __init__(self, revision, with_ethernet=False, with_etherbone=False, **kwargs): + def __init__(self, revision, with_ethernet=False, with_etherbone=False, sys_clk_freq=60e6, **kwargs): platform = colorlight_5a_75b.Platform(revision=revision) - sys_clk_freq = int(125e6) if with_etherbone else int(60e6) + if (with_etherbone): + sys_clk_freq = int(125e6) # SoCCore ---------------------------------------------------------------------------------- SoCCore.__init__(self, platform, clk_freq=sys_clk_freq, **kwargs) # CRG -------------------------------------------------------------------------------------- with_rst = kwargs["uart_name"] not in ["serial", "bridge"] # serial_rx shared with user_btn_n. - self.submodules.crg = _CRG(platform, sys_clk_freq, with_rst=with_rst) + with_usb_pll = kwargs.get("uart_name", None) == "usb_cdc" + self.submodules.crg = _CRG(platform, sys_clk_freq, with_usb_pll=with_usb_pll,with_rst=with_rst) # SDR SDRAM -------------------------------------------------------------------------------- if not self.integrated_main_ram_size: @@ -115,21 +127,33 @@ class BaseSoC(SoCCore): # Load --------------------------------------------------------------------------------------------- -def load(): +def load(iface="ftdi"): import os f = open("openocd.cfg", "w") - f.write( -""" -interface ftdi + if (iface == "ftdi"): + f.write( +"""adapter driver ftdi ftdi_vid_pid 0x0403 0x6011 ftdi_channel 0 ftdi_layout_init 0x0098 0x008b reset_config none -adapter_khz 25000 +adapter speed 25000 jtag newtap ecp5 tap -irlen 8 -expected-id 0x41111043 """) + elif (iface=="jlink"): + f.write("""adapter driver jlink +transport select jtag +reset_config none +telnet_port 4444 +adapter speed 10000 +jtag newtap lfe5u25 tap -irlen 8 -irmask 0xFF -ircapture 0x5 -expected-id 0x41111043 +""") + else: + print("Unrecognised jtag interface") + exit() + f.close() - os.system("openocd -f openocd.cfg -c \"transport select jtag; init; svf soc_basesoc_colorlight_5a_75b/gateware/top.svf; exit\"") + os.system("openocd -f openocd.cfg -c \"transport select jtag; init; svf -tap lfe5u25.tap -quiet -progress soc_basesoc_colorlight_5a_75b/gateware/top.svf; exit\"") exit() # Build -------------------------------------------------------------------------------------------- @@ -144,15 +168,20 @@ def main(): parser.add_argument("--with-etherbone", action="store_true", help="enable Etherbone support") parser.add_argument("--eth-phy", default=0, type=int, help="Ethernet PHY 0 or 1 (default=0)") parser.add_argument("--load", action="store_true", help="load bitstream") + parser.add_argument("--iface", default="ftdi", help="loading jtag interface") + parser.add_argument("--sys-clk-freq", default=60e6, + help="system clock frequency (default=60MHz)") + args = parser.parse_args() if args.load: - load() + load(iface=args.iface) assert not (args.with_ethernet and args.with_etherbone) soc = BaseSoC(revision=args.revision, with_ethernet = args.with_ethernet, with_etherbone = args.with_etherbone, + sys_clk_freq = args.sys_clk_freq, **soc_core_argdict(args)) builder = Builder(soc, **builder_argdict(args)) builder.build(**trellis_argdict(args)) diff --git a/litex_boards/targets/ulx3s.py b/litex_boards/targets/ulx3s.py index fa75121..eec7670 100755 --- a/litex_boards/targets/ulx3s.py +++ b/litex_boards/targets/ulx3s.py @@ -27,7 +27,7 @@ from litedram.phy import GENSDRPHY # CRG ---------------------------------------------------------------------------------------------- class _CRG(Module): - def __init__(self, platform, sys_clk_freq): + def __init__(self, platform, sys_clk_freq, with_usb_pll=False): self.clock_domains.cd_sys = ClockDomain() self.clock_domains.cd_sys_ps = ClockDomain(reset_less=True) @@ -42,10 +42,17 @@ class _CRG(Module): self.submodules.pll = pll = ECP5PLL() self.comb += pll.reset.eq(rst) pll.register_clkin(clk25, 25e6) - pll.create_clkout(self.cd_sys, sys_clk_freq) + pll.create_clkout(self.cd_sys, sys_clk_freq, margin=0) pll.create_clkout(self.cd_sys_ps, sys_clk_freq, phase=90) self.specials += AsyncResetSynchronizer(self.cd_sys, ~pll.locked | rst) + # USB PLL + if with_usb_pll: + self.clock_domains.cd_usb_12 = ClockDomain() + self.clock_domains.cd_usb_48 = ClockDomain() + pll.create_clkout(self.cd_usb_12, 12e6, margin=0) + self.comb += self.cd_usb_48.clk.eq(self.cd_sys.clk) + # SDRAM clock self.specials += DDROutput(1, 0, platform.request("sdram_clock"), ClockSignal("sys_ps")) @@ -64,7 +71,8 @@ class BaseSoC(SoCCore): SoCCore.__init__(self, platform, clk_freq=sys_clk_freq, **kwargs) # CRG -------------------------------------------------------------------------------------- - self.submodules.crg = _CRG(platform, sys_clk_freq) + with_usb_pll = kwargs.get("uart_name", None) == "usb_cdc" + self.submodules.crg = _CRG(platform, sys_clk_freq, with_usb_pll) # SDR SDRAM -------------------------------------------------------------------------------- if not self.integrated_main_ram_size: @@ -87,8 +95,8 @@ def main(): help="gateware toolchain to use, trellis (default) or diamond") parser.add_argument("--device", dest="device", default="LFE5U-45F", help="FPGA device, ULX3S can be populated with LFE5U-45F (default) or LFE5U-85F") - parser.add_argument("--sys-clk-freq", default=50e6, - help="system clock frequency (default=50MHz)") + parser.add_argument("--sys-clk-freq", default=48e6, + help="system clock frequency (default=48MHz)") parser.add_argument("--sdram-module", default="MT48LC16M16", help="SDRAM module: MT48LC16M16, AS4C32M16 or AS4C16M16 (default=MT48LC16M16)") builder_args(parser)