Files
hackrf/firmware/fpga/board.py
Michael Ossmann 409acbc3c9 Add support for HackRF Pro (code name: Praline)
Co-authored-by: mndza <diego.hdmp@gmail.com>
Co-authored-by: Martin Ling <martin-git@earth.li>
Co-authored-by: Antoine van Gelder <antoine@greatscottgadgets.com>
2025-11-24 20:53:41 -05:00

91 lines
3.2 KiB
Python

#!/usr/bin/env python3
#
# This file is part of HackRF.
#
# Copyright (c) 2024 Great Scott Gadgets <info@greatscottgadgets.com>
# SPDX-License-Identifier: BSD-3-Clause
from amaranth import Elaboratable, Signal, Instance, Module, ClockDomain
from amaranth.build import Resource, Pins, Clock, Attrs
from amaranth.vendor import LatticeICE40Platform
from amaranth_boards.resources import SPIResource
__all__ = ["PralinePlatform", "ClockDomainGenerator"]
class PralinePlatform(LatticeICE40Platform):
device = "iCE40UP5K"
package = "SG48"
default_clk = "SB_HFOSC" # 48 MHz internal oscillator
hfosc_div = 0 # Do not divide
resources = [
Resource("fpga_clk", 0, Pins("39", dir="i"),
Attrs(GLOBAL=True, IO_STANDARD="SB_LVCMOS")),
# ADC/DAC interfaces.
Resource("afe_clk", 0, Pins("35", dir="i"),
Clock(40e6), Attrs(GLOBAL=True, IO_STANDARD="SB_LVCMOS")),
Resource("dd", 0, Pins("38 37 36 34 32 31 28 27 26 25", dir="o"),
Attrs(IO_STANDARD="SB_LVCMOS")),
Resource("da", 0, Pins("46 45 44 43 42 41 40 39", dir="i"),
Attrs(IO_STANDARD="SB_LVCMOS")),
# SGPIO interface.
Resource("host_clk", 0, Pins("20", dir="o"),
Attrs(IO_STANDARD="SB_LVCMOS")),
Resource("host_data", 0, Pins("21 19 6 13 10 3 4 18", dir="io"),
Attrs(IO_STANDARD="SB_LVCMOS")),
Resource("q_invert", 0, Pins("9", dir="i"),
Attrs(IO_STANDARD="SB_LVCMOS")),
Resource("direction", 0, Pins("12", dir="i"),
Attrs(IO_STANDARD="SB_LVCMOS")),
Resource("disable", 0, Pins("23", dir="i"),
Attrs(IO_STANDARD="SB_LVCMOS")),
Resource("capture_en", 0, Pins("11", dir="o"),
Attrs(IO_STANDARD="SB_LVCMOS")),
Resource("trigger_in", 0, Pins("48", dir="i"),
Attrs(IO_STANDARD="SB_LVCMOS")),
Resource("trigger_out", 0, Pins("2", dir="o"),
Attrs(IO_STANDARD="SB_LVCMOS")),
# SPI can be used after configuration.
SPIResource("spi", 0, role="peripheral",
cs_n="16", clk="15", copi="17", cipo="14",
attrs=Attrs(IO_STANDARD="SB_LVCMOS"),
),
]
connectors = []
class ClockDomainGenerator(Elaboratable):
@staticmethod
def lut_delay(m, signal, *, depth):
signal_out = signal
for i in range(depth):
signal_in = signal_out
signal_out = Signal()
m.submodules += Instance("SB_LUT4",
p_LUT_INIT=0xAAAA, # Buffer configuration
i_I0=signal_in,
o_O=signal_out,
)
return signal_out
def elaborate(self, platform):
m = Module()
# Define clock domains.
m.domains.gck1 = cd_gck1 = ClockDomain(name="gck1", reset_less=True) # analog front-end clock.
# We need to delay `gck1` clock by at least 8ns, not possible with the PLL alone.
# Each LUT introduces a minimum propagation delay of 9ns (best case).
delayed_gck1 = self.lut_delay(m, platform.request("afe_clk").i, depth=2)
m.d.comb += cd_gck1.clk.eq(delayed_gck1)
platform.add_clock_constraint(delayed_gck1, 40e6)
return m