Files
Adat/gateware/car.py
2026-03-13 19:58:28 +03:00

567 lines
19 KiB
Python

from amaranth import *
from amaranth.build import *
from amaranth.lib.cdc import ResetSynchronizer
from amaranth.lib.wiring import flipped
from amlib.utils import SimpleClockDivider
class ClockDomainGeneratorBase():
NO_PHASE_SHIFT = 0
def wire_up_reset(self, m, reset):
m.submodules.reset_sync_fast = ResetSynchronizer(reset, domain="fast")
m.submodules.reset_sync_usb = ResetSynchronizer(reset, domain="usb")
m.submodules.reset_sync_sync = ResetSynchronizer(reset, domain="sync")
m.submodules.reset_sync_dac = ResetSynchronizer(reset, domain="dac")
m.submodules.reset_sync_adat = ResetSynchronizer(reset, domain="adat")
class IntelCycloneIVClockDomainGenerator(Elaboratable, ClockDomainGeneratorBase):
ADAT_DIV_48k = 83
ADAT_MULT_48k = 17
ADAT_DIV_44_1k = 62
ADAT_MULT_44_1k = 14
DUTY_CYCLE = 50
def __init__(self, *, clock_frequencies=None, clock_signal_name=None):
pass
def elaborate(self, platform):
m = Module()
# Create our domains
m.domains.usb = ClockDomain("usb")
m.domains.sync = ClockDomain("sync")
m.domains.fast = ClockDomain("fast")
m.domains.adat = ClockDomain("adat")
m.domains.dac = ClockDomain("dac")
clk = flipped(platform.request(platform.default_clk))
main_clocks = Signal(5)
audio_clocks = Signal(4)
fast_clock_48k = Signal()
sys_locked = Signal()
audio_locked = Signal()
fast_locked = Signal()
reset = Signal()
m.submodules.mainpll = Instance("ALTPLL",
p_BANDWIDTH_TYPE = "AUTO",
# USB clock: 60MHz
p_CLK0_DIVIDE_BY = 5,
p_CLK0_DUTY_CYCLE = self.DUTY_CYCLE,
p_CLK0_MULTIPLY_BY = 6,
p_CLK0_PHASE_SHIFT = self.NO_PHASE_SHIFT,
# 44.1k ADAT Clock 11.2896 MHz = 44.1kHz * 256
p_CLK1_DIVIDE_BY = self.ADAT_DIV_44_1k,
p_CLK1_DUTY_CYCLE = self.DUTY_CYCLE,
p_CLK1_MULTIPLY_BY = self.ADAT_MULT_44_1k,
p_CLK1_PHASE_SHIFT = self.NO_PHASE_SHIFT,
# I2S DAC clock 44.1k = 3.072 MHz = 44.1kHz * 32 bit * 2 channels
p_CLK2_DIVIDE_BY = self.ADAT_DIV_44_1k * 4,
p_CLK2_DUTY_CYCLE = self.DUTY_CYCLE,
p_CLK2_MULTIPLY_BY = self.ADAT_MULT_44_1k,
p_CLK2_PHASE_SHIFT = self.NO_PHASE_SHIFT,
# ADAT sampling clock = 44.1kHz * 256 * 8 times oversampling
p_CLK3_DIVIDE_BY = self.ADAT_DIV_44_1k,
p_CLK3_DUTY_CYCLE = self.DUTY_CYCLE,
p_CLK3_MULTIPLY_BY = self.ADAT_MULT_44_1k * 8,
p_CLK3_PHASE_SHIFT = self.NO_PHASE_SHIFT,
# ADAT transmit domain clock = 44.1kHz * 5 output terminals
p_CLK4_DIVIDE_BY = self.ADAT_DIV_44_1k,
p_CLK4_DUTY_CYCLE = self.DUTY_CYCLE,
p_CLK4_MULTIPLY_BY = self.ADAT_MULT_44_1k * 5,
p_CLK4_PHASE_SHIFT = self.NO_PHASE_SHIFT,
# 50MHz = 20000 picoseconds
p_INCLK0_INPUT_FREQUENCY = 20000,
p_OPERATION_MODE = "NORMAL",
# Drive our clock from the USB clock
# coming from the USB clock pin of the USB3300
i_inclk = clk,
o_clk = main_clocks,
o_locked = sys_locked,
)
m.submodules.audiopll = Instance("ALTPLL",
p_BANDWIDTH_TYPE = "AUTO",
# ADAT clock = 12.288 MHz = 48 kHz * 256
p_CLK0_DIVIDE_BY = self.ADAT_DIV_48k,
p_CLK0_DUTY_CYCLE = self.DUTY_CYCLE,
p_CLK0_MULTIPLY_BY = self.ADAT_MULT_48k,
p_CLK0_PHASE_SHIFT = self.NO_PHASE_SHIFT,
# I2S DAC clock 48k = 3.072 MHz = 48 kHz * 32 bit * 2 channels
p_CLK1_DIVIDE_BY = self.ADAT_DIV_48k * 4,
p_CLK1_DUTY_CYCLE = self.DUTY_CYCLE,
p_CLK1_MULTIPLY_BY = self.ADAT_MULT_48k,
p_CLK1_PHASE_SHIFT = self.NO_PHASE_SHIFT,
# ADAT sampling clock = 48 kHz * 256 * 8 times oversampling
p_CLK2_DIVIDE_BY = self.ADAT_DIV_48k,
p_CLK2_DUTY_CYCLE = self.DUTY_CYCLE,
p_CLK2_MULTIPLY_BY = self.ADAT_MULT_48k * 8,
p_CLK2_PHASE_SHIFT = self.NO_PHASE_SHIFT,
# ADAT transmit domain clock = 48 kHz * 256 * 5 output terminals
p_CLK3_DIVIDE_BY = self.ADAT_DIV_48k,
p_CLK3_DUTY_CYCLE = self.DUTY_CYCLE,
p_CLK3_MULTIPLY_BY = self.ADAT_MULT_48k * 5,
p_CLK3_PHASE_SHIFT = self.NO_PHASE_SHIFT,
p_INCLK0_INPUT_FREQUENCY = 16667,
p_OPERATION_MODE = "NORMAL",
i_inclk = main_clocks[0],
o_clk = audio_clocks,
o_locked = audio_locked,
)
m.submodules.fastpll = Instance("ALTPLL",
p_BANDWIDTH_TYPE = "AUTO",
# ADAT sampling clock = 48 kHz * 256 * 8 times oversampling
p_CLK0_DIVIDE_BY = 1,
p_CLK0_DUTY_CYCLE = self.DUTY_CYCLE,
p_CLK0_MULTIPLY_BY = platform.fast_multiplier,
p_CLK0_PHASE_SHIFT = self.NO_PHASE_SHIFT,
p_INCLK0_INPUT_FREQUENCY = 81395,
p_OPERATION_MODE = "NORMAL",
i_inclk = audio_clocks[0],
o_clk = fast_clock_48k,
o_locked = fast_locked,
)
m.d.comb += [
reset.eq(~(sys_locked & audio_locked & fast_locked)),
ClockSignal("fast").eq(fast_clock_48k),
ClockSignal("usb") .eq(main_clocks[0]),
ClockSignal("adat").eq(audio_clocks[0]),
ClockSignal("dac").eq(audio_clocks[1]),
ClockSignal("sync").eq(audio_clocks[3]),
]
self.wire_up_reset(m, reset)
return m
class IntelCycloneVClockDomainGenerator(Elaboratable, ClockDomainGeneratorBase):
def __init__(self, *, clock_frequencies=None, clock_signal_name=None):
pass
def elaborate(self, platform):
m = Module()
# Create our domains
# usb: USB clock: 60MHz
# adat: ADAT clock = 12.288 MHz = 48 kHz * 256
# dac: I2S DAC clock 48k = 3.072 MHz = 48 kHz * 32 bit * 2 channels
# sync: ADAT transmit domain clock = 61.44 MHz = 48 kHz * 256 * 5 output terminals
# fast: ADAT sampling clock = 98.304 MHz = 48 kHz * 256 * 8 times oversampling
m.domains.usb = ClockDomain("usb")
m.domains.sync = ClockDomain("sync")
m.domains.fast = ClockDomain("fast")
m.domains.adat = ClockDomain("adat")
m.domains.dac = ClockDomain("dac")
clk = flipped(platform.request(platform.default_clk))
main_clock = Signal()
audio_clocks = Signal(4)
sys_locked = Signal()
audio_locked = Signal()
reset = Signal()
m.submodules.mainpll = Instance("altera_pll",
p_pll_type="General",
p_pll_subtype="General",
p_fractional_vco_multiplier="false",
p_operation_mode="normal",
p_reference_clock_frequency="50.0 MHz",
p_number_of_clocks="1",
p_output_clock_frequency0="60.000000 MHz",
# Drive our clock from the internal 50MHz clock
i_refclk = clk,
o_outclk = main_clock,
o_locked = sys_locked
)
m.submodules.audiopll = Instance("altera_pll",
p_pll_type="General",
p_pll_subtype="General",
p_fractional_vco_multiplier="true",
p_operation_mode="normal",
p_reference_clock_frequency="60.0 MHz",
p_number_of_clocks="4",
p_output_clock_frequency0="12.288000 MHz",
p_output_clock_frequency1="3.072000 MHz",
p_output_clock_frequency2="61.440000 MHz",
p_output_clock_frequency3="98.304000 MHz",
# Drive our clock from the mainpll
i_refclk=main_clock,
o_outclk=audio_clocks,
o_locked=audio_locked
)
m.d.comb += [
reset.eq(~(sys_locked & audio_locked)),
ClockSignal("usb") .eq(main_clock),
ClockSignal("adat").eq(audio_clocks[0]),
ClockSignal("dac").eq(audio_clocks[1]),
ClockSignal("sync").eq(audio_clocks[2]),
ClockSignal("fast").eq(audio_clocks[3])
]
self.wire_up_reset(m, reset)
return m
class Xilinx7SeriesClockDomainGenerator(Elaboratable, ClockDomainGeneratorBase):
ADAT_DIV_48k = 83
ADAT_MULT_48k = 17
DUTY_CYCLE = 0.5
def __init__(self, *, clock_frequencies=None, clock_signal_name=None):
pass
def elaborate(self, platform):
m = Module()
# Create our domains
m.domains.usb = ClockDomain("usb")
m.domains.sync = ClockDomain("sync")
m.domains.fast = ClockDomain("fast")
m.domains.adat = ClockDomain("adat")
m.domains.dac = ClockDomain("dac")
clk = flipped(platform.request(platform.default_clk))
main_clocks = Signal()
audio_clocks = Signal(4)
fast_clock_48k = Signal()
sys_locked = Signal()
audio_locked = Signal()
fast_locked = Signal()
reset = Signal()
mainpll_feedback = Signal()
audiopll_feedback = Signal()
fastpll_feedback = Signal()
m.submodules.mainpll = Instance("PLLE2_ADV",
p_CLKIN1_PERIOD = 20,
p_BANDWIDTH = "OPTIMIZED",
p_COMPENSATION = "ZHOLD",
p_STARTUP_WAIT = "FALSE",
p_DIVCLK_DIVIDE = 1,
p_CLKFBOUT_MULT = 30,
p_CLKFBOUT_PHASE = self.NO_PHASE_SHIFT,
# 60MHz
p_CLKOUT0_DIVIDE = 25,
p_CLKOUT0_PHASE = self.NO_PHASE_SHIFT,
p_CLKOUT0_DUTY_CYCLE = self.DUTY_CYCLE,
i_CLKFBIN = mainpll_feedback,
o_CLKFBOUT = mainpll_feedback,
i_CLKIN1 = clk,
o_CLKOUT0 = main_clocks,
o_LOCKED = sys_locked,
)
m.submodules.audiopll = Instance("PLLE2_ADV",
p_CLKIN1_PERIOD = 16.666,
p_BANDWIDTH = "OPTIMIZED",
p_COMPENSATION = "ZHOLD",
p_STARTUP_WAIT = "FALSE",
p_DIVCLK_DIVIDE = 1,
p_CLKFBOUT_MULT = self.ADAT_MULT_48k,
p_CLKFBOUT_PHASE = self.NO_PHASE_SHIFT,
# ADAT clock = 12.288 MHz = 48 kHz * 256
p_CLKOUT2_DIVIDE = self.ADAT_DIV_48k,
p_CLKOUT2_PHASE = self.NO_PHASE_SHIFT,
p_CLKOUT2_DUTY_CYCLE = self.DUTY_CYCLE,
# ADAT sampling clock = 48 kHz * 256 * 8 times oversampling
p_CLKOUT0_DIVIDE = self.ADAT_DIV_48k / 8,
p_CLKOUT0_PHASE = self.NO_PHASE_SHIFT,
p_CLKOUT0_DUTY_CYCLE = self.DUTY_CYCLE,
# ADAT transmit domain clock = 48 kHz * 256 * 5 output terminals
p_CLKOUT3_DIVIDE = self.ADAT_DIV_48k / 5,
p_CLKOUT3_PHASE = self.NO_PHASE_SHIFT,
p_CLKOUT3_DUTY_CYCLE = self.DUTY_CYCLE,
i_CLKFBIN = audiopll_feedback,
o_CLKFBOUT = audiopll_feedback,
i_CLKIN1 = main_clocks[0],
o_CLKOUT0 = audio_clocks[2],
o_CLKOUT2 = audio_clocks[0],
o_CLKOUT3 = audio_clocks[3],
o_LOCKED = audio_locked,
)
VCO_SCALER_FAST = 1
m.submodules.fastpll = Instance("PLLE2_ADV",
p_CLKIN1_PERIOD = 10.172,
p_BANDWIDTH = "OPTIMIZED",
p_COMPENSATION = "ZHOLD",
p_STARTUP_WAIT = "FALSE",
p_DIVCLK_DIVIDE = 1,
p_CLKFBOUT_MULT = VCO_SCALER_FAST * platform.fast_multiplier,
p_CLKFBOUT_PHASE = self.NO_PHASE_SHIFT,
# Fast clock = 48 kHz * 256 * 9
p_CLKOUT0_DIVIDE = VCO_SCALER_FAST,
p_CLKOUT0_PHASE = self.NO_PHASE_SHIFT,
p_CLKOUT0_DUTY_CYCLE = self.DUTY_CYCLE,
# I2S DAC clock 48k = 3.072 MHz = 48 kHz * 32 bit * 2 channels
p_CLKOUT1_DIVIDE = VCO_SCALER_FAST * platform.fast_multiplier * 4,
p_CLKOUT1_PHASE = self.NO_PHASE_SHIFT,
p_CLKOUT1_DUTY_CYCLE = self.DUTY_CYCLE,
i_CLKFBIN = fastpll_feedback,
o_CLKFBOUT = fastpll_feedback,
i_CLKIN1 = audio_clocks[2],
o_CLKOUT0 = fast_clock_48k,
o_CLKOUT1 = audio_clocks[1],
o_LOCKED = fast_locked,
)
m.d.comb += [
reset.eq(~(sys_locked & audio_locked & fast_locked)),
ClockSignal("fast").eq(fast_clock_48k),
ClockSignal("usb") .eq(main_clocks[0]),
ClockSignal("adat").eq(audio_clocks[0]),
ClockSignal("dac").eq(audio_clocks[1]),
ClockSignal("sync").eq(audio_clocks[3]),
]
self.wire_up_reset(m, reset)
return m
class ColorlightDomainGenerator(Elaboratable, ClockDomainGeneratorBase):
""" Clock generator for the Colorlight I5 board. """
FastDomainDivider = 7
FastClockFreq = 25e6 * 29 / FastDomainDivider
def __init__(self, clock_frequencies=None):
pass
def elaborate(self, platform):
m = Module()
# Create our domains.
m.domains.sync = ClockDomain("sync")
m.domains.usb = ClockDomain("usb")
m.domains.fast = ClockDomain("fast")
m.domains.adat = ClockDomain("adat")
m.domains.dac = ClockDomain("dac")
# Grab our clock and global reset signals.
clk25 = flipped(platform.request(platform.default_clk))
main_clocks = Signal(5)
audio_clocks = Signal(4)
fast_clock_48k = Signal()
main_locked = Signal()
audio_locked = Signal()
fast_locked = Signal()
reset = Signal()
# USB PLL
main_feedback = Signal()
m.submodules.main_pll = Instance("EHXPLLL",
# Status.
o_LOCK=main_locked,
# PLL parameters...
p_PLLRST_ENA="DISABLED",
p_INTFB_WAKE="DISABLED",
p_STDBY_ENABLE="DISABLED",
p_DPHASE_SOURCE="DISABLED",
p_OUTDIVIDER_MUXA="DIVA",
p_OUTDIVIDER_MUXB="DIVB",
p_OUTDIVIDER_MUXC="DIVC",
p_OUTDIVIDER_MUXD="DIVD",
# 60 MHz
p_CLKI_DIV = 5,
p_CLKOP_ENABLE = "ENABLED",
p_CLKOP_DIV = 10,
p_CLKOP_CPHASE = 15,
p_CLKOP_FPHASE = 0,
p_FEEDBK_PATH = "CLKOP",
p_CLKFB_DIV = 12,
# Clock in.
i_CLKI=clk25,
# Internal feedback.
i_CLKFB=main_feedback,
# Control signals.
i_RST=reset,
i_PHASESEL0=0,
i_PHASESEL1=0,
i_PHASEDIR=1,
i_PHASESTEP=1,
i_PHASELOADREG=1,
i_STDBY=0,
i_PLLWAKESYNC=0,
# Output Enables.
i_ENCLKOP=0,
i_ENCLKOS=0,
# Generated clock outputs.
o_CLKOP=main_feedback,
# Synthesis attributes.
a_FREQUENCY_PIN_CLKI="25",
a_FREQUENCY_PIN_CLKOP="60",
a_ICP_CURRENT="6",
a_LPF_RESISTOR="16",
a_MFG_ENABLE_FILTEROPAMP="1",
a_MFG_GMCREF_SEL="2"
)
audio_feedback = Signal()
audio_locked = Signal()
m.submodules.audio_pll = Instance("EHXPLLL",
# Status.
o_LOCK=audio_locked,
# PLL parameters...
p_PLLRST_ENA="DISABLED",
p_INTFB_WAKE="DISABLED",
p_STDBY_ENABLE="DISABLED",
p_DPHASE_SOURCE="DISABLED",
p_OUTDIVIDER_MUXA="DIVA",
p_OUTDIVIDER_MUXB="DIVB",
p_OUTDIVIDER_MUXC="DIVC",
p_OUTDIVIDER_MUXD="DIVD",
# 25MHz * 29 = 725 MHz PLL freqency
p_CLKI_DIV = 1,
p_CLKOP_ENABLE = "ENABLED",
p_CLKOP_DIV = 29,
p_CLKOP_CPHASE = 0,
p_CLKOP_FPHASE = 0,
# 12.288 MHz = 725 MHz / 59
p_CLKOS_ENABLE = "ENABLED",
p_CLKOS_DIV = 59,
p_CLKOS_CPHASE = 0,
p_CLKOS_FPHASE = 0,
# fast domain clock
p_CLKOS3_ENABLE = "ENABLED",
p_CLKOS3_DIV = self.FastDomainDivider,
p_CLKOS3_CPHASE = 0,
p_CLKOS3_FPHASE = 0,
p_FEEDBK_PATH = "CLKOP",
p_CLKFB_DIV = 1,
# Clock in.
i_CLKI=clk25,
# Internal feedback.
i_CLKFB=audio_feedback,
# Control signals.
i_RST=reset,
i_PHASESEL0=0,
i_PHASESEL1=0,
i_PHASEDIR=1,
i_PHASESTEP=1,
i_PHASELOADREG=1,
i_STDBY=0,
i_PLLWAKESYNC=0,
# Output Enables.
i_ENCLKOP=0,
i_ENCLKOS=0,
i_ENCLKOS3=0,
# Generated clock outputs.
o_CLKOP=audio_feedback,
o_CLKOS=ClockSignal("adat"),
o_CLKOS3=ClockSignal("fast"),
# Synthesis attributes.
a_FREQUENCY_PIN_CLKI="25",
a_FREQUENCY_PIN_CLKOS="12.288",
a_ICP_CURRENT="6",
a_LPF_RESISTOR="16",
a_MFG_ENABLE_FILTEROPAMP="1",
a_MFG_GMCREF_SEL="2"
)
debug0 = platform.request("debug", 0)
debug1 = platform.request("debug", 1)
debug2 = platform.request("debug", 2)
debug3 = platform.request("debug", 3)
m.submodules.bclk_div = clk_div = DomainRenamer("adat")(SimpleClockDivider(4))
reset = Signal()
# Control our resets.
m.d.comb += [
ClockSignal("usb") .eq(main_feedback),
ClockSignal("sync") .eq(ClockSignal("usb")),
ClockSignal("dac") .eq(clk_div.clock_out),
clk_div.clock_enable_in.eq(1),
reset.eq(~(main_locked & audio_locked)),
debug0.eq(ClockSignal("usb")),
debug1.eq(ClockSignal("adat")),
debug2.eq(ClockSignal("fast")),
debug3.eq(reset),
]
self.wire_up_reset(m, reset)
return m