217 lines
8.2 KiB
Python
217 lines
8.2 KiB
Python
#
|
|
# This file is part of LUNA.
|
|
#
|
|
# Copyright (c) 2020 Great Scott Gadgets <info@greatscottgadgets.com>
|
|
# SPDX-License-Identifier: BSD-3-Clause
|
|
"""
|
|
The DE0 Nano does not have an explicit USB port. Instead, you'll need to connect an external ULPI PHY breakout,
|
|
such as https://www.waveshare.com/wiki/USB3300_USB_HS_Board.
|
|
|
|
See the pin definitions below for connection information (ULPIResource).
|
|
|
|
The DE0 Nano is an -unsupported- platform! To use it, you'll need to set your LUNA_PLATFORM variable:
|
|
> export LUNA_PLATFORM="luna.gateware.platform.de0_nano:DE0NanoPlatform"
|
|
"""
|
|
|
|
import os
|
|
import logging
|
|
import subprocess
|
|
|
|
from amaranth import *
|
|
from amaranth.build import *
|
|
from amaranth.vendor.intel import IntelPlatform
|
|
|
|
from amaranth_boards.resources import *
|
|
|
|
from luna.gateware.platform.core import LUNAPlatform
|
|
|
|
__all__ = ["DE0NanoPlatform"]
|
|
|
|
|
|
class DE0NanoClockAndResetController(Elaboratable):
|
|
""" Controller for de0_nano's clocking and global resets. """
|
|
def __init__(self, *, clock_frequencies=None, clock_signal_name=None):
|
|
pass
|
|
|
|
def elaborate(self, platform):
|
|
m = Module()
|
|
|
|
# Create our domains; but don't do anything else for them, for now.
|
|
m.domains.sync = ClockDomain()
|
|
m.domains.usb = ClockDomain()
|
|
m.domains.jt51 = ClockDomain()
|
|
m.domains.adat = ClockDomain()
|
|
|
|
m.submodules.mainpll = Instance("ALTPLL",
|
|
p_BANDWIDTH_TYPE = "AUTO",
|
|
p_CLK0_DIVIDE_BY = 1,
|
|
p_CLK0_DUTY_CYCLE = 50,
|
|
p_CLK0_MULTIPLY_BY = 1,
|
|
p_CLK0_PHASE_SHIFT = 0,
|
|
p_INCLK0_INPUT_FREQUENCY = 16666,
|
|
p_OPERATION_MODE = "NORMAL",
|
|
|
|
# Drive our clock from the USB clock
|
|
# coming from the USB clock pin of the USB3300
|
|
i_inclk = ClockSignal("usb"),
|
|
o_clk = ClockSignal("sync"),
|
|
)
|
|
|
|
m.submodules.jt51pll = Instance("ALTPLL",
|
|
p_BANDWIDTH_TYPE = "AUTO",
|
|
p_CLK0_DIVIDE_BY = 218,
|
|
p_CLK0_DUTY_CYCLE = 50,
|
|
p_CLK0_MULTIPLY_BY = 13,
|
|
p_CLK0_PHASE_SHIFT = 0,
|
|
p_INCLK0_INPUT_FREQUENCY = 16666,
|
|
p_OPERATION_MODE = "NORMAL",
|
|
|
|
# Drive our clock from the USB clock
|
|
# coming from the USB clock pin of the USB3300
|
|
i_inclk = ClockSignal("usb"),
|
|
o_clk = ClockSignal("jt51"),
|
|
)
|
|
|
|
m.submodules.adatpll = Instance("ALTPLL",
|
|
p_BANDWIDTH_TYPE = "AUTO",
|
|
p_CLK0_DIVIDE_BY = 83,
|
|
p_CLK0_DUTY_CYCLE = 50,
|
|
p_CLK0_MULTIPLY_BY = 17,
|
|
p_CLK0_PHASE_SHIFT = 0,
|
|
p_INCLK0_INPUT_FREQUENCY = 16666,
|
|
p_OPERATION_MODE = "NORMAL",
|
|
|
|
# Drive our clock from the USB clock
|
|
# coming from the USB clock pin of the USB3300
|
|
i_inclk = ClockSignal("usb"),
|
|
o_clk = ClockSignal("adat"),
|
|
)
|
|
|
|
# Use a blinky to see if the clock signal works
|
|
# from amaranth_boards.test.blinky import Blinky
|
|
# m.submodules += Blinky()
|
|
|
|
return m
|
|
|
|
class DE0NanoPlatform(IntelPlatform, LUNAPlatform):
|
|
""" This is a de0_nano board with an USB3300 PHY attached to JP_2 """
|
|
|
|
name = "de0_nano"
|
|
device = "EP4CE22"
|
|
package = "F17"
|
|
speed = "C6"
|
|
|
|
default_clk = "clk_50MHz"
|
|
clock_domain_generator = DE0NanoClockAndResetController
|
|
default_usb_connection = "ulpi"
|
|
ignore_phy_vbus = True
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
logging.warning("This platform is not officially supported, and thus not tested. Your results may vary.")
|
|
logging.warning("Note also that this platform does not use the DE0 nano's main USB port!")
|
|
logging.warning("You'll need to connect a ULPI PHY breakout. See the platform file for more info.")
|
|
|
|
super().__init__(*args, **kwargs)
|
|
|
|
#
|
|
# I/O resources.
|
|
#
|
|
resources = [
|
|
# Primary clock generator clocks.
|
|
Resource("clk_50MHz", 0, Pins("R8", dir="i"), Clock(50e6), Attrs(io_standard="3.3-V LVTTL")),
|
|
|
|
# USB2 / ULPI section of the USB3300.
|
|
ULPIResource("ulpi", 0,
|
|
data="JP_2:27 JP_2:25 JP_2:23 JP_2:21 JP_2:19 JP_2:17 JP_2:15 JP_2:13",
|
|
clk="JP_2:1", # this needs to be a clock pin of the FPGA or the core won't work
|
|
dir="JP_2:18", nxt="JP_2:16", stp="JP_2:14", rst="JP_2:22",
|
|
attrs=Attrs(io_standard="3.3-V LVCMOS")
|
|
),
|
|
|
|
UARTResource(0,
|
|
# GND on JP1 Pin 12.
|
|
rx="JP_1:8", tx="JP_1:10",
|
|
attrs=Attrs(io_standard="3.3-V LVTTL")),
|
|
|
|
*LEDResources(
|
|
pins="A15 A13 B13 A11 D1 F3 B1 L3",
|
|
attrs=Attrs(io_standard="3.3-V LVTTL")),
|
|
|
|
*ButtonResources(
|
|
pins="J15 E1", invert=True,
|
|
attrs=Attrs(io_standard="3.3-V LVTTL")),
|
|
|
|
*SwitchResources(
|
|
pins="M1 T8 B9 M15",
|
|
attrs=Attrs(io_standard="3.3-V LVTTL")),
|
|
|
|
SDRAMResource(0,
|
|
clk="R4", cke="L7", cs_n="P6", we_n="C2", ras_n="L2", cas_n="L1",
|
|
ba="M7 M6", a="P2 N5 N6 M8 P8 T7 N8 T6 R1 P1 N2 N1 L4",
|
|
dq="G2 G1 L8 K5 K2 J2 J1 R7 T4 T2 T3 R3 R5 P3 N3 K1", dqm="R6 T5",
|
|
attrs=Attrs(io_standard="3.3-V LVTTL")),
|
|
|
|
# Accelerometer
|
|
Resource("acc", 0,
|
|
Subsignal("cs_n", Pins("G5", dir="o")),
|
|
Subsignal("int", Pins("M2", dir="i")),
|
|
Attrs(io_standard="3.3-V LVTTL")),
|
|
# I2C is part of the Accelerometer
|
|
I2CResource(0,
|
|
scl="F2", sda="F1",
|
|
attrs=Attrs(io_standard="3.3-V LVTTL")),
|
|
|
|
# ADC
|
|
Resource("adc", 0,
|
|
Subsignal("cs_n", Pins("A10")),
|
|
Subsignal("saddr", Pins("B10")),
|
|
Subsignal("sclk", Pins("B14")),
|
|
Subsignal("sdat", Pins("A9")),
|
|
Attrs(io_standard="3.3-V LVTTL")),
|
|
|
|
# ECPS
|
|
Resource("epcs", 0,
|
|
Subsignal("data0", Pins("H2")),
|
|
Subsignal("dclk", Pins("H1")),
|
|
Subsignal("ncs0", Pins("D2")),
|
|
Subsignal("asd0", Pins("C1")),
|
|
Attrs(io_standard="3.3-V LVTTL")),
|
|
|
|
Resource("adat", 0,
|
|
Subsignal("tx", Pins("JP_3:5", dir="o")),
|
|
Subsignal("rx", Pins("JP_3:6", dir="i")),
|
|
Attrs(io_standard="3.3-V LVTTL")),
|
|
]
|
|
|
|
connectors = [
|
|
# PIN 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
|
|
Connector("JP", 1, "A8 D3 B8 C3 A2 A3 B3 B4 A4 B5 - - A5 D5 B6 A6 B7 D6 A7 C6 C8 E6 E7 D8 E8 F8 F9 E9 - - C9 D9 E11 E10 C11 B11 A12 D11 D12 B12"),
|
|
Connector("JP", 2, "T9 F13 R9 T15 T14 T13 R13 T12 R12 T11 - - T10 R11 P11 R10 N12 P9 N9 N11 L16 K16 R16 L15 P15 P16 R14 N16 - - N15 P14 L14 N14 M10 L13 J16 K15 J13 J14"),
|
|
Connector("JP", 3, "- E15 E16 M16 A14 B16 C14 C16 C15 D16 D15 D14 F15 F16 F14 G16 G15 - - - - - - - - -")
|
|
]
|
|
|
|
@property
|
|
def file_templates(self):
|
|
templates = super().file_templates
|
|
templates["{{name}}.qsf"] += r"""
|
|
set_global_assignment -name OPTIMIZATION_MODE "Aggressive Performance"
|
|
set_global_assignment -name FITTER_EFFORT "Standard Fit"
|
|
set_global_assignment -name PHYSICAL_SYNTHESIS_EFFORT "Extra"
|
|
set_instance_assignment -name DECREASE_INPUT_DELAY_TO_INPUT_REGISTER OFF -to *ulpi*
|
|
set_instance_assignment -name INCREASE_DELAY_TO_OUTPUT_PIN OFF -to *ulpi*
|
|
set_global_assignment -name NUM_PARALLEL_PROCESSORS ALL
|
|
"""
|
|
templates["{{name}}.sdc"] += r"""
|
|
create_clock -name "clk_60MHz" -period 16.667 [get_ports "ulpi_0__clk__io"]
|
|
"""
|
|
return templates
|
|
|
|
|
|
def toolchain_program(self, products, name):
|
|
""" Programs the attached de0_nano board via a Quartus programming cable. """
|
|
|
|
quartus_pgm = os.environ.get("QUARTUS_PGM", "quartus_pgm")
|
|
with products.extract("{}.sof".format(name)) as bitstream_filename:
|
|
subprocess.check_call([quartus_pgm, "--haltcc", "--mode", "JTAG",
|
|
"--operation", "P;" + bitstream_filename])
|