Building a SoC in python with Migen

A simple guide

Overview
Installing the tools
Connecting the board
Getting started
Creating a platform description
Top Level Design


Get the source code on GitHub brandonhamilton/building-a-soc-with-migen

Creating a platform description

A list of the currently supported platforms can be found in the Mibuild platforms folder.

If the target platform is already supported, there is no need to create a new platform description file as described in this section, and you can continue on to the Top Level Design

If the target platform is not yet supported, it is simple to create a new platform description for the target board. In our case, we will create a description for the Xilinx ML605 in a python module - platform.py - in the project root directory

The platform documentation serves as our reference:

Import the mibuild platform elements from the mibuild.generic_platform module. These allow us to define the platform resources using python objects such as Subsignal, Pins, and IOStandard.

from mibuild.generic_platform import *
from mibuild.xilinx_ise import XilinxISEPlatform, CRG_DS

The I/O pads on the platform are described using these mibuild platform elements. These will also be used to automatically create the constraints file used by the synthesis tools. Our SoC design will be able to request relevant platform resources from this platform description by name (and number). This allows us to create a more portable design that is separated from the underlying implementation platform.

_io = [

The I/O pads are specified in a list containing a tuple for each resource specifying the resource name, resource number (used for multiple resources with the same name), and corresponding properties and sub-signals.

The ML605 contains a 200MHz differential oscillator connected to pins J9 and H9. These pins are represented using Subsignals with the location, corresponding I/O standards and other properties.

    # System clock (Differential 200MHz)
    ("clk200", 0,
        Subsignal("p", Pins("J9"), IOStandard("LVDS_25"), Misc("DIFF_TERM=TRUE")),
        Subsignal("n", Pins("H9"), IOStandard("LVDS_25"), Misc("DIFF_TERM=TRUE"))
    ),

Our platform description will try to use a naming convention similar to that used by other mibuild platforms, where system clocks are specified with the clk prefix along with the frequency.

The single source 66MHz oscillator could be described similarly:

    # User clock (66MHz)
    ("clk66", 0, Pins("U23"), IOStandard("LVCMOS25")),

The ML605 provides six active-High pushbutton switches. For the purposes of this tutorial we will only specify the CPU Reset connected to pin H10. Note that this pin uses a different I/O standard (SSTL15).

    # CPU reset switch
    ("cpu_reset", 0, Pins("H10"), IOStandard("SSTL15")),

The USB-to-UART pins will be used for serial communication with the board

    # USB-to-UART
    ("serial", 0,
        Subsignal("tx", Pins("J25"), IOStandard("LVCMOS25")),
        Subsignal("rx", Pins("J24"), IOStandard("LVCMOS25"))
    ),

A group of simliar resources can defined with the same resource name

    # LEDs
    ("user_led", 0, Pins("AC22"), IOStandard("LVCMOS25"), Misc("SLEW=SLOW")),
    ("user_led", 1, Pins("AC24"), IOStandard("LVCMOS25"), Misc("SLEW=SLOW")),
    ("user_led", 2, Pins("AE22"), IOStandard("LVCMOS25"), Misc("SLEW=SLOW")),
    ("user_led", 3, Pins("AE23"), IOStandard("LVCMOS25"), Misc("SLEW=SLOW")),
    ("user_led", 4, Pins("AB23"), IOStandard("LVCMOS25"), Misc("SLEW=SLOW")),
    ("user_led", 5, Pins("AG23"), IOStandard("LVCMOS25"), Misc("SLEW=SLOW")),
    ("user_led", 6, Pins("AE24"), IOStandard("LVCMOS25"), Misc("SLEW=SLOW")),
    ("user_led", 7, Pins("AD24"), IOStandard("LVCMOS25"), Misc("SLEW=SLOW")),
]

The above is not a complete description of all resources available on the ML605, and any additional resources, such as the Ethernet PHY, Multi-Gigabit Transceivers or others, can similarly be added as needed.

Now we create out platform class, which will be used by our build script. This class will inherit from the XilinxISEPlatform class, which contains the logic for building our platform with the Xilinx ISE tools.

Parameters passed to the platform constructor are

deviceTarget FPGA devicerequired
ioList of I/O padsrequired
default_crg_factoryDefault Clock/Reset generatoroptional
namePlatform nameoptional

In this case the ML605 device is the xc6vlx240t-ff1156-1 FPGA.

By specifying a default Clock/Reset generator factory, mibuild will use this to automatically generate a Clock/Reset module for the platform if no ClockDomain instances are provided in the design. In this case, we will specify the CRG_DS class, which will create a dedicated differential buffered input clock (using the Xilinx IBUFGDS primitive) with the clk200 resource, reset signal with the cpu_reset resource, and timing constraint of 5.0 ns.

class Platform(XilinxISEPlatform):
    def __init__(self):
        XilinxISEPlatform.__init__(self, "xc6vlx240t-ff1156-1", _io,
            lambda p: CRG_DS(p, "clk200", "cpu_reset", 5.0))

The platform is now ready to be used by the mibuild tools.

If possible, consider contributing any new platform descriptions to be included in the Mibuild project by sending them to the Developers mailing list.