add RTIO PLL and clock source selection

This commit is contained in:
Sebastien Bourdeauducq 2020-07-08 19:58:13 +08:00
parent 6454315cd2
commit bd7d58e239
4 changed files with 127 additions and 31 deletions

2
src/Cargo.lock generated
View File

@ -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",

View File

@ -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 }

View File

@ -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);
} }

View File

@ -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)