c4m iopad integration working
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Thu, 24 Sep 2020 19:39:13 +0000 (20:39 +0100)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Thu, 24 Sep 2020 19:39:21 +0000 (20:39 +0100)
src/soc/debug/jtag.py
src/soc/litex/florent/libresoc/core.py
src/soc/litex/florent/libresoc/ls180.py
src/soc/litex/florent/ls180soc.py

index b83f993e8dc1e60e5fdaa0f56599a6a1b37aa4ce..b1091dac28e31765bdf028191e68bb791894cbed 100644 (file)
@@ -14,10 +14,10 @@ iotypes = {'-': IOType.In,
            '+': IOType.Out,
            '*': IOType.InTriOut}
 
+# TODO: move to suitable location
+class Pins:
 
-class JTAG(DMITAP):
     def __init__(self):
-        super().__init__(ir_width=4)
 
         # sigh this needs to come from pinmux.
         gpios = []
@@ -25,15 +25,31 @@ class JTAG(DMITAP):
             gpios.append("gpio%d*" % i)
         self.io_names = {'serial': ['tx+', 'rx-'], 'gpio': gpios}
 
+    def __iter__(self):
         # start parsing io_names and create IOConn Records
-        self.ios = []
         for fn, pins in self.io_names.items():
             for pin in pins:
                 # decode the pin name and determine the c4m jtag io type
                 name, pin_type = pin[:-1], pin[-1]
                 iotype = iotypes[pin_type]
                 pin_name = "%s_%s" % (fn, name)
-                self.ios.append(self.add_io(iotype=iotype, name=pin_name))
+                yield (fn, name, iotype, pin_name)
+
+class JTAG(DMITAP, Pins):
+    def __init__(self):
+        DMITAP.__init__(self, ir_width=4)
+        Pins.__init__(self)
+
+        # sigh this needs to come from pinmux.
+        gpios = []
+        for i in range(16):
+            gpios.append("gpio%d*" % i)
+        self.io_names = {'serial': ['tx+', 'rx-'], 'gpio': gpios}
+
+        # start parsing io_names and create IOConn Records
+        self.ios = []
+        for fn, pin, iotype, pin_name in list(self):
+            self.ios.append(self.add_io(iotype=iotype, name=pin_name))
 
         # this is redundant.  or maybe part of testing, i don't know.
         self.sr = self.add_shiftreg(ircode=4, length=3)
index a082f72bb983bb7379b0ad21f278ef1d0e4edf76..c366961a5e7548ca22b139609d5ce3842379889c 100644 (file)
@@ -5,6 +5,13 @@ from migen import ClockSignal, ResetSignal, Signal, Instance, Cat
 from litex.soc.interconnect import wishbone as wb
 from litex.soc.cores.cpu import CPU
 
+from soc.debug.jtag import Pins # TODO move to suitable location
+from c4m.nmigen.jtag.tap import IOType
+
+from libresoc.ls180io import make_uart, make_gpio
+from litex.build.generic_platform import ConstraintManager
+
+
 CPU_VARIANTS = ["standard", "standard32", "standardjtag", "ls180"]
 
 
@@ -28,6 +35,35 @@ def make_wb_slave(prefix, obj):
     return res
 
 
