-
Notifications
You must be signed in to change notification settings - Fork 290
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Showing
2 changed files
with
382 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,165 @@ | ||
# | ||
# This file is part of LiteX-Boards. | ||
# | ||
# Copyright (c) 2024 Yu-Ti Kuo <[email protected]> | ||
# SPDX-License-Identifier: BSD-2-Clause | ||
# embedfire rise pro FPGA: https://detail.tmall.com/item.htm?id=645153441975 | ||
|
||
from litex.build.generic_platform import * | ||
from litex.build.xilinx import Xilinx7SeriesPlatform | ||
from litex.build.openocd import OpenOCD | ||
from litex.build.xilinx.programmer import VivadoProgrammer | ||
|
||
# IOs ---------------------------------------------------------------------------------------------- | ||
|
||
_io = [ | ||
# Clk / Rst | ||
("clk50" , 0, Pins("W19"), IOStandard("LVCMOS33")), | ||
("cpu_reset", 0, Pins("N15"), IOStandard("LVCMOS33")), | ||
|
||
# Leds | ||
("user_led", 0, Pins("M21"), IOStandard("LVCMOS33")), | ||
("user_led", 1, Pins("L21"), IOStandard("LVCMOS33")), | ||
("user_led", 2, Pins("K21"), IOStandard("LVCMOS33")), | ||
("user_led", 3, Pins("K22"), IOStandard("LVCMOS33")), | ||
|
||
# Buttons | ||
("user_sw", 0, Pins("V17"), IOStandard("LVCMOS33")), | ||
("user_sw", 1, Pins("W17"), IOStandard("LVCMOS33")), | ||
("user_sw", 2, Pins("AA18"), IOStandard("LVCMOS33")), | ||
("user_sw", 3, Pins("AB18"), IOStandard("LVCMOS33")), | ||
|
||
# Beeper (Buzzer) | ||
("beeper", 0, Pins("M17"), IOStandard("LVCMOS33")), | ||
|
||
# Fan | ||
("fan", 0, Pins("W22"), IOStandard("LVCMOS33")), | ||
|
||
# Serial CH340G | ||
("serial", 0, | ||
Subsignal("tx", Pins("N17")), | ||
Subsignal("rx", Pins("P17")), | ||
IOStandard("LVCMOS33") | ||
), | ||
|
||
# I2C EEPROM 24C64 | ||
("i2c", 0, | ||
Subsignal("scl", Pins("E22")), | ||
Subsignal("sda", Pins("D22")), | ||
IOStandard("LVCMOS33"), | ||
), | ||
|
||
# # SPIFlash N25Q128A13ESE40G | ||
# ("spiflash4x", 0, | ||
# Subsignal("cs_n", Pins("T19")), | ||
# Subsignal("clk", Pins("L12")), | ||
# Subsignal("dq", Pins("P22 R22 P21 R21")), | ||
# IOStandard("LVCMOS33") | ||
# ), | ||
|
||
# DDR3 SDRAM MT41K256M16 | ||
("ddram", 0, | ||
Subsignal("a", Pins( | ||
"AA4 AB2 AA5 AB3 AB1 U2 W1 R2", | ||
"V2 U3 Y1 W2 Y2 U1 V3"), | ||
IOStandard("SSTL135")), | ||
Subsignal("ba", Pins("AA1 Y3 AA3"), IOStandard("SSTL135")), | ||
Subsignal("ras_n", Pins("W6"), IOStandard("SSTL135")), | ||
Subsignal("cas_n", Pins("U5"), IOStandard("SSTL135")), | ||
Subsignal("we_n", Pins("Y4"), IOStandard("SSTL135")), | ||
Subsignal("cs_n", Pins("T1"), IOStandard("SSTL135")), | ||
Subsignal("dm", Pins("D2 G2 M2 M5"), IOStandard("SSTL135")), | ||
Subsignal("dq", Pins( | ||
"C2 G1 A1 F3 B2 F1 B1 E2", | ||
"H3 G3 H2 H5 J1 J5 K1 H4", | ||
"L4 M3 L3 J6 K3 K6 J4 L5", | ||
"P1 N4 R1 N2 M6 N5 P6 P2"), | ||
IOStandard("SSTL135"), | ||
Misc("IN_TERM=UNTUNED_SPLIT_40")), | ||
Subsignal("dqs_p", Pins("E1 K2 M1 P5"), | ||
IOStandard("DIFF_SSTL135"), | ||
Misc("IN_TERM=UNTUNED_SPLIT_40")), | ||
Subsignal("dqs_n", Pins("D1 J2 L1 P4"), | ||
IOStandard("DIFF_SSTL135"), | ||
Misc("IN_TERM=UNTUNED_SPLIT_40")), | ||
Subsignal("clk_p", Pins("V4"), IOStandard("DIFF_SSTL135")), | ||
Subsignal("clk_n", Pins("W4"), IOStandard("DIFF_SSTL135")), | ||
Subsignal("cke", Pins("AB5"), IOStandard("SSTL135")), | ||
Subsignal("odt", Pins("T5"), IOStandard("SSTL135")), | ||
Subsignal("reset_n", Pins("R3"), IOStandard("SSTL135")), | ||
Misc("SLEW=FAST"), | ||
), | ||
|
||
# RGMII Ethernet (RTL8211F) | ||
("eth_clocks", 0, | ||
Subsignal("tx", Pins("C18")), | ||
Subsignal("rx", Pins("C19")), | ||
IOStandard("LVCMOS33") | ||
), | ||
("eth", 0, | ||
#SubSignal("inib"), Pins("D21")), | ||
#Subsignal("rst_n", Pins("E21")), | ||
Subsignal("mdio", Pins("G22")), | ||
Subsignal("mdc", Pins("G21")), | ||
Subsignal("rx_ctl", Pins("C22")), | ||
Subsignal("rx_data", Pins("D20 C20 A18 A19")), | ||
Subsignal("tx_ctl", Pins("B22")), | ||
Subsignal("tx_data", Pins("B20 A20 B21 A21")), | ||
IOStandard("LVCMOS33") | ||
), | ||
|
||
# SDCard | ||
("spisdcard", 0, | ||
Subsignal("cd", Pins("AA19")), | ||
Subsignal("clk", Pins("Y22")), | ||
Subsignal("mosi", Pins("Y21")), | ||
Subsignal("cs_n", Pins("A14")), | ||
Subsignal("miso", Pins("AB21")), | ||
Misc("SLEW=FAST"), | ||
IOStandard("LVCMOS33"), | ||
), | ||
|
||
("sdcard", 0, | ||
Subsignal("data", Pins("AB21 AB22 AB20 W21"),), | ||
Subsignal("cmd", Pins("Y21"),), | ||
Subsignal("clk", Pins("Y22")), | ||
Subsignal("cd", Pins("AA19")), | ||
Misc("SLEW=FAST"), | ||
IOStandard("LVCMOS33"), | ||
), | ||
] | ||
# Connectors --------------------------------------------------------------------------------------- | ||
|
||
_connectors = [] # ToDo | ||
|
||
# Platform ----------------------------------------------------------------------------------------- | ||
|
||
class Platform(Xilinx7SeriesPlatform): | ||
default_clk_name = "clk50" | ||
default_clk_period = 1e9/50e6 | ||
|
||
def __init__(self, variant="a7-35", toolchain="vivado"): | ||
device = { | ||
"a7-35": "xc7a35tfgg484-2", | ||
"a7-100": "xc7a100tfgg484-2", | ||
"a7-200": "xc7a200tfbg484-2" | ||
}[variant] | ||
Xilinx7SeriesPlatform.__init__(self, device, _io, _connectors, toolchain=toolchain) | ||
self.toolchain.bitstream_commands = \ | ||
["set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 4 [current_design]"] | ||
self.toolchain.additional_commands = \ | ||
["write_cfgmem -force -format bin -interface spix4 -size 16 " | ||
"-loadbit \"up 0x0 {build_name}.bit\" -file {build_name}.bin"] | ||
self.add_platform_command("set_property INTERNAL_VREF 0.675 [get_iobanks 34]") | ||
|
||
def create_programmer(self): | ||
# bscan_spi = ( | ||
# "bscan_spi_xc7a100t.bit" if "xc7a100t" in self.device | ||
# else "bscan_spi_xc7a200t.bit" if "xc7a200t" in self.device | ||
# else "bscan_spi_xc7a35t.bit" | ||
# ) | ||
return VivadoProgrammer(flash_part="mt25ql128-spi-x1_x2_x4") | ||
|
||
def do_finalize(self, fragment): | ||
Xilinx7SeriesPlatform.do_finalize(self, fragment) | ||
self.add_period_constraint(self.lookup_request("clk50", loose=True), 1e9/50e6) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,217 @@ | ||
#!/usr/bin/env python3 | ||
|
||
# | ||
# This file is part of LiteX-Boards. | ||
# | ||
# Copyright (c) 2024 Yu-Ti Kuo <[email protected]> | ||
# SPDX-License-Identifier: BSD-2-Clause | ||
# embedfire rise pro FPGA: https://detail.tmall.com/item.htm?id=645153441975 | ||
|
||
from migen import * | ||
|
||
from litex.gen import * | ||
|
||
from litex_boards.platforms import embedfire_rise_pro | ||
|
||
from litex.soc.cores.clock import * | ||
from litex.soc.integration.soc import SoCRegion | ||
from litex.soc.integration.soc_core import * | ||
from litex.soc.integration.builder import * | ||
from litex.soc.cores.led import LedChaser | ||
from litex.soc.cores.gpio import GPIOIn | ||
from litex.soc.cores.xadc import XADC | ||
from litex.soc.cores.dna import DNA | ||
from litex.soc.cores.pwm import PWM | ||
|
||
from litedram.modules import MT41K256M16 | ||
from litedram.phy import s7ddrphy | ||
|
||
from liteeth.phy.mii import LiteEthPHYMII | ||
|
||
# CRG ---------------------------------------------------------------------------------------------- | ||
|
||
class _CRG(LiteXModule): | ||
def __init__(self, platform, sys_clk_freq, with_dram=True, with_rst=True): | ||
self.rst = Signal() | ||
self.cd_sys = ClockDomain() | ||
if with_dram: | ||
self.cd_sys4x = ClockDomain() | ||
self.cd_sys4x_dqs = ClockDomain() | ||
self.cd_idelay = ClockDomain() | ||
|
||
# # # | ||
|
||
# Clk/Rst. | ||
clk50 = platform.request("clk50") | ||
rst = ~platform.request("cpu_reset") if with_rst else 0 | ||
|
||
# PLL. | ||
self.pll = pll = S7PLL(speedgrade=-1) | ||
self.comb += pll.reset.eq(rst | self.rst) | ||
pll.register_clkin(clk50, 50e6) | ||
pll.create_clkout(self.cd_sys, sys_clk_freq) | ||
platform.add_false_path_constraints(self.cd_sys.clk, pll.clkin) # Ignore sys_clk to pll.clkin path created by SoC's rst. | ||
if with_dram: | ||
pll.create_clkout(self.cd_sys4x, 4*sys_clk_freq) | ||
pll.create_clkout(self.cd_sys4x_dqs, 4*sys_clk_freq, phase=90) | ||
pll.create_clkout(self.cd_idelay, 200e6) | ||
|
||
# IdelayCtrl. | ||
if with_dram: | ||
self.idelayctrl = S7IDELAYCTRL(self.cd_idelay) | ||
|
||
# BaseSoC ------------------------------------------------------------------------------------------ | ||
|
||
class BaseSoC(SoCCore): | ||
def __init__(self, variant="a7-35", toolchain="vivado", sys_clk_freq=50e6, | ||
with_xadc = False, | ||
with_dna = False, | ||
with_ethernet = False, | ||
with_etherbone = False, | ||
eth_ip = "192.168.1.50", | ||
remote_ip = None, | ||
eth_dynamic_ip = False, | ||
with_led_chaser = True, | ||
with_buttons = False, | ||
with_beeper = True, | ||
**kwargs): | ||
platform = embedfire_rise_pro.Platform(variant=variant, toolchain=toolchain) | ||
|
||
# CRG -------------------------------------------------------------------------------------- | ||
with_dram = (kwargs.get("integrated_main_ram_size", 0) == 0) | ||
self.crg = _CRG(platform, sys_clk_freq, with_dram) | ||
|
||
# SoCCore ---------------------------------------------------------------------------------- | ||
SoCCore.__init__(self, platform, sys_clk_freq, ident="LiteX SoC on embedfire", **kwargs) | ||
|
||
# XADC ------------------------------------------------------------------------------------- | ||
if with_xadc: | ||
self.xadc = XADC() | ||
|
||
# DNA -------------------------------------------------------------------------------------- | ||
if with_dna: | ||
self.dna = DNA() | ||
self.dna.add_timing_constraints(platform, sys_clk_freq, self.crg.cd_sys.clk) | ||
|
||
# DDR3 SDRAM ------------------------------------------------------------------------------- | ||
if not self.integrated_main_ram_size: | ||
self.ddrphy = s7ddrphy.A7DDRPHY(platform.request("ddram"), | ||
memtype = "DDR3", | ||
nphases = 4, | ||
sys_clk_freq = sys_clk_freq) | ||
self.add_sdram("sdram", | ||
phy = self.ddrphy, | ||
module = MT41K256M16(sys_clk_freq, "1:4"), | ||
l2_cache_size = kwargs.get("l2_size", 8192) | ||
) | ||
|
||
# Ethernet / Etherbone --------------------------------------------------------------------- | ||
if with_ethernet or with_etherbone: | ||
self.ethphy = LiteEthPHYMII( | ||
clock_pads = self.platform.request("eth_clocks"), | ||
pads = self.platform.request("eth")) | ||
if with_etherbone: | ||
self.add_etherbone(phy=self.ethphy, ip_address=eth_ip, with_ethmac=with_ethernet) | ||
elif with_ethernet: | ||
self.add_ethernet(phy=self.ethphy, dynamic_ip=eth_dynamic_ip, local_ip=eth_ip, remote_ip=remote_ip) | ||
|
||
# Leds ------------------------------------------------------------------------------------- | ||
if with_led_chaser: | ||
self.leds = LedChaser( | ||
pads = platform.request_all("user_led"), | ||
sys_clk_freq = sys_clk_freq, | ||
) | ||
self.leds.add_pwm() | ||
|
||
# Buttons ---------------------------------------------------------------------------------- | ||
if with_buttons: | ||
self.buttons = GPIOIn( | ||
pads = platform.request_all("user_btn"), | ||
with_irq = self.irq.enabled | ||
) | ||
|
||
# Beeper------------------------------------------------------------------------------------ | ||
self.beeper = PWM( | ||
pwm=platform.request("beeper", 0), | ||
with_csr = True, | ||
default_enable = False, | ||
default_width = 0x800, | ||
default_period = 0xfff, | ||
) | ||
|
||
self.fan_pwm = PWM( | ||
pwm=platform.request("fan", 0), | ||
with_csr = True, | ||
default_enable = False, | ||
default_width = 0x800, | ||
default_period = 0xfff, | ||
) | ||
|
||
# Build -------------------------------------------------------------------------------------------- | ||
|
||
def main(): | ||
from litex.build.parser import LiteXArgumentParser | ||
parser = LiteXArgumentParser(platform=embedfire_rise_pro.Platform, description="LiteX SoC on embedfire rise pro.") | ||
parser.add_target_argument("--flash", action="store_true", help="Flash bitstream.") | ||
parser.add_target_argument("--variant", default="a7-35", help="Board variant (a7-35 or a7-100 or a7-200).") | ||
parser.add_target_argument("--sys-clk-freq", default=50e6, type=float, help="System clock frequency.") | ||
parser.add_target_argument("--with-xadc", action="store_true", help="Enable 7-Series XADC.") | ||
parser.add_target_argument("--with-dna", action="store_true", help="Enable 7-Series DNA.") | ||
# parser.add_target_argument("--with-usb", action="store_true", help="Enable USB Host.") | ||
parser.add_target_argument("--with-ethernet", action="store_true", help="Enable Ethernet support.") | ||
parser.add_target_argument("--with-etherbone", action="store_true", help="Enable Etherbone support.") | ||
parser.add_target_argument("--eth-ip", default="192.168.1.50", help="Ethernet/Etherbone IP address.") | ||
parser.add_target_argument("--remote-ip", default="192.168.1.100", help="Remote IP address of TFTP server.") | ||
parser.add_target_argument("--eth-dynamic-ip", action="store_true", help="Enable dynamic Ethernet IP addresses setting.") | ||
sdopts = parser.target_group.add_mutually_exclusive_group() | ||
sdopts.add_argument("--with-spi-sdcard", action="store_true", help="Enable SPI-mode SDCard support.") | ||
sdopts.add_argument("--with-sdcard", action="store_true", help="Enable SDCard support.") | ||
# parser.add_target_argument("--sdcard-adapter", help="SDCard PMOD adapter (digilent or numato).") | ||
# parser.add_target_argument("--with-spi-flash", action="store_true", help="Enable SPI Flash (MMAPed).") | ||
# parser.add_target_argument("--with-pmod-gpio", action="store_true", help="Enable GPIOs through PMOD.") # FIXME: Temporary test. | ||
# parser.add_target_argument("--with-can", action="store_true", help="Enable CAN support (Through CTU-CAN-FD Core and SN65HVD230 'PMOD'.") | ||
args = parser.parse_args() | ||
|
||
assert not (args.with_etherbone and args.eth_dynamic_ip) | ||
|
||
soc = BaseSoC( | ||
variant = args.variant, | ||
toolchain = args.toolchain, | ||
sys_clk_freq = args.sys_clk_freq, | ||
with_xadc = args.with_xadc, | ||
with_dna = args.with_dna, | ||
with_ethernet = args.with_ethernet, | ||
with_etherbone = args.with_etherbone, | ||
eth_ip = args.eth_ip, | ||
remote_ip = args.remote_ip, | ||
eth_dynamic_ip = args.eth_dynamic_ip, | ||
# with_usb = args.with_usb, | ||
# with_spi_flash = args.with_spi_flash, | ||
# with_pmod_gpio = args.with_pmod_gpio, | ||
# with_can = args.with_can, | ||
**parser.soc_argdict | ||
) | ||
|
||
# if args.sdcard_adapter == "numato": | ||
# soc.platform.add_extension(embedfire_rise_pro._numato_sdcard_pmod_io) | ||
# else: | ||
# soc.platform.add_extension(embedfire_rise_pro._sdcard_pmod_io) | ||
if args.with_spi_sdcard: | ||
soc.add_spi_sdcard() | ||
if args.with_sdcard: | ||
soc.add_sdcard() | ||
|
||
builder = Builder(soc, **parser.builder_argdict) | ||
if args.build: | ||
builder.build(**parser.toolchain_argdict) | ||
|
||
if args.load: | ||
prog = soc.platform.create_programmer() | ||
prog.load_bitstream(builder.get_bitstream_filename(mode="sram")) | ||
|
||
if args.flash: | ||
prog = soc.platform.create_programmer() | ||
prog.flash(0, builder.get_bitstream_filename(mode="flash")) | ||
|
||
if __name__ == "__main__": | ||
main() |