Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UartLite as a separate module. #2096

Open
mohammadshahidzade opened this issue Oct 15, 2024 · 2 comments
Open

UartLite as a separate module. #2096

mohammadshahidzade opened this issue Oct 15, 2024 · 2 comments

Comments

@mohammadshahidzade
Copy link

Hi,

I wanted to replicate a Litex soc with a Vivado block design. I was wondering if there is any way to generate a UartLite module without anything else included since the Litex UartLite control register signals are different from Xilinx LiteUart and 16550 Uart.

@mohammadshahidzade
Copy link
Author

This is what I have so far, but it is not working as expected inside the block design.

import argparse

from migen import *

from litex.build.generic_platform import *

from litex.soc.integration.soc_core import *
from litex.soc.integration.soc import SoCRegion
from litex.soc.integration.builder import *
from litex.soc.interconnect import wishbone
from litex.soc.interconnect import axi

# IOs/Interfaces -----------------------------------------------------------------------------------

def get_common_ios():
    return [
        # Clk/Rst.
        ("clk", 0, Pins(1)),
        ("rst", 0, Pins(1)),
    ]

def get_uart_ios():
    return [
        # Serial
        ("uart", 0,
            Subsignal("tx",  Pins(1)),
            Subsignal("rx", Pins(1)),
        )
    ]

# Platform -----------------------------------------------------------------------------------------


class Platform(GenericPlatform):
    def build(self, fragment, build_dir, build_name, **kwargs):
        os.makedirs(build_dir, exist_ok=True)
        os.chdir(build_dir)
        conv_output = self.get_verilog(fragment, name=build_name)
        conv_output.write(f"{build_name}.v")

# LiteX SoC Generator ------------------------------------------------------------------------------

