forked from M-Labs/nac3
add RTIO PLL and clock source selection
This commit is contained in:
parent
6454315cd2
commit
bd7d58e239
|
@ -390,6 +390,7 @@ dependencies = [
|
|||
"cslice",
|
||||
"dwarf",
|
||||
"dyld",
|
||||
"embedded-hal",
|
||||
"fatfs",
|
||||
"futures",
|
||||
"libasync",
|
||||
|
@ -399,6 +400,7 @@ dependencies = [
|
|||
"libregister",
|
||||
"libsupport_zynq",
|
||||
"log",
|
||||
"nb",
|
||||
"num-derive",
|
||||
"num-traits",
|
||||
"unwind",
|
||||
|
|
|
@ -14,18 +14,22 @@ num-traits = { version = "0.2", default-features = false }
|
|||
num-derive = "0.3"
|
||||
cslice = "0.3"
|
||||
log = "0.4"
|
||||
nb = "0.1"
|
||||
embedded-hal = "0.2"
|
||||
core_io = { version = "0.1", features = ["collections"] }
|
||||
byteorder = { version = "1.3", default-features = false }
|
||||
void = { version = "1", default-features = false }
|
||||
futures = { version = "0.3", default-features = false, features = ["async-await"] }
|
||||
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" }
|
||||
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" }
|
||||
libasync = { git = "https://git.m-labs.hk/M-Labs/zc706.git" }
|
||||
libregister = { git = "https://git.m-labs.hk/M-Labs/zc706.git" }
|
||||
|
||||
dyld = { path = "../libdyld" }
|
||||
dwarf = { path = "../libdwarf" }
|
||||
unwind = { path = "../libunwind" }
|
||||
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 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 libregister::RegisterW;
|
||||
use nb::block;
|
||||
use embedded_hal::timer::CountDown;
|
||||
|
||||
mod sd_reader;
|
||||
mod config;
|
||||
|
@ -29,28 +31,7 @@ mod load_pl;
|
|||
mod eh_artiq;
|
||||
mod panic;
|
||||
|
||||
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])
|
||||
}
|
||||
}
|
||||
|
||||
#[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();
|
||||
|
||||
fn init_gateware() {
|
||||
// Set up PS->PL clocks
|
||||
slcr::RegisterBlock::unlocked(|slcr| {
|
||||
// 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),
|
||||
}
|
||||
}
|
||||
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 {
|
||||
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() {
|
||||
Ok(cfg) => cfg,
|
||||
|
@ -100,5 +143,8 @@ pub fn main_core0() {
|
|||
config::Config::new_dummy()
|
||||
}
|
||||
};
|
||||
|
||||
init_rtio(timer, &cfg);
|
||||
|
||||
comms::main(timer, &cfg);
|
||||
}
|
||||
|
|
56
src/zc706.py
56
src/zc706.py
|
@ -3,15 +3,61 @@
|
|||
import argparse
|
||||
|
||||
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.platforms import zc706
|
||||
from misoc.interconnect.csr import *
|
||||
from misoc.integration import cpu_interface
|
||||
|
||||
from artiq.gateware import rtio, nist_clock, nist_qc2
|
||||
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):
|
||||
def __init__(self):
|
||||
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("set_input_jitter clk_fpga_0 0.24")
|
||||
self.clock_domains.cd_rtio = ClockDomain()
|
||||
self.comb += [
|
||||
self.cd_rtio.clk.eq(self.ps7.cd_sys.clk),
|
||||
self.cd_rtio.rst.eq(self.ps7.cd_sys.rst)
|
||||
]
|
||||
|
||||
self.submodules.rtio_crg = RTIOCRG(self.platform, self.ps7.cd_sys.clk)
|
||||
self.csr_devices.append("rtio_crg")
|
||||
|
||||
def add_rtio(self, rtio_channels):
|
||||
self.submodules.rtio_tsc = rtio.TSC("async", glbl_fine_ts_width=3)
|
||||
|
|
Loading…
Reference in New Issue