254 lines
12 KiB
Python
Executable File
254 lines
12 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
|
|
#
|
|
# This file is part of LiteX-Boards.
|
|
#
|
|
# Copyright (c) 2021 Franck Jullien <franck.jullien@collshade.fr>
|
|
# Copyright (c) 2021 Florent Kermarrec <florent@enjoy-digital.fr>
|
|
# SPDX-License-Identifier: BSD-2-Clause
|
|
|
|
import argparse
|
|
|
|
from migen import *
|
|
from migen.genlib.resetsync import AsyncResetSynchronizer
|
|
|
|
from litex_boards.platforms import efinix_trion_t120_bga576_dev_kit
|
|
|
|
from litex.soc.cores.clock import *
|
|
from litex.soc.integration.soc_core import *
|
|
from litex.soc.integration.soc import SoCRegion
|
|
from litex.soc.integration.builder import *
|
|
from litex.soc.cores.led import LedChaser
|
|
from litex.soc.interconnect import axi
|
|
|
|
from liteeth.phy.trionrgmii import LiteEthPHYRGMII
|
|
|
|
# CRG ----------------------------------------------------------------------------------------------
|
|
|
|
class _CRG(Module):
|
|
def __init__(self, platform, sys_clk_freq):
|
|
self.clock_domains.cd_sys = ClockDomain()
|
|
|
|
# # #
|
|
|
|
clk40 = platform.request("clk40")
|
|
rst_n = platform.request("user_btn", 0)
|
|
|
|
|
|
# PLL
|
|
self.submodules.pll = pll = TRIONPLL(platform)
|
|
self.comb += pll.reset.eq(~rst_n)
|
|
pll.register_clkin(clk40, 40e6)
|
|
pll.create_clkout(self.cd_sys, sys_clk_freq, with_reset=True, name="axi_clk")
|
|
|
|
# BaseSoC ------------------------------------------------------------------------------------------
|
|
|
|
class BaseSoC(SoCCore):
|
|
def __init__(self, sys_clk_freq=int(50e6),
|
|
with_spi_flash = False,
|
|
with_ethernet = False,
|
|
with_etherbone = False,
|
|
eth_phy = 0,
|
|
eth_ip = "192.168.1.50",
|
|
with_led_chaser = True,
|
|
**kwargs):
|
|
platform = efinix_trion_t120_bga576_dev_kit.Platform()
|
|
|
|
# USBUART PMOD as Serial--------------------------------------------------------------------
|
|
platform.add_extension(efinix_trion_t120_bga576_dev_kit.usb_pmod_io("pmod_e"))
|
|
kwargs["uart_name"] = "usb_uart"
|
|
|
|
# SoCCore ----------------------------------------------------------------------------------
|
|
SoCCore.__init__(self, platform, sys_clk_freq,
|
|
ident = "LiteX SoC on Efinix Trion T120 BGA576 Dev Kit",
|
|
ident_version = True,
|
|
**kwargs
|
|
)
|
|
|
|
# CRG --------------------------------------------------------------------------------------
|
|
self.submodules.crg = _CRG(platform, sys_clk_freq)
|
|
|
|
# SPI Flash --------------------------------------------------------------------------------
|
|
if with_spi_flash:
|
|
from litespi.modules import W25Q128JV
|
|
from litespi.opcodes import SpiNorFlashOpCodes as Codes
|
|
self.add_spi_flash(mode="4x", module=W25Q128JV(Codes.READ_1_1_4), with_master=True)
|
|
platform.toolchain.excluded_ios.append(platform.lookup_request("spiflash4x").dq)
|
|
|
|
# Leds -------------------------------------------------------------------------------------
|
|
if with_led_chaser:
|
|
self.submodules.leds = LedChaser(
|
|
pads = platform.request_all("user_led"),
|
|
sys_clk_freq = sys_clk_freq)
|
|
|
|
# Tristate Test ----------------------------------------------------------------------------
|
|
from litex.build.generic_platform import Subsignal, Pins, Misc, IOStandard
|
|
from litex.soc.cores.bitbang import I2CMaster
|
|
platform.add_extension([("i2c", 0,
|
|
Subsignal("sda", Pins("T12")),
|
|
Subsignal("scl", Pins("V11")),
|
|
IOStandard("3.3_V_LVTTL_/_LVCMOS"),
|
|
)])
|
|
self.submodules.i2c = I2CMaster(pads=platform.request("i2c"))
|
|
|
|
# Ethernet / Etherbone ---------------------------------------------------------------------
|
|
if with_ethernet or with_etherbone:
|
|
self.submodules.ethphy = LiteEthPHYRGMII(
|
|
platform = platform,
|
|
clock_pads = platform.request("eth_clocks", eth_phy),
|
|
pads = platform.request("eth", eth_phy),
|
|
with_hw_init_reset = False)
|
|
if with_ethernet:
|
|
self.add_ethernet(phy=self.ethphy, software_debug=True)
|
|
if with_etherbone:
|
|
self.add_etherbone(phy=self.ethphy)
|
|
|
|
# FIXME: Avoid this.
|
|
platform.toolchain.excluded_ios.append(platform.lookup_request("eth_clocks").tx)
|
|
platform.toolchain.excluded_ios.append(platform.lookup_request("eth_clocks").rx)
|
|
platform.toolchain.excluded_ios.append(platform.lookup_request("eth").tx_data)
|
|
platform.toolchain.excluded_ios.append(platform.lookup_request("eth").rx_data)
|
|
platform.toolchain.excluded_ios.append(platform.lookup_request("eth").mdio)
|
|
|
|
# LPDDR3 SDRAM -----------------------------------------------------------------------------
|
|
if not self.integrated_main_ram_size:
|
|
#./efinix_trion_t120_bga576_dev_kit.py --with-lpddr3 --sys-clk-freq=50e6 --csr-csv=csr.csv --build --load
|
|
|
|
# DRAM / PLL Blocks.
|
|
# ------------------
|
|
br0_pll_clkin = platform.request("br0_pll_clkin")
|
|
platform.toolchain.excluded_ios.append(br0_pll_clkin)
|
|
self.platform.toolchain.additional_sdc_commands.append(f"create_clock -period {1e9/50e6} br0_pll_clkin")
|
|
|
|
block = {"type" : "DRAM"}
|
|
platform.toolchain.ifacewriter.xml_blocks.append(block)
|
|
block = {"type" : "PLL_DRAM"}
|
|
platform.toolchain.ifacewriter.blocks.append(block)
|
|
|
|
# DRAM Rst.
|
|
# ---------
|
|
br0_pll_rstn = platform.add_iface_io("br0_pll_rstn")
|
|
self.comb += br0_pll_rstn.eq(platform.request("user_btn", 1))
|
|
self.specials += Instance("ddr_reset_sequencer",
|
|
i_ddr_rstn_i = br0_pll_rstn,
|
|
i_clk = br0_pll_clkin,
|
|
o_ddr_rstn = platform.add_iface_io("ddr_inst1_RSTN"),
|
|
o_ddr_cfg_seq_rst = platform.add_iface_io("ddr_inst1_CFG_SEQ_RST"),
|
|
o_ddr_cfg_seq_start = platform.add_iface_io("ddr_inst1_CFG_SEQ_START"),
|
|
o_ddr_init_done = Signal(),
|
|
)
|
|
platform.add_source("ddr_reset_sequencer.v") # FIXME: From example design.
|
|
|
|
# DRAM AXI-Port.
|
|
# --------------
|
|
axi_port = axi.AXIInterface(data_width=256, address_width=32, id_width=8)
|
|
ios = [("axi0", 0,
|
|
Subsignal("wdata", Pins(256)),
|
|
Subsignal("wready", Pins(1)),
|
|
Subsignal("wid", Pins(8)),
|
|
Subsignal("bready", Pins(1)),
|
|
Subsignal("rdata", Pins(256)),
|
|
Subsignal("aid", Pins(8)),
|
|
Subsignal("bvalid", Pins(1)),
|
|
Subsignal("rlast", Pins(1)),
|
|
Subsignal("bid", Pins(8)),
|
|
Subsignal("asize", Pins(3)),
|
|
Subsignal("atype", Pins(1)),
|
|
Subsignal("aburst", Pins(2)),
|
|
Subsignal("wvalid", Pins(1)),
|
|
Subsignal("aaddr", Pins(32)),
|
|
Subsignal("rid", Pins(8)),
|
|
Subsignal("avalid", Pins(1)),
|
|
Subsignal("rvalid", Pins(1)),
|
|
Subsignal("alock", Pins(2)),
|
|
Subsignal("rready", Pins(1)),
|
|
Subsignal("rresp", Pins(2)),
|
|
Subsignal("wstrb", Pins(32)),
|
|
Subsignal("aready", Pins(1)),
|
|
Subsignal("alen", Pins(8)),
|
|
Subsignal("wlast", Pins(1)),
|
|
)]
|
|
io = platform.add_iface_ios(ios)
|
|
rw_n = Signal()
|
|
self.comb += rw_n.eq(axi_port.ar.valid)
|
|
self.comb += [
|
|
# Pseudo AW/AR Channels.
|
|
io.atype.eq(~rw_n),
|
|
io.aaddr[:28].eq( Mux(rw_n, axi_port.ar.addr, axi_port.aw.addr)), # FIXME: Clear 4-LSBs / Limit to 256MB.
|
|
io.aid.eq( Mux(rw_n, axi_port.ar.id, axi_port.aw.id)),
|
|
io.alen.eq( Mux(rw_n, axi_port.ar.len, axi_port.aw.len)),
|
|
io.asize.eq( Mux(rw_n, axi_port.ar.size[0:4], axi_port.aw.size[0:4])), # CHECKME.
|
|
io.aburst.eq( Mux(rw_n, axi_port.ar.burst, axi_port.aw.burst)),
|
|
io.alock.eq( Mux(rw_n, axi_port.ar.lock, axi_port.aw.lock)),
|
|
io.avalid.eq( Mux(rw_n, axi_port.ar.valid, axi_port.aw.valid)),
|
|
axi_port.aw.ready.eq(~rw_n & io.aready),
|
|
axi_port.ar.ready.eq( rw_n & io.aready),
|
|
|
|
# R Channel.
|
|
axi_port.r.id.eq(io.rid),
|
|
axi_port.r.data.eq(io.rdata),
|
|
axi_port.r.last.eq(io.rlast),
|
|
axi_port.r.resp.eq(io.rresp),
|
|
axi_port.r.valid.eq(io.rvalid),
|
|
io.rready.eq(axi_port.r.ready),
|
|
|
|
# W Channel.
|
|
io.wid.eq(axi_port.w.id),
|
|
io.wstrb.eq(axi_port.w.strb),
|
|
io.wdata.eq(axi_port.w.data),
|
|
io.wlast.eq(axi_port.w.last),
|
|
io.wvalid.eq(axi_port.w.valid),
|
|
axi_port.w.ready.eq(io.wready),
|
|
|
|
# B Channel.
|
|
axi_port.b.id.eq(io.bid),
|
|
axi_port.b.valid.eq(io.bvalid),
|
|
io.bready.eq(axi_port.b.ready),
|
|
]
|
|
|
|
# Connect AXI interface to the main bus of the SoC.
|
|
axi_lite_port = axi.AXILiteInterface(data_width=256, address_width=32)
|
|
self.submodules += axi.AXILite2AXI(axi_lite_port, axi_port)
|
|
self.bus.add_slave("main_ram", axi_lite_port, SoCRegion(origin=0x4000_0000, size=0x1000_0000)) # 256MB.
|
|
|
|
# Build --------------------------------------------------------------------------------------------
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(description="LiteX SoC on Efinix Trion T120 BGA576 Dev Kit")
|
|
parser.add_argument("--build", action="store_true", help="Build bitstream")
|
|
parser.add_argument("--load", action="store_true", help="Load bitstream")
|
|
parser.add_argument("--flash", action="store_true", help="Flash bitstream")
|
|
parser.add_argument("--sys-clk-freq", default=50e6, help="System clock frequency (default: 50MHz)")
|
|
parser.add_argument("--with-spi-flash", action="store_true", help="Enable SPI Flash (MMAPed)")
|
|
ethopts = parser.add_mutually_exclusive_group()
|
|
ethopts.add_argument("--with-ethernet", action="store_true", help="Enable Ethernet support")
|
|
ethopts.add_argument("--with-etherbone", action="store_true", help="Enable Etherbone support")
|
|
parser.add_argument("--eth-ip", default="192.168.1.50", type=str, help="Ethernet/Etherbone IP address")
|
|
parser.add_argument("--eth-phy", default=0, type=int, help="Ethernet PHY: 0 (default) or 1")
|
|
builder_args(parser)
|
|
soc_core_args(parser)
|
|
args = parser.parse_args()
|
|
|
|
soc = BaseSoC(
|
|
sys_clk_freq = int(float(args.sys_clk_freq)),
|
|
with_spi_flash = args.with_spi_flash,
|
|
with_ethernet = args.with_ethernet,
|
|
with_etherbone = args.with_etherbone,
|
|
eth_ip = args.eth_ip,
|
|
eth_phy = args.eth_phy,
|
|
**soc_core_argdict(args))
|
|
builder = Builder(soc, **builder_argdict(args))
|
|
builder.build(run=args.build)
|
|
|
|
if args.load:
|
|
prog = soc.platform.create_programmer()
|
|
prog.load_bitstream(os.path.join(builder.gateware_dir, f"{soc.build_name}.bit"))
|
|
|
|
if args.flash:
|
|
from litex.build.openfpgaloader import OpenFPGALoader
|
|
prog = OpenFPGALoader("trion_t120_bga576")
|
|
prog.flash(0, os.path.join(builder.gateware_dir, f"{soc.build_name}.hex"))
|
|
|
|
if __name__ == "__main__":
|
|
main()
|