class LiteXSoCGenerator(SoCMini):
    # def __init__(self, name="litex_soc", sys_clk_freq=int(50e6),platform, **kwargs):
    SoCMini.mem_map["csr"] = 0xf0000000
    SoCMini.csr_map = {
        "ctrl":           0,
    }
    def __init__(self, name="litex_soc", sys_clk_freq=int(50e6),platform = 0, **kwargs):
        platform.add_extension(get_uart_ios())
        platform.name = name
        self.sys_clk_freq = sys_clk_freq
        self.submodules.crg = CRG(
            clk = platform.request("clk"),
            rst = platform.request("rst"),
        )

        self.add_uart(uart_pads = platform.request("uart"))
        SoCMini.__init__(self, platform, clk_freq=sys_clk_freq,
            csr_data_width = 32,
            ident          = "LiteUart",
            ident_version  = True
        )

        s_bus = {
            "wishbone" : wishbone.Interface(data_width=32, address_width=32, addressing="word"),
            "axi-lite" : axi.AXILiteInterface(data_width=32, address_width=32),

        }[kwargs["bus_standard"]]
        self.bus.add_master(name="mmap_s", master=s_bus)
        platform.add_extension(s_bus.get_ios("mmap_s"))
        wb_pads = platform.request("mmap_s")
        self.comb += s_bus.connect_to_pads(wb_pads, mode="slave")

    def add_uart(self, name="uart", uart_name="serial", uart_pads=None, baudrate=115200, fifo_depth=16):
        # Imports.
        from litex.soc.cores.uart import UART, UARTCrossover

        # Core.
        self.check_if_exists(name)
        supported_uarts = [
            "crossover",
            "crossover+uartbone",
            "jtag_uart",
            "sim",
            "stub",
            "stream",
            "uartbone",
            "usb_acm",
            "serial(x)",
        ]
        if uart_pads is None:
            uart_pads_name = "serial" if uart_name == "sim" else uart_name
            uart_pads      = self.platform.request(uart_pads_name, loose=True)
        uart_phy       = None
        uart           = None
        uart_kwargs    = {
            "tx_fifo_depth": fifo_depth,
            "rx_fifo_depth": fifo_depth,
        }
        if (uart_pads is None) and (uart_name not in supported_uarts):
            self.logger.error("{} UART {}, supported are: \n{}.".format(
                colorer(uart_name),
                colorer("not supported/found on board", color="red"),
                colorer("- " + "\n- ".join(supported_uarts))))
            raise SoCError()

        # Crossover.
        if uart_name in ["crossover"]:
            uart = UARTCrossover(**uart_kwargs)

        # Crossover + UARTBone.
        elif uart_name in ["crossover+uartbone"]:
            self.add_uartbone(baudrate=baudrate)
            uart = UARTCrossover(**uart_kwargs)

        # JTAG UART.
        elif uart_name in ["jtag_uart"]:
            from litex.soc.cores.jtag import JTAGPHY
            uart_phy = JTAGPHY(device=self.platform.device, platform=self.platform)
            uart     = UART(uart_phy, **uart_kwargs)

        # Sim.
        elif uart_name in ["sim"]:
            from litex.soc.cores.uart import RS232PHYModel
            uart_phy = RS232PHYModel(uart_pads)
            uart     = UART(uart_phy, **uart_kwargs)

        # Stub / Stream.
        elif uart_name in ["stub", "stream"]:
            uart = UART(tx_fifo_depth=0, rx_fifo_depth=0)
            self.comb += uart.source.ready.eq(uart_name == "stub")

        # UARTBone.
        elif uart_name in ["uartbone"]:
            self.add_uartbone(baudrate=baudrate)

        # USB ACM (with ValentyUSB core).
        elif uart_name in ["usb_acm"]:
            import valentyusb.usbcore.io as usbio
            import valentyusb.usbcore.cpu.cdc_eptri as cdc_eptri
            usb_pads  = self.platform.request("usb")
            usb_iobuf = usbio.IoBuf(usb_pads.d_p, usb_pads.d_n, usb_pads.pullup)
            # Run USB-ACM in sys_usb clock domain similar to sys_clk domain but without sys_rst.
            self.cd_sys_usb = ClockDomain()
            self.comb += self.cd_sys_usb.clk.eq(ClockSignal("sys"))
            uart = ClockDomainsRenamer("sys_usb")(cdc_eptri.CDCUsb(usb_iobuf))

        # Regular UART.
        else:
            from litex.soc.cores.uart import UARTPHY
            uart_phy  = UARTPHY(uart_pads, clk_freq=self.sys_clk_freq, baudrate=baudrate)
            uart      = UART(uart_phy, **uart_kwargs)

        # Add PHY/UART.
        if uart_phy is not None:
            self.add_module(name=f"{name}_phy", module=uart_phy)
        if uart is not None:
            self.add_module(name=name, module=uart)


# Build --------------------------------------------------------------------------------------------
def main():
    # Arguments.
    from litex.soc.integration.soc import LiteXSoCArgumentParser
    parser = LiteXSoCArgumentParser(description="LiteX standalone SoC generator")
    target_group = parser.add_argument_group(title="Generator options")
    target_group.add_argument("--name",          default="litex_soc", help="SoC Name.")
    target_group.add_argument("--build",         action="store_true", help="Build SoC.")
    target_group.add_argument("--sys-clk-freq",  default=int(50e6),   help="System clock frequency.")
    builder_args(parser)
    soc_core_args(parser)
    args = parser.parse_args()

    from litex.build.xilinx import XilinxPlatform
    platform = XilinxPlatform("xc7a", io=get_common_ios())

    soc = LiteXSoCGenerator(
        name         = args.name,
        sys_clk_freq = int(float(args.sys_clk_freq)),
        platform  = platform,
        **soc_core_argdict(args)
    )
    builder = Builder(soc, **builder_argdict(args))
    builder.build(build_name=args.name, run=args.build)

if __name__ == "__main__":
    main()

@mohammadshahidzade
Copy link
Author

Ok, found the problem. The code that I send here will work but you should have an accurate clk_frequency.

Also, does anyone know how I can change the CSR location generated for the UART in this code and add the irq to the top-level module?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant