forked from M-Labs/artiq-zynq
add RTIO PLL and clock source selection
This commit is contained in:
parent
6454315cd2
commit
bd7d58e239
|
@ -390,6 +390,7 @@ dependencies = [
|
||||||
"cslice",
|
"cslice",
|
||||||
"dwarf",
|
"dwarf",
|
||||||
"dyld",
|
"dyld",
|
||||||
|
"embedded-hal",
|
||||||
"fatfs",
|
"fatfs",
|
||||||
"futures",
|
"futures",
|
||||||
"libasync",
|
"libasync",
|
||||||
|
@ -399,6 +400,7 @@ dependencies = [
|
||||||
"libregister",
|
"libregister",
|
||||||
"libsupport_zynq",
|
"libsupport_zynq",
|
||||||
"log",
|
"log",
|
||||||
|
"nb",
|
||||||
"num-derive",
|
"num-derive",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
"unwind",
|
"unwind",
|
||||||
|
|
|
@ -14,18 +14,22 @@ num-traits = { version = "0.2", default-features = false }
|
||||||
num-derive = "0.3"
|
num-derive = "0.3"
|
||||||
cslice = "0.3"
|
cslice = "0.3"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
|
nb = "0.1"
|
||||||
|
embedded-hal = "0.2"
|
||||||
core_io = { version = "0.1", features = ["collections"] }
|
core_io = { version = "0.1", features = ["collections"] }
|
||||||
byteorder = { version = "1.3", default-features = false }
|
byteorder = { version = "1.3", default-features = false }
|
||||||
void = { version = "1", default-features = false }
|
void = { version = "1", default-features = false }
|
||||||
futures = { version = "0.3", default-features = false, features = ["async-await"] }
|
futures = { version = "0.3", default-features = false, features = ["async-await"] }
|
||||||
async-recursion = "0.3"
|
async-recursion = "0.3"
|
||||||
|
fatfs = { version = "0.3", features = ["core_io"], default-features = false }
|
||||||
|
|
||||||
libboard_zynq = { git = "https://git.m-labs.hk/M-Labs/zc706.git" }
|
libboard_zynq = { git = "https://git.m-labs.hk/M-Labs/zc706.git" }
|
||||||
libsupport_zynq = { default-features = false, git = "https://git.m-labs.hk/M-Labs/zc706.git" }
|
libsupport_zynq = { default-features = false, git = "https://git.m-labs.hk/M-Labs/zc706.git" }
|
||||||
libcortex_a9 = { git = "https://git.m-labs.hk/M-Labs/zc706.git" }
|
libcortex_a9 = { git = "https://git.m-labs.hk/M-Labs/zc706.git" }
|
||||||
libasync = { git = "https://git.m-labs.hk/M-Labs/zc706.git" }
|
libasync = { git = "https://git.m-labs.hk/M-Labs/zc706.git" }
|
||||||
libregister = { git = "https://git.m-labs.hk/M-Labs/zc706.git" }
|
libregister = { git = "https://git.m-labs.hk/M-Labs/zc706.git" }
|
||||||
|
|
||||||
dyld = { path = "../libdyld" }
|
dyld = { path = "../libdyld" }
|
||||||
dwarf = { path = "../libdwarf" }
|
dwarf = { path = "../libdwarf" }
|
||||||
unwind = { path = "../libunwind" }
|
unwind = { path = "../libunwind" }
|
||||||
libc = { path = "../libc" }
|
libc = { path = "../libc" }
|
||||||
fatfs = { version = "0.3", features = ["core_io"], default-features = false }
|
|
||||||
|
|
|
@ -9,9 +9,11 @@ extern crate alloc;
|
||||||
use core::{cmp, str};
|
use core::{cmp, str};
|
||||||
use log::{info, warn};
|
use log::{info, warn};
|
||||||
|
|
||||||
use libboard_zynq::{timer::GlobalTimer, logger, devc, slcr};
|
use libboard_zynq::{timer::GlobalTimer, time::Milliseconds, logger, devc, slcr};
|
||||||
use libsupport_zynq::ram;
|
use libsupport_zynq::ram;
|
||||||
use libregister::RegisterW;
|
use libregister::RegisterW;
|
||||||
|
use nb::block;
|
||||||
|
use embedded_hal::timer::CountDown;
|
||||||
|
|
||||||
mod sd_reader;
|
mod sd_reader;
|
||||||
mod config;
|
mod config;
|
||||||
|
@ -29,28 +31,7 @@ mod load_pl;
|
||||||
mod eh_artiq;
|
mod eh_artiq;
|
||||||
mod panic;
|
mod panic;
|
||||||
|
|
||||||
fn identifier_read(buf: &mut [u8]) -> &str {
|
fn init_gateware() {
|
||||||
unsafe {
|
|
||||||
pl::csr::identifier::address_write(0);
|
|
||||||
let len = pl::csr::identifier::data_read();
|
|
||||||
let len = cmp::min(len, buf.len() as u8);
|
|
||||||
for i in 0..len {
|
|
||||||
pl::csr::identifier::address_write(1 + i);
|
|
||||||
buf[i as usize] = pl::csr::identifier::data_read();
|
|
||||||
}
|
|
||||||
str::from_utf8_unchecked(&buf[..len as usize])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
pub fn main_core0() {
|
|
||||||
let timer = GlobalTimer::start();
|
|
||||||
let _ = logger::init();
|
|
||||||
log::set_max_level(log::LevelFilter::Debug);
|
|
||||||
info!("NAR3/Zynq7000 starting...");
|
|
||||||
|
|
||||||
ram::init_alloc_linker();
|
|
||||||
|
|
||||||
// Set up PS->PL clocks
|
// Set up PS->PL clocks
|
||||||
slcr::RegisterBlock::unlocked(|slcr| {
|
slcr::RegisterBlock::unlocked(|slcr| {
|
||||||
// As we are touching the mux, the clock may glitch, so reset the PL.
|
// As we are touching the mux, the clock may glitch, so reset the PL.
|
||||||
|
@ -87,11 +68,73 @@ pub fn main_core0() {
|
||||||
Err(e) => info!("Failure loading bitstream: {}", e),
|
Err(e) => info!("Failure loading bitstream: {}", e),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
info!("detected gateware: {}", identifier_read(&mut [0; 64]));
|
}
|
||||||
|
|
||||||
|
fn identifier_read(buf: &mut [u8]) -> &str {
|
||||||
|
unsafe {
|
||||||
|
pl::csr::identifier::address_write(0);
|
||||||
|
let len = pl::csr::identifier::data_read();
|
||||||
|
let len = cmp::min(len, buf.len() as u8);
|
||||||
|
for i in 0..len {
|
||||||
|
pl::csr::identifier::address_write(1 + i);
|
||||||
|
buf[i as usize] = pl::csr::identifier::data_read();
|
||||||
|
}
|
||||||
|
str::from_utf8_unchecked(&buf[..len as usize])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn init_rtio(timer: GlobalTimer, cfg: &config::Config) {
|
||||||
|
let clock_sel =
|
||||||
|
if let Ok(rtioclk) = cfg.read_str("rtioclk") {
|
||||||
|
match rtioclk.as_ref() {
|
||||||
|
"internal" => {
|
||||||
|
info!("using internal RTIO clock");
|
||||||
|
0
|
||||||
|
},
|
||||||
|
"external" => {
|
||||||
|
info!("using external RTIO clock");
|
||||||
|
1
|
||||||
|
},
|
||||||
|
other => {
|
||||||
|
warn!("RTIO clock specification '{}' not recognized", other);
|
||||||
|
info!("using internal RTIO clock");
|
||||||
|
0
|
||||||
|
},
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
info!("using internal RTIO clock (default)");
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
pl::csr::rtio_crg::pll_reset_write(1);
|
||||||
|
pl::csr::rtio_crg::clock_sel_write(clock_sel);
|
||||||
|
pl::csr::rtio_crg::pll_reset_write(0);
|
||||||
|
}
|
||||||
|
let mut countdown = timer.countdown();
|
||||||
|
countdown.start(Milliseconds(1));
|
||||||
|
block!(countdown.wait()).unwrap();
|
||||||
|
let locked = unsafe { pl::csr::rtio_crg::pll_locked_read() != 0 };
|
||||||
|
if !locked {
|
||||||
|
panic!("RTIO PLL failed to lock");
|
||||||
|
}
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
pl::csr::rtio_core::reset_phy_write(1);
|
pl::csr::rtio_core::reset_phy_write(1);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub fn main_core0() {
|
||||||
|
let timer = GlobalTimer::start();
|
||||||
|
let _ = logger::init();
|
||||||
|
log::set_max_level(log::LevelFilter::Debug);
|
||||||
|
info!("NAR3/Zynq7000 starting...");
|
||||||
|
|
||||||
|
ram::init_alloc_linker();
|
||||||
|
|
||||||
|
init_gateware();
|
||||||
|
info!("detected gateware: {}", identifier_read(&mut [0; 64]));
|
||||||
|
|
||||||
let cfg = match config::Config::new() {
|
let cfg = match config::Config::new() {
|
||||||
Ok(cfg) => cfg,
|
Ok(cfg) => cfg,
|
||||||
|
@ -100,5 +143,8 @@ pub fn main_core0() {
|
||||||
config::Config::new_dummy()
|
config::Config::new_dummy()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
init_rtio(timer, &cfg);
|
||||||
|
|
||||||
comms::main(timer, &cfg);
|
comms::main(timer, &cfg);
|
||||||
}
|
}
|
||||||
|
|
56
src/zc706.py
56
src/zc706.py
|
@ -3,15 +3,61 @@
|
||||||
import argparse
|
import argparse
|
||||||
|
|
||||||
from migen import *
|
from migen import *
|
||||||
|
from migen.genlib.resetsync import AsyncResetSynchronizer
|
||||||
|
from migen.genlib.cdc import MultiReg
|
||||||
from migen_axi.integration.soc_core import SoCCore
|
from migen_axi.integration.soc_core import SoCCore
|
||||||
from migen_axi.platforms import zc706
|
from migen_axi.platforms import zc706
|
||||||
|
from misoc.interconnect.csr import *
|
||||||
from misoc.integration import cpu_interface
|
from misoc.integration import cpu_interface
|
||||||
|
|
||||||
from artiq.gateware import rtio, nist_clock, nist_qc2
|
from artiq.gateware import rtio, nist_clock, nist_qc2
|
||||||
from artiq.gateware.rtio.phy import ttl_simple, ttl_serdes_7series, dds, spi2
|
from artiq.gateware.rtio.phy import ttl_simple, ttl_serdes_7series, dds, spi2
|
||||||
|
|
||||||
|
|
||||||
|
class RTIOCRG(Module, AutoCSR):
|
||||||
|
def __init__(self, platform, rtio_internal_clk):
|
||||||
|
self.clock_sel = CSRStorage()
|
||||||
|
self.pll_reset = CSRStorage(reset=1)
|
||||||
|
self.pll_locked = CSRStatus()
|
||||||
|
self.clock_domains.cd_rtio = ClockDomain()
|
||||||
|
self.clock_domains.cd_rtiox4 = ClockDomain(reset_less=True)
|
||||||
|
|
||||||
|
rtio_external_clk = Signal()
|
||||||
|
user_sma_clock = platform.request("user_sma_clock")
|
||||||
|
platform.add_period_constraint(user_sma_clock.p, 8.0)
|
||||||
|
self.specials += Instance("IBUFDS",
|
||||||
|
i_I=user_sma_clock.p, i_IB=user_sma_clock.n,
|
||||||
|
o_O=rtio_external_clk)
|
||||||
|
|
||||||
|
pll_locked = Signal()
|
||||||
|
rtio_clk = Signal()
|
||||||
|
rtiox4_clk = Signal()
|
||||||
|
self.specials += [
|
||||||
|
Instance("PLLE2_ADV",
|
||||||
|
p_STARTUP_WAIT="FALSE", o_LOCKED=pll_locked,
|
||||||
|
|
||||||
|
p_REF_JITTER1=0.01,
|
||||||
|
p_CLKIN1_PERIOD=8.0, p_CLKIN2_PERIOD=8.0,
|
||||||
|
i_CLKIN1=rtio_internal_clk, i_CLKIN2=rtio_external_clk,
|
||||||
|
# Warning: CLKINSEL=0 means CLKIN2 is selected
|
||||||
|
i_CLKINSEL=~self.clock_sel.storage,
|
||||||
|
|
||||||
|
# VCO @ 1GHz when using 125MHz input
|
||||||
|
p_CLKFBOUT_MULT=8, p_DIVCLK_DIVIDE=1,
|
||||||
|
i_CLKFBIN=self.cd_rtio.clk,
|
||||||
|
i_RST=self.pll_reset.storage,
|
||||||
|
|
||||||
|
o_CLKFBOUT=rtio_clk,
|
||||||
|
|
||||||
|
p_CLKOUT0_DIVIDE=2, p_CLKOUT0_PHASE=0.0,
|
||||||
|
o_CLKOUT0=rtiox4_clk),
|
||||||
|
Instance("BUFG", i_I=rtio_clk, o_O=self.cd_rtio.clk),
|
||||||
|
Instance("BUFG", i_I=rtiox4_clk, o_O=self.cd_rtiox4.clk),
|
||||||
|
AsyncResetSynchronizer(self.cd_rtio, ~pll_locked),
|
||||||
|
MultiReg(pll_locked, self.pll_locked.status)
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
class ZC706(SoCCore):
|
class ZC706(SoCCore):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
platform = zc706.Platform()
|
platform = zc706.Platform()
|
||||||
|
@ -22,11 +68,9 @@ class ZC706(SoCCore):
|
||||||
|
|
||||||
platform.add_platform_command("create_clock -name clk_fpga_0 -period 8 [get_pins \"PS7/FCLKCLK[0]\"]")
|
platform.add_platform_command("create_clock -name clk_fpga_0 -period 8 [get_pins \"PS7/FCLKCLK[0]\"]")
|
||||||
platform.add_platform_command("set_input_jitter clk_fpga_0 0.24")
|
platform.add_platform_command("set_input_jitter clk_fpga_0 0.24")
|
||||||
self.clock_domains.cd_rtio = ClockDomain()
|
|
||||||
self.comb += [
|
self.submodules.rtio_crg = RTIOCRG(self.platform, self.ps7.cd_sys.clk)
|
||||||
self.cd_rtio.clk.eq(self.ps7.cd_sys.clk),
|
self.csr_devices.append("rtio_crg")
|
||||||
self.cd_rtio.rst.eq(self.ps7.cd_sys.rst)
|
|
||||||
]
|
|
||||||
|
|
||||||
def add_rtio(self, rtio_channels):
|
def add_rtio(self, rtio_channels):
|
||||||
self.submodules.rtio_tsc = rtio.TSC("async", glbl_fine_ts_width=3)
|
self.submodules.rtio_tsc = rtio.TSC("async", glbl_fine_ts_width=3)
|
||||||
|
|
Loading…
Reference in New Issue