2021-02-25 00:22:56 -05:00
|
|
|
#!/usr/bin/env python3
|
|
|
|
|
|
|
|
#
|
|
|
|
# This file is part of LiteX-Boards.
|
|
|
|
#
|
|
|
|
# Copyright (c) 2019 msloniewski <marcin.sloniewski@gmail.com>
|
|
|
|
# SPDX-License-Identifier: BSD-2-Clause
|
|
|
|
|
2022-02-01 05:30:26 -05:00
|
|
|
# Build/Use:
|
|
|
|
# ./terasic_deca.py --uart-name jtag_uart --build --load
|
|
|
|
# litex_term --jtag-config ../prog/openocd_max10_blaster2.cfg jtag
|
|
|
|
|
2021-02-25 00:22:56 -05:00
|
|
|
from migen import *
|
2022-05-02 06:42:04 -04:00
|
|
|
from litex_boards.platforms import terasic_deca
|
2021-02-25 00:22:56 -05:00
|
|
|
|
2023-02-23 03:09:33 -05:00
|
|
|
from litex.gen import *
|
2022-10-27 10:58:55 -04:00
|
|
|
|
2021-03-26 17:12:13 -04:00
|
|
|
from litex.soc.cores.clock import Max10PLL
|
|
|
|
from litex.soc.integration.soc_core import *
|
|
|
|
from litex.soc.integration.builder import *
|
|
|
|
from litex.soc.cores.video import VideoDVIPHY
|
|
|
|
from litex.soc.cores.led import LedChaser
|
2022-01-27 19:56:21 -05:00
|
|
|
|
|
|
|
from liteeth.phy.mii import LiteEthPHYMII
|
2021-02-25 00:22:56 -05:00
|
|
|
|
|
|
|
# CRG ----------------------------------------------------------------------------------------------
|
|
|
|
|
2022-10-27 10:58:55 -04:00
|
|
|
class _CRG(LiteXModule):
|
2021-03-26 17:12:13 -04:00
|
|
|
def __init__(self, platform, sys_clk_freq, with_usb_pll=False):
|
2022-10-27 10:58:55 -04:00
|
|
|
self.rst = Signal()
|
|
|
|
self.cd_sys = ClockDomain()
|
|
|
|
self.cd_hdmi = ClockDomain()
|
|
|
|
self.cd_usb = ClockDomain()
|
2021-02-25 00:22:56 -05:00
|
|
|
|
|
|
|
# # #
|
|
|
|
|
2021-03-26 17:12:13 -04:00
|
|
|
# Clk / Rst.
|
|
|
|
clk50 = platform.request("clk50")
|
2021-03-25 22:38:26 -04:00
|
|
|
|
2021-03-26 17:12:13 -04:00
|
|
|
# PLL
|
2022-10-27 10:58:55 -04:00
|
|
|
self.pll = pll = Max10PLL(speedgrade="-6")
|
2021-02-25 00:22:56 -05:00
|
|
|
self.comb += pll.reset.eq(self.rst)
|
2021-03-26 17:12:13 -04:00
|
|
|
pll.register_clkin(clk50, 50e6)
|
2021-03-09 09:02:30 -05:00
|
|
|
pll.create_clkout(self.cd_sys, sys_clk_freq)
|
|
|
|
pll.create_clkout(self.cd_hdmi, 40e6)
|
2021-02-25 00:22:56 -05:00
|
|
|
|
2021-03-26 17:12:13 -04:00
|
|
|
# USB PLL.
|
|
|
|
if with_usb_pll:
|
|
|
|
ulpi = platform.request("ulpi")
|
|
|
|
self.comb += ulpi.cs.eq(1) # Enable ULPI chip to enable the ULPI clock.
|
2022-10-27 10:58:55 -04:00
|
|
|
self.usb_pll = pll = Max10PLL(speedgrade="-6")
|
2021-03-26 17:12:13 -04:00
|
|
|
self.comb += pll.reset.eq(self.rst)
|
|
|
|
pll.register_clkin(ulpi.clk, 60e6)
|
|
|
|
pll.create_clkout(self.cd_usb, 60e6, phase=-120) # -120° from DECA's example (also validated with LUNA).
|
2021-03-25 22:38:26 -04:00
|
|
|
|
2021-02-25 00:22:56 -05:00
|
|
|
# BaseSoC ------------------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
class BaseSoC(SoCCore):
|
2022-11-08 06:29:11 -05:00
|
|
|
def __init__(self, sys_clk_freq=50e6,
|
|
|
|
with_led_chaser = True,
|
|
|
|
with_uartbone = False,
|
|
|
|
with_jtagbone = False,
|
|
|
|
with_video_terminal = False,
|
2022-12-27 20:13:06 -05:00
|
|
|
with_spi_sdcard = False,
|
2022-11-08 06:29:11 -05:00
|
|
|
with_ethernet = False,
|
|
|
|
with_etherbone = False,
|
|
|
|
eth_ip = "192.168.1.50",
|
|
|
|
eth_dynamic_ip = False,
|
|
|
|
**kwargs):
|
2022-05-02 06:42:04 -04:00
|
|
|
self.platform = platform = terasic_deca.Platform()
|
2021-03-25 22:38:26 -04:00
|
|
|
|
2022-04-21 06:17:26 -04:00
|
|
|
# CRG --------------------------------------------------------------------------------------
|
2022-10-27 10:58:55 -04:00
|
|
|
self.crg = self.crg = _CRG(platform, sys_clk_freq, with_usb_pll=False)
|
2022-04-21 06:17:26 -04:00
|
|
|
|
|
|
|
# SoCCore ----------------------------------------------------------------------------------
|
2021-03-26 17:12:13 -04:00
|
|
|
# Defaults to JTAG-UART since no hardware UART.
|
2022-01-27 17:12:52 -05:00
|
|
|
real_uart_name = kwargs["uart_name"]
|
|
|
|
if real_uart_name == "serial":
|
|
|
|
if with_jtagbone:
|
|
|
|
kwargs["uart_name"] = "crossover"
|
|
|
|
else:
|
2022-02-01 05:30:26 -05:00
|
|
|
kwargs["uart_name"] = "jtag_uart"
|
2022-01-27 17:12:52 -05:00
|
|
|
if with_uartbone:
|
|
|
|
kwargs["uart_name"] = "crossover"
|
2022-04-21 06:17:26 -04:00
|
|
|
SoCCore.__init__(self, platform, sys_clk_freq, ident="LiteX SoC on Terasic DECA", **kwargs)
|
2021-03-26 17:12:13 -04:00
|
|
|
|
2022-01-27 17:12:52 -05:00
|
|
|
# UARTbone ---------------------------------------------------------------------------------
|
|
|
|
if with_uartbone:
|
2023-07-20 09:42:47 -04:00
|
|
|
self.add_uartbone(uart_name=real_uart_name, baudrate=kwargs["uart_baudrate"])
|
2022-01-27 17:12:52 -05:00
|
|
|
|
|
|
|
# JTAGbone ---------------------------------------------------------------------------------
|
|
|
|
if with_jtagbone:
|
|
|
|
self.add_jtagbone()
|
2022-12-27 20:13:06 -05:00
|
|
|
|
2022-01-27 19:56:21 -05:00
|
|
|
# Ethernet ---------------------------------------------------------------------------------
|
|
|
|
if with_ethernet or with_etherbone:
|
|
|
|
self.platform.toolchain.additional_sdc_commands += [
|
|
|
|
'create_clock -name eth_rx_clk -period 40.0 [get_ports {eth_clocks_rx}]',
|
|
|
|
'create_clock -name eth_tx_clk -period 40.0 [get_ports {eth_clocks_tx}]',
|
|
|
|
'set_false_path -from [get_clocks {sys_clk}] -to [get_clocks {eth_rx_clk}]',
|
|
|
|
'set_false_path -from [get_clocks {sys_clk}] -to [get_clocks {eth_tx_clk}]',
|
|
|
|
'set_false_path -from [get_clocks {eth_rx_clk}] -to [get_clocks {eth_tx_clk}]',
|
|
|
|
]
|
2022-10-27 10:58:55 -04:00
|
|
|
self.ethphy = LiteEthPHYMII(
|
2022-01-27 19:56:21 -05:00
|
|
|
clock_pads = self.platform.request("eth_clocks"),
|
|
|
|
pads = self.platform.request("eth"))
|
|
|
|
if with_ethernet:
|
|
|
|
self.add_ethernet(phy=self.ethphy, dynamic_ip=eth_dynamic_ip)
|
|
|
|
if with_etherbone:
|
|
|
|
self.add_etherbone(phy=self.ethphy, ip_address=eth_ip)
|
|
|
|
|
2021-03-09 09:02:30 -05:00
|
|
|
# Video ------------------------------------------------------------------------------------
|
|
|
|
if with_video_terminal:
|
2022-10-27 10:58:55 -04:00
|
|
|
self.videophy = VideoDVIPHY(platform.request("hdmi"), clock_domain="hdmi")
|
2021-03-09 09:02:30 -05:00
|
|
|
self.add_video_terminal(phy=self.videophy, timings="800x600@60Hz", clock_domain="hdmi")
|
|
|
|
|
2022-12-27 20:13:06 -05:00
|
|
|
# SPI SD card ------------------------------------------------------------------------------
|
|
|
|
if with_spi_sdcard:
|
|
|
|
self.add_spi_sdcard()
|
|
|
|
|
|
|
|
sd_aux = self.platform.request("spisdcard_aux")
|
|
|
|
|
|
|
|
# Set the SD card supply to 3.3V
|
|
|
|
self.comb += sd_aux.sel.eq(0)
|
|
|
|
|
|
|
|
# Set the direction of the level shifter (0 = SD to FPGA; 1 = FPGA to SD)
|
|
|
|
self.comb += sd_aux.cmd_dir.eq(1)
|
|
|
|
self.comb += sd_aux.d0_dir.eq(0)
|
|
|
|
self.comb += sd_aux.d123_dir.eq(1)
|
|
|
|
|
|
|
|
# Keep the unused data lines high
|
|
|
|
self.comb += sd_aux.dat1.eq(1)
|
|
|
|
self.comb += sd_aux.dat2.eq(1)
|
|
|
|
|
2021-03-26 17:12:13 -04:00
|
|
|
# Leds -------------------------------------------------------------------------------------
|
2021-07-06 17:39:37 -04:00
|
|
|
if with_led_chaser:
|
2022-10-27 10:58:55 -04:00
|
|
|
self.leds = LedChaser(
|
2021-07-06 17:39:37 -04:00
|
|
|
pads = platform.request_all("user_led"),
|
|
|
|
sys_clk_freq = sys_clk_freq)
|
2021-03-26 17:12:13 -04:00
|
|
|
|
2021-02-25 00:22:56 -05:00
|
|
|
# Build --------------------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
def main():
|
2022-11-06 15:39:52 -05:00
|
|
|
from litex.build.parser import LiteXArgumentParser
|
2022-11-08 04:41:35 -05:00
|
|
|
parser = LiteXArgumentParser(platform=terasic_deca.Platform, description="LiteX SoC on DECA.")
|
|
|
|
parser.add_target_argument("--sys-clk-freq", default=50e6, type=float, help="System clock frequency.")
|
2022-11-05 03:07:14 -04:00
|
|
|
ethopts = parser.target_group.add_mutually_exclusive_group()
|
2022-11-08 04:41:35 -05:00
|
|
|
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_target_argument("--eth-ip", default="192.168.1.50", help="Ethernet/Etherbone IP address.")
|
|
|
|
parser.add_target_argument("--eth-dynamic-ip", action="store_true", help="Enable dynamic Ethernet IP addresses setting.")
|
|
|
|
parser.add_target_argument("--with-uartbone", action="store_true", help="Enable UARTbone support.")
|
|
|
|
parser.add_target_argument("--with-jtagbone", action="store_true", help="Enable JTAGbone support.")
|
|
|
|
parser.add_target_argument("--with-video-terminal", action="store_true", help="Enable Video Terminal (VGA).")
|
2022-12-27 20:13:06 -05:00
|
|
|
parser.add_target_argument("--with-spi-sdcard", action="store_true", help="Enable SPI SD card controller.")
|
2021-02-25 00:22:56 -05:00
|
|
|
args = parser.parse_args()
|
|
|
|
|
|
|
|
soc = BaseSoC(
|
2022-11-08 04:41:35 -05:00
|
|
|
sys_clk_freq = args.sys_clk_freq,
|
|
|
|
with_ethernet = args.with_ethernet,
|
|
|
|
with_etherbone = args.with_etherbone,
|
|
|
|
eth_ip = args.eth_ip,
|
|
|
|
eth_dynamic_ip = args.eth_dynamic_ip,
|
|
|
|
with_uartbone = args.with_uartbone,
|
|
|
|
with_jtagbone = args.with_jtagbone,
|
|
|
|
with_video_terminal = args.with_video_terminal,
|
2022-12-27 20:13:06 -05:00
|
|
|
with_spi_sdcard = args.with_spi_sdcard,
|
2022-11-07 02:43:26 -05:00
|
|
|
**parser.soc_argdict
|
2021-02-25 00:22:56 -05:00
|
|
|
)
|
2022-11-05 03:07:14 -04:00
|
|
|
builder = Builder(soc, **parser.builder_argdict)
|
2022-05-06 09:14:32 -04:00
|
|
|
if args.build:
|
2022-11-05 03:07:14 -04:00
|
|
|
builder.build(**parser.toolchain_argdict)
|
2021-02-25 00:22:56 -05:00
|
|
|
|
|
|
|
if args.load:
|
|
|
|
prog = soc.platform.create_programmer()
|
2022-03-17 04:21:05 -04:00
|
|
|
prog.load_bitstream(builder.get_bitstream_filename(mode="sram"))
|
2021-02-25 00:22:56 -05:00
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
main()
|