+def make_jtag_ioconn(res, pin, cpupads, iopads):
+    (fn, pin, iotype, pin_name) = pin
+    #serial_tx__core__o, serial_rx__pad__i,
+    print ("cpupads", cpupads)
+    print ("iopads", iopads)
+    print ("pin", fn, pin, iotype, pin_name)
+    cpu = cpupads[fn]
+    io = iopads[fn]
+    sigs = []
+
+    if iotype == IOType.Out:
+        # output from the pad is routed through C4M JTAG and so
+        # is an *INPUT* into core.  ls180soc connects this to "real" peripheral
+        res['i_%s_%s_core__o' % (fn, pin)] = getattr(cpu, pin)
+        res['o_%s_%s_pad__o' % (fn, pin)] = getattr(io, pin)
+
+    elif iotype == IOType.In:
+        # input to the pad is routed through C4M JTAG and so
+        # is an *OUTPUT* into core.  ls180soc connects this to "real" peripheral
+        res['o_%s_%s_core__i' % (fn, pin)] = getattr(cpu, pin)
+        res['i_%s_%s_pad__i' % (fn, pin)] = getattr(io, pin)
+
+    if iotype in (IOType.In, IOType.InTriOut):
+        sigs.append(("i", 1))
+    if iotype in (IOType.Out, IOType.TriOut, IOType.InTriOut):
+        sigs.append(("o", 1))
+    if iotype in (IOType.TriOut, IOType.InTriOut):
+        sigs.append(("oe", 1))
+
 class LibreSoC(CPU):
     name                 = "libre_soc"
     human_name           = "Libre-SoC"
@@ -148,6 +184,24 @@ class LibreSoC(CPU):
         if jtag_en:
             self.cpu_params.update(make_wb_bus("jtag_wb", jtag_wb, simple=True))
 
+        # urr yuk.  have to expose iopads / pins from core to litex
+        # then back again.  cut _some_ of that out by connecting
+        self.cpuresources = (make_uart('serial', 0),
+                             make_gpio('gpio', 0, 16))
+        self.padresources = (make_uart('serial', 0),
+                             make_gpio('gpio', 0, 16))
+        self.cpu_cm = ConstraintManager(self.cpuresources, [])
+        self.pad_cm = ConstraintManager(self.cpuresources, [])
+        self.cpupads = {'serial': self.cpu_cm.request('serial', 0),
+                        'gpio': self.cpu_cm.request('gpio', 0)}
+        self.iopads = {'serial': self.pad_cm.request('serial', 0),
+                        'gpio': self.pad_cm.request('gpio', 0)}
+
+        p = Pins()
+        for pin in list(p):
+            make_jtag_ioconn(self.cpu_params, pin, self.cpupads,
+                                                   self.iopads)
+
         # add verilog sources
         self.add_sources(platform)
 
index 51d3654edf338f79caa697cf61260f2b917c6e2a..b7e01ccdd0d81b4cc9f95d5a535e87711a7f3d71 100644 (file)
@@ -20,8 +20,10 @@ from migen.fhdl.structure import _Fragment
 from litex.build.generic_platform import (GenericPlatform, Pins,
                                         Subsignal, IOStandard, Misc,
                                         )
+from libresoc.ls180io import make_uart, make_gpio
 import os
 
