forked from M-Labs/artiq
1
0
Fork 0

Merge pull request #1796 from HarryMakes/release-6

Metlino/Sayma: fix DDS sync & upgrade SAWG to 1 GS/s
This commit is contained in:
Sébastien Bourdeauducq 2021-12-13 10:58:49 +08:00 committed by GitHub
commit 9547a15162
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 116 additions and 110 deletions

View File

@ -5,7 +5,7 @@ device_db = {
"type": "local", "type": "local",
"module": "artiq.coredevice.core", "module": "artiq.coredevice.core",
"class": "Core", "class": "Core",
"arguments": {"host": core_addr, "ref_period": 1/(8*150e6)} "arguments": {"host": core_addr, "ref_period": 1/(8*125e6)}
}, },
"core_log": { "core_log": {
"type": "controller", "type": "controller",

View File

@ -5,7 +5,7 @@ device_db = {
"type": "local", "type": "local",
"module": "artiq.coredevice.core", "module": "artiq.coredevice.core",
"class": "Core", "class": "Core",
"arguments": {"host": core_addr, "ref_period": 1/(8*150e6)} "arguments": {"host": core_addr, "ref_period": 1/(8*125e6)}
}, },
"core_log": { "core_log": {
"type": "controller", "type": "controller",
@ -69,7 +69,7 @@ device_db.update(
"arguments": { "arguments": {
"spi_device": "spi_urukul0", "spi_device": "spi_urukul0",
"io_update_device": "ttl_urukul0_io_update", "io_update_device": "ttl_urukul0_io_update",
"refclk": 150e6, "refclk": 125e6,
"clk_sel": 2 "clk_sel": 2
} }
} }

View File

@ -5,7 +5,7 @@ device_db = {
"type": "local", "type": "local",
"module": "artiq.coredevice.core", "module": "artiq.coredevice.core",
"class": "Core", "class": "Core",
"arguments": {"host": core_addr, "ref_period": 1/(8*150e6)} "arguments": {"host": core_addr, "ref_period": 1/(8*125e6)}
}, },
"core_log": { "core_log": {
"type": "controller", "type": "controller",

View File

@ -5,7 +5,7 @@ device_db = {
"type": "local", "type": "local",
"module": "artiq.coredevice.core", "module": "artiq.coredevice.core",
"class": "Core", "class": "Core",
"arguments": {"host": core_addr, "ref_period": 1/(8*150e6)} "arguments": {"host": core_addr, "ref_period": 1/(8*125e6)}
}, },
"core_log": { "core_log": {
"type": "controller", "type": "controller",

View File

@ -34,9 +34,9 @@ fn read(addr: u16) -> u8 {
} }
// ad9154 mode 1 // ad9154 mode 1
// linerate 5Gbps or 6Gbps // linerate 10Gbps
// deviceclock_fpga 125MHz or 150MHz // deviceclock_fpga 125MHz
// deviceclock_dac 500MHz or 600MHz // deviceclock_dac 1000MHz
struct JESDSettings { struct JESDSettings {
did: u8, did: u8,
@ -87,7 +87,7 @@ const JESD_SETTINGS: JESDSettings = JESDSettings {
np: 16, np: 16,
f: 2, f: 2,
s: 2, s: 2,
k: 16, k: 32,
cs: 0, cs: 0,
subclassv: 1, subclassv: 1,
@ -144,9 +144,7 @@ pub fn setup(dacno: u8, linerate: u64) -> Result<(), &'static str> {
write(ad9154_reg::DEVICE_CONFIG_REG_1, 0x01); // magic write(ad9154_reg::DEVICE_CONFIG_REG_1, 0x01); // magic
write(ad9154_reg::DEVICE_CONFIG_REG_2, 0x01); // magic write(ad9154_reg::DEVICE_CONFIG_REG_2, 0x01); // magic
write(ad9154_reg::SPI_PAGEINDX, 0x3); // A and B dual write(ad9154_reg::INTERP_MODE, 0x01); // 2x
write(ad9154_reg::INTERP_MODE, 0x03); // 4x
write(ad9154_reg::MIX_MODE, 0); write(ad9154_reg::MIX_MODE, 0);
write(ad9154_reg::DATA_FORMAT, 0*ad9154_reg::BINARY_FORMAT); // s16 write(ad9154_reg::DATA_FORMAT, 0*ad9154_reg::BINARY_FORMAT); // s16
write(ad9154_reg::DATAPATH_CTRL, write(ad9154_reg::DATAPATH_CTRL,
@ -326,13 +324,17 @@ pub fn setup(dacno: u8, linerate: u64) -> Result<(), &'static str> {
1*ad9154_reg::EQ_POWER_MODE); 1*ad9154_reg::EQ_POWER_MODE);
write(ad9154_reg::GENERAL_JRX_CTRL_1, 1); // subclass 1 write(ad9154_reg::GENERAL_JRX_CTRL_1, 1); // subclass 1
write(ad9154_reg::LMFC_DELAY_0, 0); // LMFCDel & LMFCVar were deduced from values of DYN_LINK_LATENCY_0
write(ad9154_reg::LMFC_DELAY_1, 0); // gathered from repeated power-cycles; see datasheet (Rev. C) p.44
write(ad9154_reg::LMFC_VAR_0, 0x0a); // receive buffer delay // "Link Delay Setup Example, Without Known Delay"
write(ad9154_reg::LMFC_VAR_1, 0x0a); write(ad9154_reg::LMFC_DELAY_0, 14);
write(ad9154_reg::LMFC_DELAY_1, 14);
write(ad9154_reg::LMFC_VAR_0, 4); // receive buffer delay
write(ad9154_reg::LMFC_VAR_1, 4);
write(ad9154_reg::SYNC_ERRWINDOW, 0); // +- 1/2 DAC clock write(ad9154_reg::SYNC_ERRWINDOW, 0); // +- 1/2 DAC clock
// datasheet seems to say ENABLE and ARM should be separate steps, // datasheet seems to say ENABLE and ARM should be separate steps,
// so enable now so it can be armed in sync(). // so enable now so it can be armed in sync().
write(ad9154_reg::SPI_PAGEINDX, 0x3); // A and B dual
write(ad9154_reg::SYNC_CONTROL, write(ad9154_reg::SYNC_CONTROL,
0x1*ad9154_reg::SYNCMODE | 1*ad9154_reg::SYNCENABLE | 0x1*ad9154_reg::SYNCMODE | 1*ad9154_reg::SYNCENABLE |
0*ad9154_reg::SYNCARM | 0*ad9154_reg::SYNCCLRSTKY); 0*ad9154_reg::SYNCARM | 0*ad9154_reg::SYNCCLRSTKY);
@ -349,6 +351,28 @@ pub fn setup(dacno: u8, linerate: u64) -> Result<(), &'static str> {
write(ad9154_reg::GENERAL_JRX_CTRL_0, write(ad9154_reg::GENERAL_JRX_CTRL_0,
0x1*ad9154_reg::LINK_EN | 0*ad9154_reg::LINK_PAGE | 0x1*ad9154_reg::LINK_EN | 0*ad9154_reg::LINK_PAGE |
0*ad9154_reg::LINK_MODE | 0*ad9154_reg::CHECKSUM_MODE); 0*ad9154_reg::LINK_MODE | 0*ad9154_reg::CHECKSUM_MODE);
// JESD Checks
let jesd_checks = read(ad9154_reg::JESD_CHECKS);
if jesd_checks & ad9154_reg::ERR_DLYOVER == ad9154_reg::ERR_DLYOVER {
error!("LMFC_Delay > JESD_K Parameter")
}
if jesd_checks & ad9154_reg::ERR_WINLIMIT == ad9154_reg::ERR_WINLIMIT {
error!("Unsupported Window Limit")
}
if jesd_checks & ad9154_reg::ERR_JESDBAD == ad9154_reg::ERR_JESDBAD {
error!("Unsupported M/L/S/F Selection")
}
if jesd_checks & ad9154_reg::ERR_KUNSUPP == ad9154_reg::ERR_KUNSUPP {
error!("Unsupported K Values")
}
if jesd_checks & ad9154_reg::ERR_SUBCLASS == ad9154_reg::ERR_SUBCLASS {
error!("Unsupported SUBCLASSV Value")
}
if jesd_checks & ad9154_reg::ERR_INTSUPP == ad9154_reg::ERR_INTSUPP {
error!("Unsupported Interpolation Factor")
}
info!(" ...done"); info!(" ...done");
Ok(()) Ok(())
} }
@ -529,6 +553,7 @@ pub fn stpl(dacno: u8, m: u8, s: u8) -> Result<(), &'static str> {
pub fn sync(dacno: u8) -> Result<bool, &'static str> { pub fn sync(dacno: u8) -> Result<bool, &'static str> {
spi_setup(dacno); spi_setup(dacno);
write(ad9154_reg::SPI_PAGEINDX, 0x3); // A and B dual
write(ad9154_reg::SYNC_CONTROL, write(ad9154_reg::SYNC_CONTROL,
0x1*ad9154_reg::SYNCMODE | 1*ad9154_reg::SYNCENABLE | 0x1*ad9154_reg::SYNCMODE | 1*ad9154_reg::SYNCENABLE |
1*ad9154_reg::SYNCARM | 1*ad9154_reg::SYNCCLRSTKY); 1*ad9154_reg::SYNCARM | 1*ad9154_reg::SYNCCLRSTKY);
@ -545,5 +570,10 @@ pub fn sync(dacno: u8) -> Result<bool, &'static str> {
return Err("no sysref edge"); return Err("no sysref edge");
} }
let realign_occured = sync_status & ad9154_reg::SYNC_ROTATE != 0; let realign_occured = sync_status & ad9154_reg::SYNC_ROTATE != 0;
let phase_error = sync_status & ad9154_reg::SYNC_WLIM != 0;
if !realign_occured && phase_error {
// see also: SYNC_ERRWINDOW
warn!(" phase error window exceeded but clock did not rotate");
}
Ok(realign_occured) Ok(realign_occured)
} }

View File

@ -157,7 +157,7 @@ pub mod hmc7043 {
(false, FPGA_CLK_DIV, 0x10, true), // 5: AMC_FPGA_SYSREF1 (false, FPGA_CLK_DIV, 0x10, true), // 5: AMC_FPGA_SYSREF1
(false, 0, 0x10, false), // 6: unused (false, 0, 0x10, false), // 6: unused
(true, FPGA_CLK_DIV, 0x10, true), // 7: RTM_FPGA_SYSREF0 (true, FPGA_CLK_DIV, 0x10, true), // 7: RTM_FPGA_SYSREF0
(true, FPGA_CLK_DIV, 0x08, false), // 8: GTP_CLK0_IN (true, FPGA_CLK_DIV/2, 0x08, false), // 8: GTP_CLK0_IN
(false, 0, 0x10, false), // 9: unused (false, 0, 0x10, false), // 9: unused
(false, 0, 0x10, false), // 10: unused (false, 0, 0x10, false), // 10: unused
(false, 0, 0x08, false), // 11: unused / uFL (false, 0, 0x08, false), // 11: unused / uFL
@ -393,8 +393,6 @@ pub mod hmc7043 {
pub fn init() -> Result<(), &'static str> { pub fn init() -> Result<(), &'static str> {
#[cfg(all(hmc830_ref = "125", rtio_frequency = "125.0"))] #[cfg(all(hmc830_ref = "125", rtio_frequency = "125.0"))]
const DIV: (u32, u32, u32, u32) = (2, 32, 0, 1); // 125MHz -> 2.0GHz const DIV: (u32, u32, u32, u32) = (2, 32, 0, 1); // 125MHz -> 2.0GHz
#[cfg(all(hmc830_ref = "150", rtio_frequency = "150.0"))]
const DIV: (u32, u32, u32, u32) = (2, 32, 0, 1); // 150MHz -> 2.4GHz
/* do not use other SPI devices before HMC830 SPI mode selection */ /* do not use other SPI devices before HMC830 SPI mode selection */
hmc830::select_spi_mode(); hmc830::select_spi_mode();
@ -406,7 +404,7 @@ pub fn init() -> Result<(), &'static str> {
hmc830::check_locked()?; hmc830::check_locked()?;
if hmc7043::get_id() == hmc7043::CHIP_ID { if hmc7043::get_id() == hmc7043::CHIP_ID {
error!("HMC7043 detected while in reset (board rework missing?)"); error!("HMC7043 detected while in reset");
} }
hmc7043::enable(); hmc7043::enable();
hmc7043::detect()?; hmc7043::detect()?;

View File

@ -119,19 +119,6 @@ fn setup_si5324_as_synthesizer() {
bwsel : 4, bwsel : 4,
crystal_ref: true crystal_ref: true
}; };
// 150MHz output, from crystal
#[cfg(all(rtio_frequency = "150.0", not(si5324_ext_ref)))]
const SI5324_SETTINGS: si5324::FrequencySettings
= si5324::FrequencySettings {
n1_hs : 9,
nc1_ls : 4,
n2_hs : 10,
n2_ls : 33732,
n31 : 7139,
n32 : 7139,
bwsel : 3,
crystal_ref: true
};
// 100MHz output, from crystal. Also used as reference for Sayma HMC830. // 100MHz output, from crystal. Also used as reference for Sayma HMC830.
#[cfg(all(rtio_frequency = "100.0", not(si5324_ext_ref)))] #[cfg(all(rtio_frequency = "100.0", not(si5324_ext_ref)))]
const SI5324_SETTINGS: si5324::FrequencySettings const SI5324_SETTINGS: si5324::FrequencySettings

View File

@ -300,9 +300,7 @@ fn process_aux_packet(_repeaters: &mut [repeater::Repeater],
#[cfg(has_ad9154)] #[cfg(has_ad9154)]
let (succeeded, retval) = { let (succeeded, retval) = {
#[cfg(rtio_frequency = "125.0")] #[cfg(rtio_frequency = "125.0")]
const LINERATE: u64 = 5_000_000_000; const LINERATE: u64 = 10_000_000_000;
#[cfg(rtio_frequency = "150.0")]
const LINERATE: u64 = 6_000_000_000;
match _reqno { match _reqno {
jdac_common::INIT => (board_artiq::ad9154::setup(_dacno, LINERATE).is_ok(), 0), jdac_common::INIT => (board_artiq::ad9154::setup(_dacno, LINERATE).is_ok(), 0),
jdac_common::PRINT_STATUS => { board_artiq::ad9154::status(_dacno); (true, 0) }, jdac_common::PRINT_STATUS => { board_artiq::ad9154::status(_dacno); (true, 0) },
@ -417,19 +415,6 @@ fn hardware_tick(ts: &mut u64) {
} }
} }
#[cfg(all(has_si5324, rtio_frequency = "150.0"))]
const SI5324_SETTINGS: si5324::FrequencySettings
= si5324::FrequencySettings {
n1_hs : 6,
nc1_ls : 6,
n2_hs : 10,
n2_ls : 270,
n31 : 75,
n32 : 75,
bwsel : 4,
crystal_ref: true
};
#[cfg(all(has_si5324, rtio_frequency = "125.0"))] #[cfg(all(has_si5324, rtio_frequency = "125.0"))]
const SI5324_SETTINGS: si5324::FrequencySettings const SI5324_SETTINGS: si5324::FrequencySettings
= si5324::FrequencySettings { = si5324::FrequencySettings {

View File

@ -4,20 +4,20 @@ from migen.genlib.cdc import MultiReg, PulseSynchronizer
from misoc.interconnect.csr import * from misoc.interconnect.csr import *
# This code assumes 125/62.5MHz reference clock and 125MHz or 150MHz RTIO # This code assumes 125/62.5MHz reference clock and 125MHz RTIO
# frequency. # frequency.
class SiPhaser7Series(Module, AutoCSR): class SiPhaser7Series(Module, AutoCSR):
def __init__(self, si5324_clkin, rx_synchronizer, def __init__(self, si5324_clkin, rx_synchronizer,
ref_clk=None, ref_div2=False, ultrascale=False, rtio_clk_freq=150e6): ref_clk=None, ref_div2=False, ultrascale=False, rtio_clk_freq=125e6):
self.switch_clocks = CSRStorage() self.switch_clocks = CSRStorage()
self.phase_shift = CSR() self.phase_shift = CSR()
self.phase_shift_done = CSRStatus(reset=1) self.phase_shift_done = CSRStatus(reset=1)
self.error = CSR() self.error = CSR()
assert rtio_clk_freq in (125e6, 150e6) assert rtio_clk_freq == 125e6
# 125MHz/62.5MHz reference clock to 125MHz/150MHz. VCO @ 750MHz. # 125MHz reference clock to 125MHz. VCO @ 750MHz.
# Used to provide a startup clock to the transceiver through the Si, # Used to provide a startup clock to the transceiver through the Si,
# we do not use the crystal reference so that the PFD (f3) frequency # we do not use the crystal reference so that the PFD (f3) frequency
# can be high. # can be high.
@ -43,8 +43,8 @@ class SiPhaser7Series(Module, AutoCSR):
else: else:
mmcm_freerun_output = mmcm_freerun_output_raw mmcm_freerun_output = mmcm_freerun_output_raw
# 125MHz/150MHz to 125MHz/150MHz with controllable phase shift, # 125MHz to 125MHz with controllable phase shift,
# VCO @ 1000MHz/1200MHz. # VCO @ 1000MHz.
# Inserted between CDR and output to Si, used to correct # Inserted between CDR and output to Si, used to correct
# non-determinstic skew of Si5324. # non-determinstic skew of Si5324.
mmcm_ps_fb = Signal() mmcm_ps_fb = Signal()

View File

@ -77,8 +77,6 @@ class GTHSingle(Module):
p_ALIGN_PCOMMA_DET ="FALSE", p_ALIGN_PCOMMA_DET ="FALSE",
p_ALIGN_PCOMMA_VALUE =0b0101111100, p_ALIGN_PCOMMA_VALUE =0b0101111100,
p_A_RXOSCALRESET =0b0, p_A_RXOSCALRESET =0b0,
p_A_RXPROGDIVRESET =0b0,
p_A_TXPROGDIVRESET =0b0,
p_CBCC_DATA_SOURCE_SEL ="ENCODED", p_CBCC_DATA_SOURCE_SEL ="ENCODED",
p_CDR_SWAP_MODE_EN =0b0, p_CDR_SWAP_MODE_EN =0b0,
p_CHAN_BOND_KEEP_ALIGN ="FALSE", p_CHAN_BOND_KEEP_ALIGN ="FALSE",
@ -314,7 +312,7 @@ class GTHSingle(Module):
p_RX_BIAS_CFG0 =0b0000101010110100, p_RX_BIAS_CFG0 =0b0000101010110100,
p_RX_BUFFER_CFG =0b000000, p_RX_BUFFER_CFG =0b000000,
p_RX_CAPFF_SARC_ENB =0b0, p_RX_CAPFF_SARC_ENB =0b0,
p_RX_CLK25_DIV =6, p_RX_CLK25_DIV =5, # Applicable to 125MHz RXPLLREFCLK_DIV1 = CPLL GTREFCLK0
p_RX_CLKMUX_EN =0b1, p_RX_CLKMUX_EN =0b1,
p_RX_CLK_SLIP_OVRD =0b00000, p_RX_CLK_SLIP_OVRD =0b00000,
p_RX_CM_BUF_CFG =0b1010, p_RX_CM_BUF_CFG =0b1010,
@ -413,7 +411,7 @@ class GTHSingle(Module):
p_TXSYNC_MULTILANE =0 if mode == "single" else 1, p_TXSYNC_MULTILANE =0 if mode == "single" else 1,
p_TXSYNC_OVRD =0b0, p_TXSYNC_OVRD =0b0,
p_TXSYNC_SKIP_DA =0b0, p_TXSYNC_SKIP_DA =0b0,
p_TX_CLK25_DIV =6, p_TX_CLK25_DIV =5, # Applicable to 125MHz TXPLLREFCLK_DIV1 = CPLL GTREFCLK0
p_TX_CLKMUX_EN =0b1, p_TX_CLKMUX_EN =0b1,
p_TX_DATA_WIDTH =dw, p_TX_DATA_WIDTH =dw,
p_TX_DCD_CFG =0b000010, p_TX_DCD_CFG =0b000010,
@ -475,6 +473,7 @@ class GTHSingle(Module):
# TX Startup/Reset # TX Startup/Reset
i_GTTXRESET=tx_init.gtXxreset, i_GTTXRESET=tx_init.gtXxreset,
i_TXPROGDIVRESET=tx_init.gtXxprogdivreset,
o_TXRESETDONE=tx_init.Xxresetdone, o_TXRESETDONE=tx_init.Xxresetdone,
i_TXDLYSRESET=tx_init.Xxdlysreset if mode != "slave" else self.txdlysreset, i_TXDLYSRESET=tx_init.Xxdlysreset if mode != "slave" else self.txdlysreset,
o_TXDLYSRESETDONE=tx_init.Xxdlysresetdone, o_TXDLYSRESETDONE=tx_init.Xxdlysresetdone,
@ -501,6 +500,7 @@ class GTHSingle(Module):
# RX Startup/Reset # RX Startup/Reset
i_GTRXRESET=rx_init.gtXxreset, i_GTRXRESET=rx_init.gtXxreset,
i_RXPROGDIVRESET=rx_init.gtXxprogdivreset,
o_RXRESETDONE=rx_init.Xxresetdone, o_RXRESETDONE=rx_init.Xxresetdone,
i_RXDLYSRESET=rx_init.Xxdlysreset, i_RXDLYSRESET=rx_init.Xxdlysreset,
o_RXPHALIGNDONE=rxphaligndone, o_RXPHALIGNDONE=rxphaligndone,

View File

@ -18,6 +18,8 @@ class GTHInit(Module):
self.plllock = Signal() self.plllock = Signal()
self.pllreset = Signal() self.pllreset = Signal()
self.gtXxreset = Signal() self.gtXxreset = Signal()
# Reset signal for programmable divider: https://www.xilinx.com/support/answers/64103.html
self.gtXxprogdivreset = Signal()
self.Xxresetdone = Signal() self.Xxresetdone = Signal()
self.Xxdlysreset = Signal() self.Xxdlysreset = Signal()
self.Xxdlysresetdone = Signal() self.Xxdlysresetdone = Signal()
@ -46,10 +48,12 @@ class GTHInit(Module):
# Deglitch FSM outputs driving transceiver asynch inputs # Deglitch FSM outputs driving transceiver asynch inputs
gtXxreset = Signal() gtXxreset = Signal()
gtXxprogdivreset = Signal()
Xxdlysreset = Signal() Xxdlysreset = Signal()
Xxuserrdy = Signal() Xxuserrdy = Signal()
self.sync += [ self.sync += [
self.gtXxreset.eq(gtXxreset), self.gtXxreset.eq(gtXxreset),
self.gtXxprogdivreset.eq(gtXxprogdivreset),
self.Xxdlysreset.eq(Xxdlysreset), self.Xxdlysreset.eq(Xxdlysreset),
self.Xxuserrdy.eq(Xxuserrdy) self.Xxuserrdy.eq(Xxuserrdy)
] ]
@ -80,6 +84,7 @@ class GTHInit(Module):
startup_fsm.act("RESET_ALL", startup_fsm.act("RESET_ALL",
gtXxreset.eq(1), gtXxreset.eq(1),
gtXxprogdivreset.eq(1),
self.pllreset.eq(1), self.pllreset.eq(1),
pll_reset_timer.wait.eq(1), pll_reset_timer.wait.eq(1),
If(pll_reset_timer.done, If(pll_reset_timer.done,

View File

@ -19,31 +19,27 @@ from jesd204b.core import JESD204BCoreTXControl
class UltrascaleCRG(Module, AutoCSR): class UltrascaleCRG(Module, AutoCSR):
linerate = int(6e9) # linerate = 20*data_rate*4/8 = data_rate*10 linerate = int(10e9) # linerate = 20*data_rate*4/8 = data_rate*10
# data_rate = dac_rate/interp_factor # data_rate = dac_rate/interp_factor
refclk_freq = int(150e6) refclk_freq = int(250e6)
fabric_freq = int(125e6) fabric_freq = int(125e6)
def __init__(self, platform, use_rtio_clock=False): def __init__(self, platform):
self.jreset = CSRStorage(reset=1) self.jreset = CSRStorage(reset=1)
self.refclk = Signal() self.refclk = Signal()
self.clock_domains.cd_jesd = ClockDomain() self.clock_domains.cd_jesd = ClockDomain()
refclk2 = Signal()
refclk_pads = platform.request("dac_refclk", 0) refclk_pads = platform.request("dac_refclk", 0)
platform.add_period_constraint(refclk_pads.p, 1e9/self.refclk_freq) platform.add_period_constraint(refclk_pads.p, 1e9/self.refclk_freq)
self.specials += [ self.specials += [
Instance("IBUFDS_GTE3", i_CEB=0, p_REFCLK_HROW_CK_SEL=0b00, Instance("IBUFDS_GTE3", i_CEB=0, p_REFCLK_HROW_CK_SEL=0b01,
i_I=refclk_pads.p, i_IB=refclk_pads.n, i_I=refclk_pads.p, i_IB=refclk_pads.n,
o_O=self.refclk, o_ODIV2=refclk2), o_O=self.refclk),
AsyncResetSynchronizer(self.cd_jesd, self.jreset.storage),
] ]
if use_rtio_clock:
self.cd_jesd.clk.attr.add("keep") self.cd_jesd.clk.attr.add("keep")
self.comb += self.cd_jesd.clk.eq(ClockSignal("rtio")) self.comb += self.cd_jesd.clk.eq(ClockSignal("rtio"))
else: self.specials += AsyncResetSynchronizer(self.cd_jesd, self.jreset.storage)
self.specials += Instance("BUFG_GT", i_I=refclk2, o_O=self.cd_jesd.clk)
PhyPads = namedtuple("PhyPads", "txp txn") PhyPads = namedtuple("PhyPads", "txp txn")
@ -61,7 +57,7 @@ class UltrascaleTX(Module, AutoCSR):
"qpll": JESD204BGTHQuadPLL "qpll": JESD204BGTHQuadPLL
}[pll_type] }[pll_type]
ps = JESD204BPhysicalSettings(l=8, m=4, n=16, np=16) ps = JESD204BPhysicalSettings(l=8, m=4, n=16, np=16)
ts = JESD204BTransportSettings(f=2, s=2, k=16, cs=0) ts = JESD204BTransportSettings(f=2, s=2, k=32, cs=0)
settings = JESD204BSettings(ps, ts, did=0x5a, bid=0x5) settings = JESD204BSettings(ps, ts, did=0x5a, bid=0x5)
jesd_pads = platform.request("dac_jesd", dac) jesd_pads = platform.request("dac_jesd", dac)
@ -142,7 +138,7 @@ class UltrascaleTX(Module, AutoCSR):
pll, phy.transmitter, **phy_channel_cfg) pll, phy.transmitter, **phy_channel_cfg)
self.submodules.core = JESD204BCoreTX( self.submodules.core = JESD204BCoreTX(
phys, settings, converter_data_width=64) phys, settings, converter_data_width=128, tx_half=tx_half)
self.submodules.control = JESD204BCoreTXControl(self.core) self.submodules.control = JESD204BCoreTXControl(self.core)
self.core.register_jsync(platform.request("dac_sync", dac)) self.core.register_jsync(platform.request("dac_sync", dac))
@ -166,7 +162,7 @@ class DDMTDEdgeDetector(Module):
# See "Digital femtosecond time difference circuit for CERN's timing system" # See "Digital femtosecond time difference circuit for CERN's timing system"
# by P. Moreira and I. Darwazeh # by P. Moreira and I. Darwazeh
class DDMTD(Module, AutoCSR): class DDMTD(Module, AutoCSR):
def __init__(self, input_pads, rtio_clk_freq=150e6): def __init__(self, input_pads, rtio_clk_freq=125e6):
N = 64 N = 64
self.reset = CSRStorage(reset=1) self.reset = CSRStorage(reset=1)
self.locked = CSRStatus() self.locked = CSRStatus()
@ -189,7 +185,7 @@ class DDMTD(Module, AutoCSR):
i_RST=self.reset.storage, i_RST=self.reset.storage,
o_LOCKED=helper_locked, o_LOCKED=helper_locked,
# VCO at 1200MHz with 150MHz RTIO frequency # VCO at 1000MHz/1200MHz with 125MHz/150MHz RTIO frequency
p_CLKFBOUT_MULT_F=8.0, p_CLKFBOUT_MULT_F=8.0,
p_DIVCLK_DIVIDE=1, p_DIVCLK_DIVIDE=1,

View File

@ -54,7 +54,7 @@ class Master(MiniSoC, AMPSoC):
add_identifier(self, gateware_identifier_str=gateware_identifier_str) add_identifier(self, gateware_identifier_str=gateware_identifier_str)
platform = self.platform platform = self.platform
rtio_clk_freq = 150e6 rtio_clk_freq = 125e6
self.comb += platform.request("input_clk_sel").eq(1) self.comb += platform.request("input_clk_sel").eq(1)
self.comb += platform.request("filtered_clk_sel").eq(1) self.comb += platform.request("filtered_clk_sel").eq(1)

View File

@ -173,11 +173,11 @@ class SatelliteBase(MiniSoC):
class JDCGSAWG(Module, AutoCSR): class JDCGSAWG(Module, AutoCSR):
def __init__(self, platform, sys_crg, jesd_crg, dac): def __init__(self, platform, sys_crg, jesd_crg, dac):
# Kintex Ultrascale GTH, speed grade -1C: # Kintex Ultrascale GTH, speed grade -1C:
# CPLL linerate (D=1): 4.0 - 8.5 Gb/s # QPLL0 linerate (D=1): 9.8 - 12.5 Gb/s
self.submodules.jesd = jesd204_tools.UltrascaleTX( self.submodules.jesd = jesd204_tools.UltrascaleTX(
platform, sys_crg, jesd_crg, dac) platform, sys_crg, jesd_crg, dac, pll_type="qpll", tx_half=True)
self.submodules.sawgs = [sawg.Channel(width=16, parallelism=4) for i in range(4)] self.submodules.sawgs = [sawg.Channel(width=16, parallelism=8) for i in range(4)]
for conv, ch in zip(self.jesd.core.sink.flatten(), self.sawgs): for conv, ch in zip(self.jesd.core.sink.flatten(), self.sawgs):
assert len(Cat(ch.o)) == len(conv) assert len(Cat(ch.o)) == len(conv)
@ -187,34 +187,42 @@ class JDCGSAWG(Module, AutoCSR):
class JDCGPattern(Module, AutoCSR): class JDCGPattern(Module, AutoCSR):
def __init__(self, platform, sys_crg, jesd_crg, dac): def __init__(self, platform, sys_crg, jesd_crg, dac):
self.submodules.jesd = jesd204_tools.UltrascaleTX( self.submodules.jesd = jesd204_tools.UltrascaleTX(
platform, sys_crg, jesd_crg, dac) platform, sys_crg, jesd_crg, dac, pll_type="qpll", tx_half=True)
self.sawgs = [] self.sawgs = []
ramp = Signal(4) ramp = Signal(4)
self.sync.rtio += ramp.eq(ramp + 1) self.sync.rtio += ramp.eq(ramp + 1)
samples = [[Signal(16) for i in range(4)] for j in range(4)] samples = [[Signal(16) for i in range(8)] for j in range(4)]
self.comb += [ self.comb += [
a.eq(Cat(b)) for a, b in zip( a.eq(Cat(b)) for a, b in zip(
self.jesd.core.sink.flatten(), samples) self.jesd.core.sink.flatten(), samples)
] ]
# ch0: 16-step ramp with big carry toggles # ch0: 16-step ramp with big carry toggles
for i in range(4): for i in range(8):
self.comb += [ self.comb += [
samples[0][i][-4:].eq(ramp), samples[0][i][-4:].eq(ramp),
samples[0][i][:-4].eq(0x7ff if i % 2 else 0x800) samples[0][i][:-4].eq(0x7ff if i % 2 else 0x800)
] ]
# ch1: 50 MHz # ch1: 50 MHz
# - Formulae:
# target cosine wave frequency: f = 50e6
# DAC sampling frequency: fs = 1000e6
# number of samples per coarse RTIO period: P = 8
# number of samples needed per wave period: M = (1/f) / (1/fs)) = 20
# number of repeating samples needed: N = LCM(P, M) = 40
# number of RTIO periods needed for repeating: k = N/P = 5
# discretized value of the wave: y[i] = cos(i/M * 2pi)
from math import pi, cos from math import pi, cos
data = [int(round(cos(i/12*2*pi)*((1 << 15) - 1))) data = [int(round(cos(i/20*2*pi)*((1 << 15) - 1)))
for i in range(12)] for i in range(40)]
k = Signal(2) k = Signal(max=5)
self.sync.rtio += If(k == 2, k.eq(0)).Else(k.eq(k + 1)) self.sync.rtio += If(k == 4, k.eq(0)).Else(k.eq(k + 1))
self.comb += [ self.comb += [
Case(k, { Case(k, {
i: [samples[1][j].eq(data[i*4 + j]) for j in range(4)] i: [samples[1][j].eq(data[i*8 + j]) for j in range(8)]
for i in range(3) for i in range(5)
}) })
] ]
# ch2: ch0, ch3: ch1 # ch2: ch0, ch3: ch1
@ -227,13 +235,13 @@ class JDCGPattern(Module, AutoCSR):
class JDCGSyncDDS(Module, AutoCSR): class JDCGSyncDDS(Module, AutoCSR):
def __init__(self, platform, sys_crg, jesd_crg, dac): def __init__(self, platform, sys_crg, jesd_crg, dac):
self.submodules.jesd = jesd204_tools.UltrascaleTX( self.submodules.jesd = jesd204_tools.UltrascaleTX(
platform, sys_crg, jesd_crg, dac) platform, sys_crg, jesd_crg, dac, pll_type="qpll", tx_half=True)
self.coarse_ts = Signal(32) self.coarse_ts = Signal(32)
self.sawgs = [] self.sawgs = []
ftw = round(2**len(self.coarse_ts)*9e6/600e6) ftw = round(2**len(self.coarse_ts)*9e6/1000e6)
parallelism = 4 parallelism = 8
mul_1 = Signal.like(self.coarse_ts) mul_1 = Signal.like(self.coarse_ts)
mul_2 = Signal.like(self.coarse_ts) mul_2 = Signal.like(self.coarse_ts)
@ -271,9 +279,7 @@ class Satellite(SatelliteBase):
DRTIO satellite with local DAC/SAWG channels, as well as TTL channels via FMC and VHDCI carrier. DRTIO satellite with local DAC/SAWG channels, as well as TTL channels via FMC and VHDCI carrier.
""" """
def __init__(self, jdcg_type, **kwargs): def __init__(self, jdcg_type, **kwargs):
SatelliteBase.__init__(self, 150e6, SatelliteBase.__init__(self, identifier_suffix="." + jdcg_type, **kwargs)
identifier_suffix="." + jdcg_type,
**kwargs)
platform = self.platform platform = self.platform
@ -307,8 +313,7 @@ class Satellite(SatelliteBase):
self.submodules += phy self.submodules += phy
rtio_channels.append(rtio.Channel.from_phy(phy)) rtio_channels.append(rtio.Channel.from_phy(phy))
self.submodules.jesd_crg = jesd204_tools.UltrascaleCRG( self.submodules.jesd_crg = jesd204_tools.UltrascaleCRG(platform)
platform, use_rtio_clock=True)
cls = { cls = {
"sawg": JDCGSAWG, "sawg": JDCGSAWG,
"pattern": JDCGPattern, "pattern": JDCGPattern,

View File

@ -278,7 +278,7 @@ def main():
builder_args(parser) builder_args(parser)
soc_sayma_rtm_args(parser) soc_sayma_rtm_args(parser)
parser.add_argument("--rtio-clk-freq", parser.add_argument("--rtio-clk-freq",
default=150, type=int, help="RTIO clock frequency in MHz") default=125, type=int, help="RTIO clock frequency in MHz")
parser.add_argument("--gateware-identifier-str", default=None, parser.add_argument("--gateware-identifier-str", default=None,
help="Override ROM identifier") help="Override ROM identifier")
parser.set_defaults(output_dir=os.path.join("artiq_sayma", "rtm")) parser.set_defaults(output_dir=os.path.join("artiq_sayma", "rtm"))