From 0a5904bbaa2163ffc1703435bd5cc996f04ecae5 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Thu, 31 Aug 2017 13:05:48 +0800 Subject: [PATCH] firmware: support for multiple JESD DACs --- artiq/firmware/libboard/ad9154.rs | 69 +++++++++++++++---------------- artiq/firmware/libboard/ad9516.rs | 2 +- artiq/gateware/targets/phaser.py | 18 ++++---- 3 files changed, 44 insertions(+), 45 deletions(-) diff --git a/artiq/firmware/libboard/ad9154.rs b/artiq/firmware/libboard/ad9154.rs index 69f5ef547..db74f924b 100644 --- a/artiq/firmware/libboard/ad9154.rs +++ b/artiq/firmware/libboard/ad9154.rs @@ -2,7 +2,7 @@ use csr; use clock; use ad9154_reg; -fn spi_setup() { +fn spi_setup(dacno: u8) { unsafe { csr::converter_spi::offline_write(1); csr::converter_spi::cs_polarity_write(0); @@ -14,7 +14,7 @@ fn spi_setup() { csr::converter_spi::clk_div_read_write(16); csr::converter_spi::xfer_len_write_write(24); csr::converter_spi::xfer_len_read_write(0); - csr::converter_spi::cs_write(1 << csr::CONFIG_CONVERTER_SPI_DAC_CS); + csr::converter_spi::cs_write(1 << (csr::CONFIG_CONVERTER_SPI_FIRST_AD9154_CS + dacno as u32)); csr::converter_spi::offline_write(0); } } @@ -35,39 +35,39 @@ fn read(addr: u16) -> u8 { } } -fn jesd_reset(rst: bool) { +fn jesd_reset(dacno: u8, rst: bool) { unsafe { - csr::ad9154::jesd_jreset_write(if rst {1} else {0}) + (csr::AD9154[dacno as usize].jesd_jreset_write)(if rst {1} else {0}) } } -fn jesd_enable(en: bool) { +fn jesd_enable(dacno: u8, en: bool) { unsafe { - csr::ad9154::jesd_control_enable_write(if en {1} else {0}) + (csr::AD9154[dacno as usize].jesd_control_enable_write)(if en {1} else {0}) } } -fn jesd_ready() -> bool { +fn jesd_ready(dacno: u8) -> bool { unsafe { - csr::ad9154::jesd_control_ready_read() != 0 + (csr::AD9154[dacno as usize].jesd_control_ready_read)() != 0 } } -fn jesd_prbs(en: bool) { +fn jesd_prbs(dacno: u8, en: bool) { unsafe { - csr::ad9154::jesd_control_prbs_config_write(if en {1} else {0}) + (csr::AD9154[dacno as usize].jesd_control_prbs_config_write)(if en {1} else {0}) } } -fn jesd_stpl(en: bool) { +fn jesd_stpl(dacno: u8, en: bool) { unsafe { - csr::ad9154::jesd_control_stpl_enable_write(if en {1} else {0}) + (csr::AD9154[dacno as usize].jesd_control_stpl_enable_write)(if en {1} else {0}) } } -fn jesd_jsync() -> bool { +fn jesd_jsync(dacno: u8) -> bool { unsafe { - csr::ad9154::jesd_control_jsync_read() != 0 + (csr::AD9154[dacno as usize].jesd_control_jsync_read)() != 0 } } @@ -421,19 +421,24 @@ fn monitor() { write(ad9154_reg::IRQ_STATUS3, 0x00); } -fn cfg() -> Result<(), &'static str> { - jesd_enable(false); - jesd_prbs(false); - jesd_stpl(false); +fn cfg(dacno: u8) -> Result<(), &'static str> { + spi_setup(dacno); + // Release the JESD clock domain reset late, as we need to + // set up clock chips before. + jesd_reset(dacno, false); + + jesd_enable(dacno, false); + jesd_prbs(dacno, false); + jesd_stpl(dacno, false); clock::spin_us(10000); - jesd_enable(true); + jesd_enable(dacno, true); dac_setup()?; - jesd_enable(false); + jesd_enable(dacno, false); clock::spin_us(10000); - jesd_enable(true); + jesd_enable(dacno, true); monitor(); let t = clock::get_ms(); - while !jesd_ready() { + while !jesd_ready(dacno) { if clock::get_ms() > t + 200 { return Err("JESD ready timeout"); } @@ -442,7 +447,7 @@ fn cfg() -> Result<(), &'static str> { if read(ad9154_reg::CODEGRPSYNCFLG) != 0x0f { return Err("bad CODEGRPSYNCFLG") } - if !jesd_jsync() { + if !jesd_jsync(dacno) { return Err("bad SYNC") } if read(ad9154_reg::FRAMESYNCFLG) != 0x0f { @@ -458,18 +463,10 @@ fn cfg() -> Result<(), &'static str> { } pub fn init() -> Result<(), &'static str> { - spi_setup(); - - // Release the JESD clock domain reset late, as we need to - // set up clock chips before. - jesd_reset(false); - - for i in 0..99 { - let outcome = cfg(); - match outcome { - Ok(_) => return outcome, - Err(e) => warn!("config attempt #{} failed ({}), retrying", i, e) - } + for dacno in 0..csr::AD9154.len() { + let dacno = dacno as u8; + debug!("setting up DAC #{}", dacno); + cfg(dacno)?; } - cfg() + Ok(()) } diff --git a/artiq/firmware/libboard/ad9516.rs b/artiq/firmware/libboard/ad9516.rs index e6f582050..93d3e1e1e 100644 --- a/artiq/firmware/libboard/ad9516.rs +++ b/artiq/firmware/libboard/ad9516.rs @@ -13,7 +13,7 @@ fn spi_setup() { csr::converter_spi::clk_div_read_write(16); csr::converter_spi::xfer_len_write_write(24); csr::converter_spi::xfer_len_read_write(0); - csr::converter_spi::cs_write(1 << csr::CONFIG_CONVERTER_SPI_CLK_CS); + csr::converter_spi::cs_write(1 << csr::CONFIG_CONVERTER_SPI_AD9516_CS); csr::converter_spi::offline_write(0); } } diff --git a/artiq/gateware/targets/phaser.py b/artiq/gateware/targets/phaser.py index fe141837f..735604063 100755 --- a/artiq/gateware/targets/phaser.py +++ b/artiq/gateware/targets/phaser.py @@ -192,12 +192,14 @@ class Phaser(MiniSoC, AMPSoC): self.comb += ad9154_spi.en.eq(1) self.submodules.converter_spi = spi_csr.SPIMaster(ad9154_spi) self.csr_devices.append("converter_spi") - self.config["CONVERTER_SPI_DAC_CS"] = 0 - self.config["CONVERTER_SPI_CLK_CS"] = 1 self.config["HAS_AD9516"] = None + self.config["CONVERTER_SPI_AD9516_CS"] = 1 + self.config["CONVERTER_SPI_FIRST_AD9154_CS"] = 0 - self.submodules.ad9154 = AD9154(platform) - self.csr_devices.append("ad9154") + self.submodules.ad9154_0 = AD9154(platform) + self.csr_devices.append("ad9154_0") + self.config["HAS_AD9154"] = None + self.add_csr_group("ad9154", ["ad9154_0"]) rtio_channels = [] @@ -218,7 +220,7 @@ class Phaser(MiniSoC, AMPSoC): self.config["RTIO_FIRST_SAWG_CHANNEL"] = len(rtio_channels) rtio_channels.extend(rtio.Channel.from_phy(phy) - for sawg in self.ad9154.sawgs + for sawg in self.ad9154_0.sawgs for phy in sawg.phys) self.config["HAS_RTIO_LOG"] = None @@ -226,7 +228,7 @@ class Phaser(MiniSoC, AMPSoC): rtio_channels.append(rtio.LogChannel()) self.submodules.rtio_crg = _PhaserCRG( - platform, self.ad9154.jesd.cd_jesd.clk) + platform, self.ad9154_0.jesd.cd_jesd.clk) self.csr_devices.append("rtio_crg") self.submodules.rtio_core = rtio.Core(rtio_channels) self.csr_devices.append("rtio_core") @@ -248,8 +250,8 @@ class Phaser(MiniSoC, AMPSoC): platform.add_false_path_constraints( self.crg.cd_sys.clk, self.rtio_crg.cd_rtio.clk) platform.add_false_path_constraints( - self.crg.cd_sys.clk, self.ad9154.jesd.cd_jesd.clk) - for phy in self.ad9154.jesd.phys: + self.crg.cd_sys.clk, self.ad9154_0.jesd.cd_jesd.clk) + for phy in self.ad9154_0.jesd.phys: platform.add_false_path_constraints( self.crg.cd_sys.clk, phy.transmitter.cd_tx.clk)