+
 # IOs ----------------------------------------------------------------------------------------------
 
 _io = [
@@ -43,18 +45,6 @@ _io = [
         Subsignal("sda", Pins("M1"), IOStandard("LVCMOS33"))
     ),
 
-    # UART0: 2 pins
-    ("serial", 0,
-        Subsignal("tx", Pins("L4"), IOStandard("LVCMOS33")),
-        Subsignal("rx", Pins("M1"), IOStandard("LVCMOS33"))
-    ),
-
-    # UART1: 2 pins
-    ("serial", 1,
-        Subsignal("tx", Pins("L4"), IOStandard("LVCMOS33")),
-        Subsignal("rx", Pins("M1"), IOStandard("LVCMOS33"))
-    ),
-
     # SPI0: 4 pins
     ("spi_master", 0,
         Subsignal("clk",  Pins("J1")),
@@ -119,22 +109,20 @@ _io = [
     ("pwm", 1, Pins("P2"), IOStandard("LVCMOS33")),
 ]
 
-pins = []
 n_gpio = 16
-for i in range(n_gpio):
-    pins.append("X%d" % i)
-pins = ' '.join(pins)
 
 # 16 GPIOs
-_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( make_gpio("gpio_litex", 0, n_gpio) )
 
 # EINT: 3 pins
 _io.append( ("eint", 3, Pins("E0 E1 E2"), IOStandard("LVCMOS33")) )
 
+# UART0: 2 pins
+_io.append(make_uart("uart_litex", 0))
+# UART1: 2 pins
+_io.append(make_uart("uart_litex", 1))
+
+
 # Platform -----------------------------------------------------------------------------------------
 
 class LS180Platform(GenericPlatform):
index 4ee35898efac152868d0f6c5e31b5147796aea01..0ddea0348a9feaae897e13cf9a23729ce862c625 100755 (executable)
@@ -6,7 +6,7 @@ from functools import reduce
 from operator import or_
 
 from migen import (Signal, FSM, If, Display, Finish, NextValue, NextState,
-                   Cat, Record, ClockSignal, wrap)
+                   Cat, Record, ClockSignal, wrap, ResetInserter)
 
 from litex.build.generic_platform import Pins, Subsignal
 from litex.build.sim import SimPlatform
@@ -27,6 +27,7 @@ from litedram.phy.dfi import Interface as DFIInterface
 from litex.soc.cores.spi import SPIMaster
 from litex.soc.cores.pwm import PWM
 from litex.soc.cores.bitbang import I2CMaster
+from litex.soc.cores import uart
 
 from litex.tools.litex_sim import sdram_module_nphases, get_sdram_phy_settings
 
@@ -250,7 +251,7 @@ class LibreSoCSim(SoCCore):
             uart_name = "sim"
         elif platform == 'ls180':
             platform     = LS180Platform()
-            uart_name = "serial"
+            uart_name = "uart_litex"
 
         #cpu_data_width = 32
         cpu_data_width = 64
@@ -291,7 +292,8 @@ class LibreSoCSim(SoCCore):
             cpu_variant              = variant,
             csr_data_width            = 8,
             l2_size             = 0,
-            uart_name                = uart_name,
+            with_uart                = False,
+            uart_name                = None,
             with_sdram               = with_sdram,
             sdram_module          = sdram_module,
             sdram_data_width      = sdram_data_width,
@@ -360,9 +362,36 @@ class LibreSoCSim(SoCCore):
             self.add_constant("MEMTEST_ADDR_DEBUG", 1)
             self.add_constant("MEMTEST_DATA_DEBUG", 1)
 
+        # UART
+        uart_core_pads = self.cpu.cpupads['serial']
+        self.submodules.uart_phy = uart.UARTPHY(
+                pads     = uart_core_pads,
+                clk_freq = self.sys_clk_freq,
+                baudrate = 115200)
+        self.submodules.uart = ResetInserter()(uart.UART(self.uart_phy,
+                tx_fifo_depth = 16,
+                rx_fifo_depth = 16))
+        # "real" pads connect to C4M JTAG iopad
+        uart_pads     = platform.request(uart_name) # "real" (actual) pin
+        uart_io_pads = self.cpu.iopads['serial'] # C4M JTAG pads
+        self.comb += uart_pads.tx.eq(uart_io_pads.tx)
+        self.comb += uart_io_pads.rx.eq(uart_pads.rx)
+
+        self.csr.add("uart_phy", use_loc_if_exists=True)
+        self.csr.add("uart", use_loc_if_exists=True)
+        self.irq.add("uart", use_loc_if_exists=True)
+
         # GPIOs (bi-directional)
-        self.submodules.gpio = GPIOTristateASIC(platform.request("gpio"))
-        self.add_csr("gpio")
+        if False:
+            gpio_core_pads = self.cpu.cpupads['gpio']
+            self.submodules.gpio = GPIOTristateASIC(gpio_core_pads)
+            self.add_csr("gpio")
+
+            gpio_pads = platform.request("gpio_litex")
+            gpio_io_pads = self.cpu.iopads['gpio'] # C4M JTAG pads
+            self.comb += gpio_pads.i.eq(gpio_io_pads.i)
+            self.comb += gpio_io_pads.o.eq(gpio_pads.o)
+            self.comb += gpio_io_pads.oe.eq(gpio_pads.oe)
 
         # SPI Master
         self.submodules.spi_master = SPIMaster(