This repository contains wrappers to allow to use some of the Nitro FPGA cores in a Migen and/or LiteX environment.
This core is wrapped as no2migen.litex.NitroUSB
for use as a wishbone
LiteX peripheral.
The core can be added as such (in the __init__
of your SoCCore
) :
self.submodules.usb = NitroUSB(platform, platform.request("usb"))
self.bus.add_slave("usb", self.usb.bus, SoCRegion(size=64*kB, cached=False))
The usb
resource must define the pads for d_p
, d_n
and pullup
.
Clocking wise, the core works at any sys
frequency for its interface to
the SoC but needs a usb_48
ClockDomain
to be defined and running at
48 MHz for the USB SIE part.
You also need to add a small work around just after constructing your Builder
and before calling its build
method. This is required because of
enjoy-digital/litex#951
soc.usb.add_gateware_dir_files(builder.gateware_dir)
The options available for the core are :
-
evt_fifo=True/False
: Enables or disable the event fifo which can be used by the driver to speed up operations slightly. -
irq=True/False
: Enables theo_irq
output of the core so it can generate interrupt on activity rather than using polling mode in the driver. -
sync=True/False
: If yoursys
domain is the same as theusb_48
domain, both running at the same 48 MHz clock, then some CDC circuitry can be omitted.
This core is wrapped as no2migen.litex.NitroMuAcmUart
for use as a standard
LiteX UART (compatible with other UART options).
If you just want your SoC to have an UART / Console over USB and don't want to run a USB stack yourself in your core, you can use this as an alternative to having a raw USB device core that you must drive yourself.
To use it, you must first disable the built-in UART added by passing
with_uart = False
to the SoCCore.__init__
call, usually using
kwargs["with_uart"] = False
to overwrite the default options.
And then create the UART module and add it yourself in the __init__
of
your SoCCore
:
from no2migen.litex import NitroMuAcmUart
usb_pads = self.platform.request("usb")
self.submodules.uart = NitroMuAcmUart(platform, usb_pads)
self.add_constant("UART_POLLING")
The usb
resource must define the pads for d_p
, d_n
and pullup
.
Clocking wise, the core works at any sys
frequency for its interface to
the SoC but needs a usb_48
ClockDomain
to be defined and running at
48 MHz for the USB SIE part.
The core also offers a bootloader_req
that generates a pulse if the
hosts requests a reboot to bootloader using a DFU_DETACH
request. This
should be tied to whatever logic you have to reboot your FPGA to its
bootloader (assuming there is one).
The options available for the core are :
-
vid
/pid
: Sets customs USB PID/VID for the core. -
vendor
/product
/serial
: Sets the corresponding string descriptors (length limited to 16). -
no_dfu_rt
: Disables the DFU runtime function of the core. -
sync=True/False
: If yoursys
domain is the same as theusb_48
domain, both running at the same 48 MHz clock, then some CDC circuitry can be omitted.
This core is also wrapped as no2migen.NitroMuAcmSync
,
no2migen.NitroMuAcmAsync
and no2migen.NitroMuAcmBuffered
.
Theses 3 variants expose the same kind of data interface, derived from
AXI-Stream. Refer to the python docstring for the details. The Sync
variant
is meant to run entirely in one clock domain and it must be 48 MHz. The Async
variant uses a usb_48
clock domain for the USB part but all user interfacing
is done in the sys
doman and this can be anything. The Buffered
variant
can use either clocking strategy (depending on sync
parameter) but it adds
some FIFO to increase efficiency.
For all variants the customizations options are the same as explained in the LiteX variant above.
Some of the cores have limited FPGA architecture supports and will only work on some FPGA target. If you need support for another, adaptation is often not too complex (mostly IO buffers / BRAM primitives), you can open an issue on the appropriate core tracker.
See LICENSE.md for the licenses of the various components in this repository