mirror of https://github.com/m-labs/artiq.git
DRTIO: RTIO/SYS clock merge
This commit is contained in:
parent
ad000609ce
commit
17efc28dbe
|
@ -1,10 +1,7 @@
|
||||||
use board_misoc::config;
|
use board_misoc::config;
|
||||||
#[cfg(si5324_as_synthesizer)]
|
#[cfg(si5324_as_synthesizer)]
|
||||||
use board_artiq::si5324;
|
use board_artiq::si5324;
|
||||||
#[cfg(any(soc_platform = "kasli", has_drtio))]
|
use board_misoc::{csr, clock};
|
||||||
use board_misoc::csr;
|
|
||||||
#[cfg(has_drtio)]
|
|
||||||
use board_misoc::clock;
|
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
|
@ -212,15 +209,12 @@ fn setup_si5324_as_synthesizer(cfg: RtioClock) {
|
||||||
|
|
||||||
#[cfg(si5324_as_synthesizer)]
|
#[cfg(si5324_as_synthesizer)]
|
||||||
fn setup_si5324(clock_cfg: RtioClock) {
|
fn setup_si5324(clock_cfg: RtioClock) {
|
||||||
#[cfg(soc_platform = "kasli")]
|
let switched = unsafe {
|
||||||
{
|
csr::crg::switch_done_read()
|
||||||
let switched = unsafe {
|
};
|
||||||
csr::crg::switch_done_read()
|
if switched == 1 {
|
||||||
};
|
info!("Clocking has already been set up.");
|
||||||
if switched == 1 {
|
return;
|
||||||
info!("Clocking has already been set up.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#[cfg(all(soc_platform = "kasli", hw_rev = "v2.0"))]
|
#[cfg(all(soc_platform = "kasli", hw_rev = "v2.0"))]
|
||||||
let si5324_ext_input = si5324::Input::Ckin1;
|
let si5324_ext_input = si5324::Input::Ckin1;
|
||||||
|
@ -239,12 +233,14 @@ fn setup_si5324(clock_cfg: RtioClock) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// switch sysclk source to si5324
|
// switch sysclk source to si5324
|
||||||
#[cfg(soc_platform = "kasli")]
|
#[cfg(not(has_drtio))]
|
||||||
{
|
{
|
||||||
// excessive dots will be cut off by the reboot
|
info!("Switching sys clock, rebooting...");
|
||||||
info!("Switching sys clock, rebooting..................");
|
// delay for clean UART log, wait until UART FIFO is empty
|
||||||
|
clock::spin_us(1300);
|
||||||
unsafe {
|
unsafe {
|
||||||
csr::crg::clock_sel_write(1);
|
csr::crg::clock_sel_write(1);
|
||||||
|
loop {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -257,15 +253,28 @@ pub fn init() {
|
||||||
|
|
||||||
#[cfg(has_drtio)]
|
#[cfg(has_drtio)]
|
||||||
{
|
{
|
||||||
unsafe {
|
let switched = unsafe {
|
||||||
csr::drtio_transceiver::stable_clkin_write(1);
|
csr::crg::switch_done_read()
|
||||||
|
};
|
||||||
|
if switched == 0 {
|
||||||
|
info!("Switching sys clock, rebooting...");
|
||||||
|
clock::spin_us(500); // delay for clean UART log
|
||||||
|
unsafe {
|
||||||
|
// clock switch and reboot will begin after TX is initialized
|
||||||
|
// and TX will be initialized after this
|
||||||
|
csr::drtio_transceiver::stable_clkin_write(1);
|
||||||
|
}
|
||||||
|
loop {}
|
||||||
}
|
}
|
||||||
clock::spin_us(1500); // wait for CPLL/QPLL lock
|
else {
|
||||||
unsafe {
|
// enable TX after the reboot, with stable clock
|
||||||
csr::drtio_transceiver::txenable_write(0xffffffffu32 as _);
|
unsafe {
|
||||||
|
csr::drtio_transceiver::txenable_write(0xffffffffu32 as _);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[cfg(has_rtio_crg)]
|
#[cfg(has_rtio_crg)]
|
||||||
{
|
{
|
||||||
#[cfg(has_rtio_clock_switch)]
|
#[cfg(has_rtio_clock_switch)]
|
||||||
|
|
|
@ -465,6 +465,30 @@ const SI5324_SETTINGS: si5324::FrequencySettings
|
||||||
crystal_ref: true
|
crystal_ref: true
|
||||||
};
|
};
|
||||||
|
|
||||||
|
fn sysclk_setup() {
|
||||||
|
let switched = unsafe {
|
||||||
|
csr::crg::switch_done_read()
|
||||||
|
};
|
||||||
|
if switched == 1 {
|
||||||
|
info!("Clocking has already been set up.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
#[cfg(has_si5324)]
|
||||||
|
si5324::setup(&SI5324_SETTINGS, si5324::Input::Ckin1).expect("cannot initialize Si5324");
|
||||||
|
#[cfg(has_wrpll)]
|
||||||
|
wrpll::init();
|
||||||
|
info!("Switching sys clock, rebooting...");
|
||||||
|
// delay for clean UART log, wait until UART FIFO is empty
|
||||||
|
clock::spin_us(1300);
|
||||||
|
unsafe {
|
||||||
|
csr::drtio_transceiver::stable_clkin_write(1);
|
||||||
|
}
|
||||||
|
loop {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern fn main() -> i32 {
|
pub extern fn main() -> i32 {
|
||||||
extern {
|
extern {
|
||||||
|
@ -517,21 +541,15 @@ pub extern fn main() -> i32 {
|
||||||
io_expander1.service().unwrap();
|
io_expander1.service().unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(has_si5324)]
|
sysclk_setup();
|
||||||
si5324::setup(&SI5324_SETTINGS, si5324::Input::Ckin1).expect("cannot initialize Si5324");
|
|
||||||
#[cfg(has_wrpll)]
|
|
||||||
wrpll::init();
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
csr::drtio_transceiver::stable_clkin_write(1);
|
|
||||||
}
|
|
||||||
clock::spin_us(1500); // wait for CPLL/QPLL lock
|
|
||||||
#[cfg(not(has_jdcg))]
|
#[cfg(not(has_jdcg))]
|
||||||
unsafe {
|
unsafe {
|
||||||
csr::drtio_transceiver::txenable_write(0xffffffffu32 as _);
|
csr::drtio_transceiver::txenable_write(0xffffffffu32 as _);
|
||||||
}
|
}
|
||||||
#[cfg(has_wrpll)]
|
#[cfg(has_wrpll)]
|
||||||
wrpll::diagnostics();
|
wrpll::diagnostics();
|
||||||
|
|
||||||
init_rtio_crg();
|
init_rtio_crg();
|
||||||
|
|
||||||
#[cfg(has_hmc830_7043)]
|
#[cfg(has_hmc830_7043)]
|
||||||
|
|
|
@ -22,8 +22,7 @@ class Transmitter(Module, AutoCSR):
|
||||||
self.aux_tx = CSR()
|
self.aux_tx = CSR()
|
||||||
self.specials.mem = Memory(mem_dw, max_packet//(mem_dw//8))
|
self.specials.mem = Memory(mem_dw, max_packet//(mem_dw//8))
|
||||||
|
|
||||||
converter = ClockDomainsRenamer("rtio")(
|
converter = stream.Converter(mem_dw, ll_dw)
|
||||||
stream.Converter(mem_dw, ll_dw))
|
|
||||||
self.submodules += converter
|
self.submodules += converter
|
||||||
|
|
||||||
# when continuously fed, the Converter outputs data continuously
|
# when continuously fed, the Converter outputs data continuously
|
||||||
|
@ -36,7 +35,7 @@ class Transmitter(Module, AutoCSR):
|
||||||
seen_eop_rst = Signal()
|
seen_eop_rst = Signal()
|
||||||
frame_r = Signal()
|
frame_r = Signal()
|
||||||
seen_eop = Signal()
|
seen_eop = Signal()
|
||||||
self.sync.rtio += [
|
self.sync += [
|
||||||
If(link_layer.tx_aux_ack,
|
If(link_layer.tx_aux_ack,
|
||||||
frame_r.eq(link_layer.tx_aux_frame),
|
frame_r.eq(link_layer.tx_aux_frame),
|
||||||
If(frame_r & ~link_layer.tx_aux_frame, seen_eop.eq(1))
|
If(frame_r & ~link_layer.tx_aux_frame, seen_eop.eq(1))
|
||||||
|
@ -44,13 +43,9 @@ class Transmitter(Module, AutoCSR):
|
||||||
If(seen_eop_rst, seen_eop.eq(0))
|
If(seen_eop_rst, seen_eop.eq(0))
|
||||||
]
|
]
|
||||||
|
|
||||||
mem_port = self.mem.get_port(clock_domain="rtio")
|
mem_port = self.mem.get_port()
|
||||||
self.specials += mem_port
|
self.specials += mem_port
|
||||||
|
|
||||||
self.aux_tx_length.storage.attr.add("no_retiming")
|
|
||||||
tx_length = Signal(bits_for(max_packet))
|
|
||||||
self.specials += MultiReg(self.aux_tx_length.storage, tx_length, "rtio")
|
|
||||||
|
|
||||||
frame_counter_nbits = bits_for(max_packet) - log2_int(mem_dw//8)
|
frame_counter_nbits = bits_for(max_packet) - log2_int(mem_dw//8)
|
||||||
frame_counter = Signal(frame_counter_nbits)
|
frame_counter = Signal(frame_counter_nbits)
|
||||||
frame_counter_next = Signal(frame_counter_nbits)
|
frame_counter_next = Signal(frame_counter_nbits)
|
||||||
|
@ -66,35 +61,33 @@ class Transmitter(Module, AutoCSR):
|
||||||
mem_port.adr.eq(frame_counter_next),
|
mem_port.adr.eq(frame_counter_next),
|
||||||
converter.sink.data.eq(mem_port.dat_r)
|
converter.sink.data.eq(mem_port.dat_r)
|
||||||
]
|
]
|
||||||
self.sync.rtio += frame_counter.eq(frame_counter_next)
|
|
||||||
|
|
||||||
start_tx = PulseSynchronizer("sys", "rtio")
|
tx_done = Signal()
|
||||||
tx_done = PulseSynchronizer("rtio", "sys")
|
|
||||||
self.submodules += start_tx, tx_done
|
|
||||||
self.comb += start_tx.i.eq(self.aux_tx.re)
|
|
||||||
self.sync += [
|
self.sync += [
|
||||||
If(tx_done.o, self.aux_tx.w.eq(0)),
|
frame_counter.eq(frame_counter_next),
|
||||||
If(self.aux_tx.re, self.aux_tx.w.eq(1))
|
If(self.aux_tx.re, self.aux_tx.w.eq(1)),
|
||||||
|
If(tx_done, self.aux_tx.w.eq(0))
|
||||||
]
|
]
|
||||||
|
|
||||||
fsm = ClockDomainsRenamer("rtio")(FSM(reset_state="IDLE"))
|
fsm = FSM(reset_state="IDLE")
|
||||||
self.submodules += fsm
|
self.submodules += fsm
|
||||||
|
|
||||||
fsm.act("IDLE",
|
fsm.act("IDLE",
|
||||||
frame_counter_rst.eq(1),
|
frame_counter_rst.eq(1),
|
||||||
seen_eop_rst.eq(1),
|
seen_eop_rst.eq(1),
|
||||||
If(start_tx.o, NextState("TRANSMIT"))
|
If(self.aux_tx.re, NextState("TRANSMIT"))
|
||||||
)
|
)
|
||||||
fsm.act("TRANSMIT",
|
fsm.act("TRANSMIT",
|
||||||
converter.sink.stb.eq(1),
|
converter.sink.stb.eq(1),
|
||||||
If(converter.sink.ack,
|
If(converter.sink.ack,
|
||||||
frame_counter_ce.eq(1)
|
frame_counter_ce.eq(1)
|
||||||
),
|
),
|
||||||
If(frame_counter_next == tx_length, NextState("WAIT_INTERFRAME"))
|
If(frame_counter_next == self.aux_tx_length.storage,
|
||||||
|
NextState("WAIT_INTERFRAME"))
|
||||||
)
|
)
|
||||||
fsm.act("WAIT_INTERFRAME",
|
fsm.act("WAIT_INTERFRAME",
|
||||||
If(seen_eop,
|
If(seen_eop,
|
||||||
tx_done.i.eq(1),
|
tx_done.eq(1),
|
||||||
NextState("IDLE")
|
NextState("IDLE")
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
|
@ -2,7 +2,6 @@ from types import SimpleNamespace
|
||||||
|
|
||||||
from migen import *
|
from migen import *
|
||||||
from migen.genlib.resetsync import AsyncResetSynchronizer
|
from migen.genlib.resetsync import AsyncResetSynchronizer
|
||||||
from migen.genlib.cdc import PulseSynchronizer
|
|
||||||
from misoc.interconnect.csr import *
|
from misoc.interconnect.csr import *
|
||||||
|
|
||||||
from artiq.gateware.rtio import cri, rtlink
|
from artiq.gateware.rtio import cri, rtlink
|
||||||
|
@ -31,7 +30,6 @@ class TransceiverInterface(AutoCSR):
|
||||||
def __init__(self, channel_interfaces):
|
def __init__(self, channel_interfaces):
|
||||||
self.stable_clkin = CSRStorage()
|
self.stable_clkin = CSRStorage()
|
||||||
self.txenable = CSRStorage(len(channel_interfaces))
|
self.txenable = CSRStorage(len(channel_interfaces))
|
||||||
self.clock_domains.cd_rtio = ClockDomain()
|
|
||||||
for i in range(len(channel_interfaces)):
|
for i in range(len(channel_interfaces)):
|
||||||
name = "rtio_rx" + str(i)
|
name = "rtio_rx" + str(i)
|
||||||
setattr(self.clock_domains, "cd_"+name, ClockDomain(name=name))
|
setattr(self.clock_domains, "cd_"+name, ClockDomain(name=name))
|
||||||
|
@ -65,7 +63,7 @@ class SyncRTIO(Module):
|
||||||
enable_spread=False, report_buffer_space=True,
|
enable_spread=False, report_buffer_space=True,
|
||||||
interface=self.cri))
|
interface=self.cri))
|
||||||
self.comb += self.outputs.coarse_timestamp.eq(tsc.coarse_ts)
|
self.comb += self.outputs.coarse_timestamp.eq(tsc.coarse_ts)
|
||||||
self.sync.rtio += self.outputs.minimum_coarse_timestamp.eq(tsc.coarse_ts + 16)
|
self.sync += self.outputs.minimum_coarse_timestamp.eq(tsc.coarse_ts + 16)
|
||||||
|
|
||||||
self.submodules.inputs = ClockDomainsRenamer("rio")(
|
self.submodules.inputs = ClockDomainsRenamer("rio")(
|
||||||
InputCollector(tsc, channels, "sync", interface=self.cri))
|
InputCollector(tsc, channels, "sync", interface=self.cri))
|
||||||
|
@ -86,8 +84,8 @@ class DRTIOSatellite(Module):
|
||||||
self.clock_domains.cd_rio = ClockDomain()
|
self.clock_domains.cd_rio = ClockDomain()
|
||||||
self.clock_domains.cd_rio_phy = ClockDomain()
|
self.clock_domains.cd_rio_phy = ClockDomain()
|
||||||
self.comb += [
|
self.comb += [
|
||||||
self.cd_rio.clk.eq(ClockSignal("rtio")),
|
self.cd_rio.clk.eq(ClockSignal("sys")),
|
||||||
self.cd_rio_phy.clk.eq(ClockSignal("rtio"))
|
self.cd_rio_phy.clk.eq(ClockSignal("sys"))
|
||||||
]
|
]
|
||||||
reset = Signal()
|
reset = Signal()
|
||||||
reset_phy = Signal()
|
reset_phy = Signal()
|
||||||
|
@ -125,9 +123,9 @@ class DRTIOSatellite(Module):
|
||||||
rx_rt_frame_perm=rx_synchronizer.resync(self.link_layer.rx_rt_frame_perm),
|
rx_rt_frame_perm=rx_synchronizer.resync(self.link_layer.rx_rt_frame_perm),
|
||||||
rx_rt_data=rx_synchronizer.resync(self.link_layer.rx_rt_data)
|
rx_rt_data=rx_synchronizer.resync(self.link_layer.rx_rt_data)
|
||||||
)
|
)
|
||||||
self.submodules.link_stats = link_layer.LinkLayerStats(link_layer_sync, "rtio")
|
self.submodules.link_stats = link_layer.LinkLayerStats(link_layer_sync, "sys")
|
||||||
self.submodules.rt_packet = ClockDomainsRenamer("rtio")(
|
self.submodules.rt_packet = rt_packet_satellite.RTPacketSatellite(
|
||||||
rt_packet_satellite.RTPacketSatellite(link_layer_sync, interface=self.cri))
|
link_layer_sync, interface=self.cri)
|
||||||
self.comb += self.rt_packet.reset.eq(self.cd_rio.rst)
|
self.comb += self.rt_packet.reset.eq(self.cd_rio.rst)
|
||||||
|
|
||||||
self.comb += [
|
self.comb += [
|
||||||
|
@ -135,12 +133,9 @@ class DRTIOSatellite(Module):
|
||||||
tsc.load_value.eq(self.rt_packet.tsc_load_value)
|
tsc.load_value.eq(self.rt_packet.tsc_load_value)
|
||||||
]
|
]
|
||||||
|
|
||||||
ps_tsc_load = PulseSynchronizer("rtio", "sys")
|
|
||||||
self.submodules += ps_tsc_load
|
|
||||||
self.comb += ps_tsc_load.i.eq(self.rt_packet.tsc_load)
|
|
||||||
self.sync += [
|
self.sync += [
|
||||||
If(self.tsc_loaded.re, self.tsc_loaded.w.eq(0)),
|
If(self.tsc_loaded.re, self.tsc_loaded.w.eq(0)),
|
||||||
If(ps_tsc_load.o, self.tsc_loaded.w.eq(1))
|
If(self.rt_packet.tsc_load, self.tsc_loaded.w.eq(1))
|
||||||
]
|
]
|
||||||
|
|
||||||
self.submodules.rt_errors = rt_errors_satellite.RTErrorsSatellite(
|
self.submodules.rt_errors = rt_errors_satellite.RTErrorsSatellite(
|
||||||
|
|
|
@ -232,7 +232,7 @@ class LinkLayer(Module, AutoCSR):
|
||||||
# receiver locked, comma aligned, receiving valid 8b10b symbols
|
# receiver locked, comma aligned, receiving valid 8b10b symbols
|
||||||
self.rx_ready = Signal()
|
self.rx_ready = Signal()
|
||||||
|
|
||||||
tx = ClockDomainsRenamer("rtio")(LinkLayerTX(encoder))
|
tx = LinkLayerTX(encoder)
|
||||||
rx = ClockDomainsRenamer("rtio_rx")(LinkLayerRX(decoders))
|
rx = ClockDomainsRenamer("rtio_rx")(LinkLayerRX(decoders))
|
||||||
self.submodules += tx, rx
|
self.submodules += tx, rx
|
||||||
|
|
||||||
|
@ -256,31 +256,23 @@ class LinkLayer(Module, AutoCSR):
|
||||||
|
|
||||||
rx_up = Signal()
|
rx_up = Signal()
|
||||||
rx_up_r = Signal()
|
rx_up_r = Signal()
|
||||||
self.sync.rtio += rx_up_r.eq(rx_up)
|
self.sync += rx_up_r.eq(rx_up)
|
||||||
rx_up_rx = Signal()
|
rx_up_rx = Signal()
|
||||||
rx_up_r.attr.add("no_retiming")
|
rx_up_r.attr.add("no_retiming")
|
||||||
self.specials += [
|
self.specials += [
|
||||||
MultiReg(rx_up_r, rx_up_rx, "rtio_rx"),
|
MultiReg(rx_up_r, rx_up_rx, "rtio_rx"),
|
||||||
MultiReg(rx_up_r, self.rx_up.status)]
|
MultiReg(rx_up_r, self.rx_up.status)]
|
||||||
|
|
||||||
tx_force_aux_zero_rtio = Signal()
|
|
||||||
tx_force_rt_zero_rtio = Signal()
|
|
||||||
self.tx_force_aux_zero.storage.attr.add("no_retiming")
|
|
||||||
self.tx_force_rt_zero.storage.attr.add("no_retiming")
|
|
||||||
self.specials += [
|
|
||||||
MultiReg(self.tx_force_aux_zero.storage, tx_force_aux_zero_rtio, "rtio"),
|
|
||||||
MultiReg(self.tx_force_rt_zero.storage, tx_force_rt_zero_rtio, "rtio")]
|
|
||||||
|
|
||||||
rx_disable_rx = Signal()
|
rx_disable_rx = Signal()
|
||||||
self.rx_disable.storage.attr.add("no_retiming")
|
self.rx_disable.storage.attr.add("no_retiming")
|
||||||
self.specials += MultiReg(self.rx_disable.storage, rx_disable_rx, "rtio_rx")
|
self.specials += MultiReg(self.rx_disable.storage, rx_disable_rx, "rtio_rx")
|
||||||
|
|
||||||
self.comb += [
|
self.comb += [
|
||||||
tx.aux_frame.eq(self.tx_aux_frame | tx_force_aux_zero_rtio),
|
tx.aux_frame.eq(self.tx_aux_frame | self.tx_force_aux_zero.storage),
|
||||||
tx.aux_data.eq(Mux(tx_force_aux_zero_rtio, 0, self.tx_aux_data)),
|
tx.aux_data.eq(Mux(self.tx_force_aux_zero.storage, 0, self.tx_aux_data)),
|
||||||
self.tx_aux_ack.eq(tx.aux_ack),
|
self.tx_aux_ack.eq(tx.aux_ack),
|
||||||
tx.rt_frame.eq(self.tx_rt_frame | tx_force_rt_zero_rtio),
|
tx.rt_frame.eq(self.tx_rt_frame | self.tx_force_rt_zero.storage),
|
||||||
tx.rt_data.eq(Mux(tx_force_rt_zero_rtio, 0, self.tx_rt_data))
|
tx.rt_data.eq(Mux(self.tx_force_rt_zero.storage, 0, self.tx_rt_data))
|
||||||
]
|
]
|
||||||
# we register those to improve timing margins, as the data may need
|
# we register those to improve timing margins, as the data may need
|
||||||
# to be recaptured by RXSynchronizer.
|
# to be recaptured by RXSynchronizer.
|
||||||
|
@ -294,10 +286,10 @@ class LinkLayer(Module, AutoCSR):
|
||||||
self.rx_rt_data.eq(rx.rt_data)
|
self.rx_rt_data.eq(rx.rt_data)
|
||||||
]
|
]
|
||||||
|
|
||||||
wait_scrambler = ClockDomainsRenamer("rtio")(WaitTimer(15))
|
wait_scrambler = WaitTimer(15)
|
||||||
self.submodules += wait_scrambler
|
self.submodules += wait_scrambler
|
||||||
|
|
||||||
fsm = ClockDomainsRenamer("rtio")(FSM(reset_state="WAIT_RX_READY"))
|
fsm = FSM(reset_state="WAIT_RX_READY")
|
||||||
self.submodules += fsm
|
self.submodules += fsm
|
||||||
|
|
||||||
fsm.act("WAIT_RX_READY",
|
fsm.act("WAIT_RX_READY",
|
||||||
|
|
|
@ -108,7 +108,7 @@ class RTController(Module):
|
||||||
|
|
||||||
cond_underflow = Signal()
|
cond_underflow = Signal()
|
||||||
self.comb += cond_underflow.eq((self.cri.o_timestamp[tsc.glbl_fine_ts_width:]
|
self.comb += cond_underflow.eq((self.cri.o_timestamp[tsc.glbl_fine_ts_width:]
|
||||||
- self.csrs.underflow_margin.storage[tsc.glbl_fine_ts_width:]) < tsc.coarse_ts_sys)
|
- self.csrs.underflow_margin.storage[tsc.glbl_fine_ts_width:]) < tsc.coarse_ts)
|
||||||
|
|
||||||
# buffer space
|
# buffer space
|
||||||
buffer_space = Memory(16, 256)
|
buffer_space = Memory(16, 256)
|
||||||
|
|
|
@ -15,15 +15,11 @@ class RTController(Module, AutoCSR):
|
||||||
self.command_missed_chan_sel = CSRStatus(24)
|
self.command_missed_chan_sel = CSRStatus(24)
|
||||||
self.buffer_space_timeout_dest = CSRStatus(8)
|
self.buffer_space_timeout_dest = CSRStatus(8)
|
||||||
|
|
||||||
self.specials += MultiReg(self.reset.storage, rt_packet.reset, "rtio")
|
self.sync += rt_packet.reset.eq(self.reset.storage)
|
||||||
|
|
||||||
set_time_stb = Signal()
|
set_time_stb = Signal()
|
||||||
set_time_ack = Signal()
|
|
||||||
self.submodules += CrossDomainRequest("rtio",
|
|
||||||
set_time_stb, set_time_ack, None,
|
|
||||||
rt_packet.set_time_stb, rt_packet.set_time_ack, None)
|
|
||||||
self.sync += [
|
self.sync += [
|
||||||
If(set_time_ack, set_time_stb.eq(0)),
|
If(rt_packet.set_time_stb, set_time_stb.eq(0)),
|
||||||
If(self.set_time.re, set_time_stb.eq(1))
|
If(self.set_time.re, set_time_stb.eq(1))
|
||||||
]
|
]
|
||||||
self.comb += self.set_time.w.eq(set_time_stb)
|
self.comb += self.set_time.w.eq(set_time_stb)
|
||||||
|
@ -31,10 +27,10 @@ class RTController(Module, AutoCSR):
|
||||||
errors = [
|
errors = [
|
||||||
(rt_packet.err_unknown_packet_type, "rtio_rx", None, None),
|
(rt_packet.err_unknown_packet_type, "rtio_rx", None, None),
|
||||||
(rt_packet.err_packet_truncated, "rtio_rx", None, None),
|
(rt_packet.err_packet_truncated, "rtio_rx", None, None),
|
||||||
(rt_packet.err_command_missed, "rtio",
|
(rt_packet.err_command_missed, "sys",
|
||||||
Cat(rt_packet.command_missed_cmd, rt_packet.command_missed_chan_sel),
|
Cat(rt_packet.command_missed_cmd, rt_packet.command_missed_chan_sel),
|
||||||
Cat(self.command_missed_cmd.status, self.command_missed_chan_sel.status)),
|
Cat(self.command_missed_cmd.status, self.command_missed_chan_sel.status)),
|
||||||
(rt_packet.err_buffer_space_timeout, "rtio",
|
(rt_packet.err_buffer_space_timeout, "sys",
|
||||||
rt_packet.buffer_space_destination, self.buffer_space_timeout_dest.status)
|
rt_packet.buffer_space_destination, self.buffer_space_timeout_dest.status)
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
from migen import *
|
from migen import *
|
||||||
from migen.genlib.fsm import *
|
from migen.genlib.fsm import *
|
||||||
from migen.genlib.fifo import AsyncFIFO
|
from migen.genlib.fifo import SyncFIFO
|
||||||
from migen.genlib.cdc import BlindTransfer
|
from migen.genlib.cdc import BlindTransfer
|
||||||
|
|
||||||
from artiq.gateware.rtio.cdc import GrayCodeTransfer
|
from artiq.gateware.rtio.cdc import GrayCodeTransfer
|
||||||
|
@ -76,8 +76,8 @@ class RTPacketMaster(Module):
|
||||||
assert len(link_layer.tx_rt_data) % 8 == 0
|
assert len(link_layer.tx_rt_data) % 8 == 0
|
||||||
ws = len(link_layer.tx_rt_data)
|
ws = len(link_layer.tx_rt_data)
|
||||||
tx_plm = get_m2s_layouts(ws)
|
tx_plm = get_m2s_layouts(ws)
|
||||||
tx_dp = ClockDomainsRenamer("rtio")(TransmitDatapath(
|
tx_dp = TransmitDatapath(
|
||||||
link_layer.tx_rt_frame, link_layer.tx_rt_data, tx_plm))
|
link_layer.tx_rt_frame, link_layer.tx_rt_data, tx_plm)
|
||||||
self.submodules += tx_dp
|
self.submodules += tx_dp
|
||||||
rx_plm = get_s2m_layouts(ws)
|
rx_plm = get_s2m_layouts(ws)
|
||||||
rx_dp = ClockDomainsRenamer("rtio_rx")(ReceiveDatapath(
|
rx_dp = ClockDomainsRenamer("rtio_rx")(ReceiveDatapath(
|
||||||
|
@ -85,8 +85,7 @@ class RTPacketMaster(Module):
|
||||||
self.submodules += rx_dp
|
self.submodules += rx_dp
|
||||||
|
|
||||||
# Write FIFO and extra data count
|
# Write FIFO and extra data count
|
||||||
sr_fifo = ClockDomainsRenamer({"write": "sys", "read": "rtio"})(
|
sr_fifo = SyncFIFO(1+64+24+8+512, sr_fifo_depth)
|
||||||
AsyncFIFO(1+64+24+8+512, sr_fifo_depth))
|
|
||||||
self.submodules += sr_fifo
|
self.submodules += sr_fifo
|
||||||
sr_notwrite_d = Signal()
|
sr_notwrite_d = Signal()
|
||||||
sr_timestamp_d = Signal(64)
|
sr_timestamp_d = Signal(64)
|
||||||
|
@ -106,7 +105,7 @@ class RTPacketMaster(Module):
|
||||||
sr_buf_re = Signal()
|
sr_buf_re = Signal()
|
||||||
|
|
||||||
self.comb += sr_fifo.re.eq(sr_fifo.readable & (~sr_buf_readable | sr_buf_re))
|
self.comb += sr_fifo.re.eq(sr_fifo.readable & (~sr_buf_readable | sr_buf_re))
|
||||||
self.sync.rtio += \
|
self.sync += \
|
||||||
If(sr_fifo.re,
|
If(sr_fifo.re,
|
||||||
sr_buf_readable.eq(1),
|
sr_buf_readable.eq(1),
|
||||||
).Elif(sr_buf_re,
|
).Elif(sr_buf_re,
|
||||||
|
@ -120,7 +119,7 @@ class RTPacketMaster(Module):
|
||||||
sr_extra_data_cnt = Signal(8)
|
sr_extra_data_cnt = Signal(8)
|
||||||
sr_data = Signal(512)
|
sr_data = Signal(512)
|
||||||
|
|
||||||
self.sync.rtio += If(sr_fifo.re,
|
self.sync += If(sr_fifo.re,
|
||||||
sr_notwrite.eq(sr_notwrite_d),
|
sr_notwrite.eq(sr_notwrite_d),
|
||||||
sr_timestamp.eq(sr_timestamp_d),
|
sr_timestamp.eq(sr_timestamp_d),
|
||||||
sr_chan_sel.eq(sr_chan_sel_d),
|
sr_chan_sel.eq(sr_chan_sel_d),
|
||||||
|
@ -131,11 +130,11 @@ class RTPacketMaster(Module):
|
||||||
sr_extra_data_d = Signal(512)
|
sr_extra_data_d = Signal(512)
|
||||||
self.comb += sr_extra_data_d.eq(sr_data_d[short_data_len:])
|
self.comb += sr_extra_data_d.eq(sr_data_d[short_data_len:])
|
||||||
for i in range(512//ws):
|
for i in range(512//ws):
|
||||||
self.sync.rtio += If(sr_fifo.re,
|
self.sync += If(sr_fifo.re,
|
||||||
If(sr_extra_data_d[ws*i:ws*(i+1)] != 0, sr_extra_data_cnt.eq(i+1)))
|
If(sr_extra_data_d[ws*i:ws*(i+1)] != 0, sr_extra_data_cnt.eq(i+1)))
|
||||||
|
|
||||||
sr_extra_data = Signal(512)
|
sr_extra_data = Signal(512)
|
||||||
self.sync.rtio += If(sr_fifo.re, sr_extra_data.eq(sr_extra_data_d))
|
self.sync += If(sr_fifo.re, sr_extra_data.eq(sr_extra_data_d))
|
||||||
|
|
||||||
extra_data_ce = Signal()
|
extra_data_ce = Signal()
|
||||||
extra_data_last = Signal()
|
extra_data_last = Signal()
|
||||||
|
@ -146,7 +145,7 @@ class RTPacketMaster(Module):
|
||||||
for i in range(512//ws)}),
|
for i in range(512//ws)}),
|
||||||
extra_data_last.eq(extra_data_counter == sr_extra_data_cnt)
|
extra_data_last.eq(extra_data_counter == sr_extra_data_cnt)
|
||||||
]
|
]
|
||||||
self.sync.rtio += \
|
self.sync += \
|
||||||
If(extra_data_ce,
|
If(extra_data_ce,
|
||||||
extra_data_counter.eq(extra_data_counter + 1),
|
extra_data_counter.eq(extra_data_counter + 1),
|
||||||
).Else(
|
).Else(
|
||||||
|
@ -160,18 +159,6 @@ class RTPacketMaster(Module):
|
||||||
buffer_space_not, buffer_space,
|
buffer_space_not, buffer_space,
|
||||||
self.buffer_space_not, self.buffer_space_not_ack, self.buffer_space)
|
self.buffer_space_not, self.buffer_space_not_ack, self.buffer_space)
|
||||||
|
|
||||||
set_time_stb = Signal()
|
|
||||||
set_time_ack = Signal()
|
|
||||||
self.submodules += CrossDomainRequest("rtio",
|
|
||||||
self.set_time_stb, self.set_time_ack, None,
|
|
||||||
set_time_stb, set_time_ack, None)
|
|
||||||
|
|
||||||
echo_stb = Signal()
|
|
||||||
echo_ack = Signal()
|
|
||||||
self.submodules += CrossDomainRequest("rtio",
|
|
||||||
self.echo_stb, self.echo_ack, None,
|
|
||||||
echo_stb, echo_ack, None)
|
|
||||||
|
|
||||||
read_not = Signal()
|
read_not = Signal()
|
||||||
read_no_event = Signal()
|
read_no_event = Signal()
|
||||||
read_is_overflow = Signal()
|
read_is_overflow = Signal()
|
||||||
|
@ -199,14 +186,14 @@ class RTPacketMaster(Module):
|
||||||
]
|
]
|
||||||
|
|
||||||
# TX FSM
|
# TX FSM
|
||||||
tx_fsm = ClockDomainsRenamer("rtio")(FSM(reset_state="IDLE"))
|
tx_fsm = FSM(reset_state="IDLE")
|
||||||
self.submodules += tx_fsm
|
self.submodules += tx_fsm
|
||||||
|
|
||||||
echo_sent_now = Signal()
|
echo_sent_now = Signal()
|
||||||
self.sync.rtio += self.echo_sent_now.eq(echo_sent_now)
|
self.sync += self.echo_sent_now.eq(echo_sent_now)
|
||||||
tsc_value = Signal(64)
|
tsc_value = Signal(64)
|
||||||
tsc_value_load = Signal()
|
tsc_value_load = Signal()
|
||||||
self.sync.rtio += If(tsc_value_load, tsc_value.eq(self.tsc_value))
|
self.sync += If(tsc_value_load, tsc_value.eq(self.tsc_value))
|
||||||
|
|
||||||
tx_fsm.act("IDLE",
|
tx_fsm.act("IDLE",
|
||||||
# Ensure 2 cycles between frames on the link.
|
# Ensure 2 cycles between frames on the link.
|
||||||
|
@ -223,10 +210,10 @@ class RTPacketMaster(Module):
|
||||||
NextState("WRITE")
|
NextState("WRITE")
|
||||||
)
|
)
|
||||||
).Else(
|
).Else(
|
||||||
If(echo_stb,
|
If(self.echo_stb,
|
||||||
echo_sent_now.eq(1),
|
echo_sent_now.eq(1),
|
||||||
NextState("ECHO")
|
NextState("ECHO")
|
||||||
).Elif(set_time_stb,
|
).Elif(self.set_time_stb,
|
||||||
tsc_value_load.eq(1),
|
tsc_value_load.eq(1),
|
||||||
NextState("SET_TIME")
|
NextState("SET_TIME")
|
||||||
)
|
)
|
||||||
|
@ -273,14 +260,14 @@ class RTPacketMaster(Module):
|
||||||
tx_fsm.act("ECHO",
|
tx_fsm.act("ECHO",
|
||||||
tx_dp.send("echo_request"),
|
tx_dp.send("echo_request"),
|
||||||
If(tx_dp.packet_last,
|
If(tx_dp.packet_last,
|
||||||
echo_ack.eq(1),
|
self.echo_ack.eq(1),
|
||||||
NextState("IDLE")
|
NextState("IDLE")
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
tx_fsm.act("SET_TIME",
|
tx_fsm.act("SET_TIME",
|
||||||
tx_dp.send("set_time", timestamp=tsc_value),
|
tx_dp.send("set_time", timestamp=tsc_value),
|
||||||
If(tx_dp.packet_last,
|
If(tx_dp.packet_last,
|
||||||
set_time_ack.eq(1),
|
self.set_time_ack.eq(1),
|
||||||
NextState("IDLE")
|
NextState("IDLE")
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
@ -334,16 +321,14 @@ class RTPacketMaster(Module):
|
||||||
# packet counters
|
# packet counters
|
||||||
tx_frame_r = Signal()
|
tx_frame_r = Signal()
|
||||||
packet_cnt_tx = Signal(32)
|
packet_cnt_tx = Signal(32)
|
||||||
self.sync.rtio += [
|
self.sync += [
|
||||||
tx_frame_r.eq(link_layer.tx_rt_frame),
|
tx_frame_r.eq(link_layer.tx_rt_frame),
|
||||||
If(link_layer.tx_rt_frame & ~tx_frame_r,
|
If(link_layer.tx_rt_frame & ~tx_frame_r,
|
||||||
packet_cnt_tx.eq(packet_cnt_tx + 1))
|
packet_cnt_tx.eq(packet_cnt_tx + 1))
|
||||||
]
|
]
|
||||||
cdc_packet_cnt_tx = GrayCodeTransfer(32)
|
|
||||||
self.submodules += cdc_packet_cnt_tx
|
|
||||||
self.comb += [
|
self.comb += [
|
||||||
cdc_packet_cnt_tx.i.eq(packet_cnt_tx),
|
self.packet_cnt_tx.eq(packet_cnt_tx)
|
||||||
self.packet_cnt_tx.eq(cdc_packet_cnt_tx.o)
|
|
||||||
]
|
]
|
||||||
|
|
||||||
rx_frame_r = Signal()
|
rx_frame_r = Signal()
|
||||||
|
@ -353,7 +338,7 @@ class RTPacketMaster(Module):
|
||||||
If(link_layer.rx_rt_frame & ~rx_frame_r,
|
If(link_layer.rx_rt_frame & ~rx_frame_r,
|
||||||
packet_cnt_rx.eq(packet_cnt_rx + 1))
|
packet_cnt_rx.eq(packet_cnt_rx + 1))
|
||||||
]
|
]
|
||||||
cdc_packet_cnt_rx = ClockDomainsRenamer({"rtio": "rtio_rx"})(
|
cdc_packet_cnt_rx = ClockDomainsRenamer({"rtio": "sys", "sys": "rtio_rx"})(
|
||||||
GrayCodeTransfer(32))
|
GrayCodeTransfer(32))
|
||||||
self.submodules += cdc_packet_cnt_rx
|
self.submodules += cdc_packet_cnt_rx
|
||||||
self.comb += [
|
self.comb += [
|
||||||
|
|
|
@ -38,8 +38,8 @@ class RTPacketRepeater(Module):
|
||||||
assert len(link_layer.tx_rt_data) % 8 == 0
|
assert len(link_layer.tx_rt_data) % 8 == 0
|
||||||
ws = len(link_layer.tx_rt_data)
|
ws = len(link_layer.tx_rt_data)
|
||||||
tx_plm = get_m2s_layouts(ws)
|
tx_plm = get_m2s_layouts(ws)
|
||||||
tx_dp = ClockDomainsRenamer("rtio")(TransmitDatapath(
|
tx_dp = TransmitDatapath(
|
||||||
link_layer.tx_rt_frame, link_layer.tx_rt_data, tx_plm))
|
link_layer.tx_rt_frame, link_layer.tx_rt_data, tx_plm)
|
||||||
self.submodules += tx_dp
|
self.submodules += tx_dp
|
||||||
rx_plm = get_s2m_layouts(ws)
|
rx_plm = get_s2m_layouts(ws)
|
||||||
rx_dp = ClockDomainsRenamer("rtio_rx")(ReceiveDatapath(
|
rx_dp = ClockDomainsRenamer("rtio_rx")(ReceiveDatapath(
|
||||||
|
@ -49,7 +49,7 @@ class RTPacketRepeater(Module):
|
||||||
# TSC sync
|
# TSC sync
|
||||||
tsc_value = Signal(64)
|
tsc_value = Signal(64)
|
||||||
tsc_value_load = Signal()
|
tsc_value_load = Signal()
|
||||||
self.sync.rtio += If(tsc_value_load, tsc_value.eq(tsc.coarse_ts))
|
self.sync += If(tsc_value_load, tsc_value.eq(tsc.coarse_ts))
|
||||||
|
|
||||||
# CRI buffer stage 1
|
# CRI buffer stage 1
|
||||||
cb0_loaded = Signal()
|
cb0_loaded = Signal()
|
||||||
|
@ -60,7 +60,7 @@ class RTPacketRepeater(Module):
|
||||||
cb0_chan_sel = Signal(24)
|
cb0_chan_sel = Signal(24)
|
||||||
cb0_o_address = Signal(8)
|
cb0_o_address = Signal(8)
|
||||||
cb0_o_data = Signal(512)
|
cb0_o_data = Signal(512)
|
||||||
self.sync.rtio += [
|
self.sync += [
|
||||||
If(self.reset | cb0_ack,
|
If(self.reset | cb0_ack,
|
||||||
cb0_loaded.eq(0),
|
cb0_loaded.eq(0),
|
||||||
cb0_cmd.eq(cri.commands["nop"])
|
cb0_cmd.eq(cri.commands["nop"])
|
||||||
|
@ -91,7 +91,7 @@ class RTPacketRepeater(Module):
|
||||||
cb_chan_sel = Signal(24)
|
cb_chan_sel = Signal(24)
|
||||||
cb_o_address = Signal(8)
|
cb_o_address = Signal(8)
|
||||||
cb_o_data = Signal(512)
|
cb_o_data = Signal(512)
|
||||||
self.sync.rtio += [
|
self.sync += [
|
||||||
If(self.reset | cb_ack,
|
If(self.reset | cb_ack,
|
||||||
cb_loaded.eq(0),
|
cb_loaded.eq(0),
|
||||||
cb_cmd.eq(cri.commands["nop"])
|
cb_cmd.eq(cri.commands["nop"])
|
||||||
|
@ -112,11 +112,11 @@ class RTPacketRepeater(Module):
|
||||||
wb_extra_data_a = Signal(512)
|
wb_extra_data_a = Signal(512)
|
||||||
self.comb += wb_extra_data_a.eq(self.cri.o_data[short_data_len:])
|
self.comb += wb_extra_data_a.eq(self.cri.o_data[short_data_len:])
|
||||||
for i in range(512//ws):
|
for i in range(512//ws):
|
||||||
self.sync.rtio += If(self.cri.cmd == cri.commands["write"],
|
self.sync += If(self.cri.cmd == cri.commands["write"],
|
||||||
If(wb_extra_data_a[ws*i:ws*(i+1)] != 0, wb_extra_data_cnt.eq(i+1)))
|
If(wb_extra_data_a[ws*i:ws*(i+1)] != 0, wb_extra_data_cnt.eq(i+1)))
|
||||||
|
|
||||||
wb_extra_data = Signal(512)
|
wb_extra_data = Signal(512)
|
||||||
self.sync.rtio += If(self.cri.cmd == cri.commands["write"],
|
self.sync += If(self.cri.cmd == cri.commands["write"],
|
||||||
wb_extra_data.eq(wb_extra_data_a))
|
wb_extra_data.eq(wb_extra_data_a))
|
||||||
|
|
||||||
extra_data_ce = Signal()
|
extra_data_ce = Signal()
|
||||||
|
@ -128,7 +128,7 @@ class RTPacketRepeater(Module):
|
||||||
for i in range(512//ws)}),
|
for i in range(512//ws)}),
|
||||||
extra_data_last.eq(extra_data_counter == wb_extra_data_cnt)
|
extra_data_last.eq(extra_data_counter == wb_extra_data_cnt)
|
||||||
]
|
]
|
||||||
self.sync.rtio += \
|
self.sync += \
|
||||||
If(extra_data_ce,
|
If(extra_data_ce,
|
||||||
extra_data_counter.eq(extra_data_counter + 1),
|
extra_data_counter.eq(extra_data_counter + 1),
|
||||||
).Else(
|
).Else(
|
||||||
|
@ -136,19 +136,19 @@ class RTPacketRepeater(Module):
|
||||||
)
|
)
|
||||||
|
|
||||||
# Buffer space
|
# Buffer space
|
||||||
self.sync.rtio += If(self.cri.cmd == cri.commands["get_buffer_space"],
|
self.sync += If(self.cri.cmd == cri.commands["get_buffer_space"],
|
||||||
self.buffer_space_destination.eq(self.cri.chan_sel[16:]))
|
self.buffer_space_destination.eq(self.cri.chan_sel[16:]))
|
||||||
|
|
||||||
rx_buffer_space_not = Signal()
|
rx_buffer_space_not = Signal()
|
||||||
rx_buffer_space = Signal(16)
|
rx_buffer_space = Signal(16)
|
||||||
buffer_space_not = Signal()
|
buffer_space_not = Signal()
|
||||||
buffer_space_not_ack = Signal()
|
buffer_space_not_ack = Signal()
|
||||||
self.submodules += CrossDomainNotification("rtio_rx", "rtio",
|
self.submodules += CrossDomainNotification("rtio_rx", "sys",
|
||||||
rx_buffer_space_not, rx_buffer_space,
|
rx_buffer_space_not, rx_buffer_space,
|
||||||
buffer_space_not, buffer_space_not_ack,
|
buffer_space_not, buffer_space_not_ack,
|
||||||
self.cri.o_buffer_space)
|
self.cri.o_buffer_space)
|
||||||
|
|
||||||
timeout_counter = ClockDomainsRenamer("rtio")(WaitTimer(8191))
|
timeout_counter = WaitTimer(8191)
|
||||||
self.submodules += timeout_counter
|
self.submodules += timeout_counter
|
||||||
|
|
||||||
# Read
|
# Read
|
||||||
|
@ -163,7 +163,7 @@ class RTPacketRepeater(Module):
|
||||||
rtio_read_is_overflow = Signal()
|
rtio_read_is_overflow = Signal()
|
||||||
rtio_read_data = Signal(32)
|
rtio_read_data = Signal(32)
|
||||||
rtio_read_timestamp = Signal(64)
|
rtio_read_timestamp = Signal(64)
|
||||||
self.submodules += CrossDomainNotification("rtio_rx", "rtio",
|
self.submodules += CrossDomainNotification("rtio_rx", "sys",
|
||||||
read_not,
|
read_not,
|
||||||
Cat(read_no_event, read_is_overflow, read_data, read_timestamp),
|
Cat(read_no_event, read_is_overflow, read_data, read_timestamp),
|
||||||
|
|
||||||
|
@ -183,7 +183,7 @@ class RTPacketRepeater(Module):
|
||||||
i_status_wait_event, i_status_overflow, cb0_loaded | cb_loaded))
|
i_status_wait_event, i_status_overflow, cb0_loaded | cb_loaded))
|
||||||
|
|
||||||
load_read_reply = Signal()
|
load_read_reply = Signal()
|
||||||
self.sync.rtio += [
|
self.sync += [
|
||||||
If(load_read_reply,
|
If(load_read_reply,
|
||||||
i_status_wait_event.eq(0),
|
i_status_wait_event.eq(0),
|
||||||
i_status_overflow.eq(0),
|
i_status_overflow.eq(0),
|
||||||
|
@ -200,7 +200,7 @@ class RTPacketRepeater(Module):
|
||||||
]
|
]
|
||||||
|
|
||||||
# TX and CRI FSM
|
# TX and CRI FSM
|
||||||
tx_fsm = ClockDomainsRenamer("rtio")(FSM(reset_state="IDLE"))
|
tx_fsm = FSM(reset_state="IDLE")
|
||||||
self.submodules += tx_fsm
|
self.submodules += tx_fsm
|
||||||
|
|
||||||
tx_fsm.act("IDLE",
|
tx_fsm.act("IDLE",
|
||||||
|
|
|
@ -17,7 +17,7 @@ class GenericRXSynchronizer(Module):
|
||||||
return synchronized
|
return synchronized
|
||||||
|
|
||||||
def do_finalize(self):
|
def do_finalize(self):
|
||||||
eb = ElasticBuffer(sum(len(s[0]) for s in self.signals), 4, "rtio_rx", "rtio")
|
eb = ElasticBuffer(sum(len(s[0]) for s in self.signals), 4, "rtio_rx", "sys")
|
||||||
self.submodules += eb
|
self.submodules += eb
|
||||||
self.comb += [
|
self.comb += [
|
||||||
eb.din.eq(Cat(*[s[0] for s in self.signals])),
|
eb.din.eq(Cat(*[s[0] for s in self.signals])),
|
||||||
|
@ -57,6 +57,6 @@ class XilinxRXSynchronizer(Module):
|
||||||
self.specials += [
|
self.specials += [
|
||||||
Instance("FD", i_C=ClockSignal("rtio_rx"), i_D=din[i], o_Q=inter[i],
|
Instance("FD", i_C=ClockSignal("rtio_rx"), i_D=din[i], o_Q=inter[i],
|
||||||
attr={hu_set, ("RLOC", "X0Y{}".format(i))}),
|
attr={hu_set, ("RLOC", "X0Y{}".format(i))}),
|
||||||
Instance("FD", i_C=ClockSignal("rtio"), i_D=inter[i], o_Q=dout[i],
|
Instance("FD", i_C=ClockSignal("sys"), i_D=inter[i], o_Q=dout[i],
|
||||||
attr={hu_set, ("RLOC", "X1Y{}".format(i))})
|
attr={hu_set, ("RLOC", "X1Y{}".format(i))})
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,23 +1,23 @@
|
||||||
from migen import *
|
from migen import *
|
||||||
from migen.genlib.cdc import MultiReg, PulseSynchronizer
|
from migen.genlib.cdc import MultiReg
|
||||||
|
|
||||||
from misoc.interconnect.csr import *
|
from misoc.interconnect.csr import *
|
||||||
|
|
||||||
|
|
||||||
# This code assumes 125/62.5MHz reference clock and 100MHz, 125MHz or 150MHz RTIO
|
# This code assumes 125/62.5MHz reference clock and 100MHz or 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 (100e6, 125e6, 150e6)
|
assert rtio_clk_freq in (100e6, 125e6)
|
||||||
|
|
||||||
# 125MHz/62.5MHz reference clock to 100MHz/125MHz/150MHz. VCO @ 750MHz.
|
# 125MHz/62.5MHz reference clock to 100MHz/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.
|
||||||
|
@ -97,17 +97,14 @@ class SiPhaser7Series(Module, AutoCSR):
|
||||||
toggle_out = rx_synchronizer.resync(toggle_in)
|
toggle_out = rx_synchronizer.resync(toggle_in)
|
||||||
|
|
||||||
toggle_out_expected = Signal()
|
toggle_out_expected = Signal()
|
||||||
self.sync.rtio += toggle_out_expected.eq(~toggle_out)
|
self.sync += toggle_out_expected.eq(~toggle_out)
|
||||||
|
|
||||||
error = Signal()
|
error = Signal()
|
||||||
error_clear = PulseSynchronizer("sys", "rtio")
|
self.sync += [
|
||||||
self.submodules += error_clear
|
|
||||||
self.sync.rtio += [
|
|
||||||
If(toggle_out != toggle_out_expected, error.eq(1)),
|
If(toggle_out != toggle_out_expected, error.eq(1)),
|
||||||
If(error_clear.o, error.eq(0))
|
If(self.error.re, error.eq(0))
|
||||||
]
|
]
|
||||||
self.specials += MultiReg(error, self.error.w)
|
self.specials += MultiReg(error, self.error.w)
|
||||||
self.comb += error_clear.i.eq(self.error.re)
|
|
||||||
|
|
||||||
# expose MMCM outputs - used for clock constraints
|
# expose MMCM outputs - used for clock constraints
|
||||||
self.mmcm_freerun_output = mmcm_freerun_output
|
self.mmcm_freerun_output = mmcm_freerun_output
|
||||||
|
|
|
@ -33,7 +33,7 @@ class BruteforceClockAligner(Module):
|
||||||
check_counter = Signal(max=check_max_val+1)
|
check_counter = Signal(max=check_max_val+1)
|
||||||
check = Signal()
|
check = Signal()
|
||||||
reset_check_counter = Signal()
|
reset_check_counter = Signal()
|
||||||
self.sync.rtio_tx += [
|
self.sync += [
|
||||||
check.eq(0),
|
check.eq(0),
|
||||||
If(reset_check_counter,
|
If(reset_check_counter,
|
||||||
check_counter.eq(check_max_val)
|
check_counter.eq(check_max_val)
|
||||||
|
@ -47,7 +47,7 @@ class BruteforceClockAligner(Module):
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
|
||||||
checks_reset = PulseSynchronizer("rtio_tx", "rtio_rx")
|
checks_reset = PulseSynchronizer("sys", "rtio_rx")
|
||||||
self.submodules += checks_reset
|
self.submodules += checks_reset
|
||||||
|
|
||||||
comma_n = ~comma & 0b1111111111
|
comma_n = ~comma & 0b1111111111
|
||||||
|
@ -76,7 +76,7 @@ class BruteforceClockAligner(Module):
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
|
||||||
fsm = ClockDomainsRenamer("rtio_tx")(FSM(reset_state="WAIT_COMMA"))
|
fsm = FSM(reset_state="WAIT_COMMA")
|
||||||
self.submodules += fsm
|
self.submodules += fsm
|
||||||
|
|
||||||
fsm.act("WAIT_COMMA",
|
fsm.act("WAIT_COMMA",
|
||||||
|
|
|
@ -20,8 +20,7 @@ class GTPSingle(Module):
|
||||||
|
|
||||||
self.stable_clkin = Signal()
|
self.stable_clkin = Signal()
|
||||||
self.txenable = Signal()
|
self.txenable = Signal()
|
||||||
self.submodules.encoder = encoder = ClockDomainsRenamer("rtio_tx")(
|
self.submodules.encoder = encoder = Encoder(2, True)
|
||||||
Encoder(2, True))
|
|
||||||
self.submodules.decoders = decoders = [ClockDomainsRenamer("rtio_rx")(
|
self.submodules.decoders = decoders = [ClockDomainsRenamer("rtio_rx")(
|
||||||
(Decoder(True))) for _ in range(2)]
|
(Decoder(True))) for _ in range(2)]
|
||||||
self.rx_ready = Signal()
|
self.rx_ready = Signal()
|
||||||
|
@ -33,10 +32,11 @@ class GTPSingle(Module):
|
||||||
|
|
||||||
# # #
|
# # #
|
||||||
|
|
||||||
# TX generates RTIO clock, init must be in system domain
|
# TX generates RTIO clock, init must be in bootstrap domain
|
||||||
self.submodules.tx_init = tx_init = GTPTXInit(sys_clk_freq, mode)
|
self.submodules.tx_init = tx_init = ClockDomainsRenamer("bootstrap")(
|
||||||
# RX receives restart commands from RTIO domain
|
GTPTXInit(125e6, mode))
|
||||||
rx_init = ClockDomainsRenamer("rtio_tx")(GTPRXInit(rtio_clk_freq))
|
# RX receives restart commands from SYS domain
|
||||||
|
rx_init = GTPRXInit(rtio_clk_freq)
|
||||||
self.submodules += rx_init
|
self.submodules += rx_init
|
||||||
|
|
||||||
self.comb += [
|
self.comb += [
|
||||||
|
@ -367,7 +367,7 @@ class GTPSingle(Module):
|
||||||
|
|
||||||
# Channel - DRP Ports
|
# Channel - DRP Ports
|
||||||
i_DRPADDR=rx_init.drpaddr,
|
i_DRPADDR=rx_init.drpaddr,
|
||||||
i_DRPCLK=ClockSignal("rtio_tx"),
|
i_DRPCLK=ClockSignal("sys"),
|
||||||
i_DRPDI=rx_init.drpdi,
|
i_DRPDI=rx_init.drpdi,
|
||||||
o_DRPDO=rx_init.drpdo,
|
o_DRPDO=rx_init.drpdo,
|
||||||
i_DRPEN=rx_init.drpen,
|
i_DRPEN=rx_init.drpen,
|
||||||
|
@ -566,8 +566,8 @@ class GTPSingle(Module):
|
||||||
i_PMARSVDIN1 =0b0,
|
i_PMARSVDIN1 =0b0,
|
||||||
# Transmit Ports - FPGA TX Interface Ports
|
# Transmit Ports - FPGA TX Interface Ports
|
||||||
i_TXDATA =Cat(txdata[:8], txdata[10:18]),
|
i_TXDATA =Cat(txdata[:8], txdata[10:18]),
|
||||||
i_TXUSRCLK =ClockSignal("rtio_tx"),
|
i_TXUSRCLK =ClockSignal("sys"),
|
||||||
i_TXUSRCLK2 =ClockSignal("rtio_tx"),
|
i_TXUSRCLK2 =ClockSignal("sys"),
|
||||||
|
|
||||||
# Transmit Ports - PCI Express Ports
|
# Transmit Ports - PCI Express Ports
|
||||||
i_TXELECIDLE =0,
|
i_TXELECIDLE =0,
|
||||||
|
@ -665,19 +665,10 @@ class GTPSingle(Module):
|
||||||
raise ValueError
|
raise ValueError
|
||||||
self.specials += Instance("GTPE2_CHANNEL", **gtp_params)
|
self.specials += Instance("GTPE2_CHANNEL", **gtp_params)
|
||||||
|
|
||||||
# tx clocking
|
|
||||||
tx_reset_deglitched = Signal()
|
|
||||||
tx_reset_deglitched.attr.add("no_retiming")
|
|
||||||
self.sync += tx_reset_deglitched.eq(~tx_init.done)
|
|
||||||
self.clock_domains.cd_rtio_tx = ClockDomain()
|
|
||||||
if mode == "master" or mode == "single":
|
|
||||||
self.specials += Instance("BUFG", i_I=self.txoutclk, o_O=self.cd_rtio_tx.clk)
|
|
||||||
self.specials += AsyncResetSynchronizer(self.cd_rtio_tx, tx_reset_deglitched)
|
|
||||||
|
|
||||||
# rx clocking
|
# rx clocking
|
||||||
rx_reset_deglitched = Signal()
|
rx_reset_deglitched = Signal()
|
||||||
rx_reset_deglitched.attr.add("no_retiming")
|
rx_reset_deglitched.attr.add("no_retiming")
|
||||||
self.sync.rtio_tx += rx_reset_deglitched.eq(~rx_init.done)
|
self.sync += rx_reset_deglitched.eq(~rx_init.done)
|
||||||
self.clock_domains.cd_rtio_rx = ClockDomain()
|
self.clock_domains.cd_rtio_rx = ClockDomain()
|
||||||
self.specials += [
|
self.specials += [
|
||||||
Instance("BUFG", i_I=self.rxoutclk, o_O=self.cd_rtio_rx.clk),
|
Instance("BUFG", i_I=self.rxoutclk, o_O=self.cd_rtio_rx.clk),
|
||||||
|
@ -727,7 +718,6 @@ class GTP(Module, TransceiverInterface):
|
||||||
|
|
||||||
# # #
|
# # #
|
||||||
|
|
||||||
rtio_tx_clk = Signal()
|
|
||||||
channel_interfaces = []
|
channel_interfaces = []
|
||||||
for i in range(nchannels):
|
for i in range(nchannels):
|
||||||
if nchannels == 1:
|
if nchannels == 1:
|
||||||
|
@ -735,10 +725,6 @@ class GTP(Module, TransceiverInterface):
|
||||||
else:
|
else:
|
||||||
mode = "master" if i == master else "slave"
|
mode = "master" if i == master else "slave"
|
||||||
gtp = GTPSingle(qpll_channel, data_pads[i], sys_clk_freq, rtio_clk_freq, mode)
|
gtp = GTPSingle(qpll_channel, data_pads[i], sys_clk_freq, rtio_clk_freq, mode)
|
||||||
if mode == "slave":
|
|
||||||
self.comb += gtp.cd_rtio_tx.clk.eq(rtio_tx_clk)
|
|
||||||
else:
|
|
||||||
self.comb += rtio_tx_clk.eq(gtp.cd_rtio_tx.clk)
|
|
||||||
self.gtps.append(gtp)
|
self.gtps.append(gtp)
|
||||||
setattr(self.submodules, "gtp"+str(i), gtp)
|
setattr(self.submodules, "gtp"+str(i), gtp)
|
||||||
channel_interface = ChannelInterface(gtp.encoder, gtp.decoders)
|
channel_interface = ChannelInterface(gtp.encoder, gtp.decoders)
|
||||||
|
@ -754,10 +740,6 @@ class GTP(Module, TransceiverInterface):
|
||||||
gtp.txenable.eq(self.txenable.storage[n])
|
gtp.txenable.eq(self.txenable.storage[n])
|
||||||
]
|
]
|
||||||
|
|
||||||
self.comb += [
|
|
||||||
self.cd_rtio.clk.eq(self.gtps[master].cd_rtio_tx.clk),
|
|
||||||
self.cd_rtio.rst.eq(reduce(or_, [gtp.cd_rtio_tx.rst for gtp in self.gtps]))
|
|
||||||
]
|
|
||||||
for i in range(nchannels):
|
for i in range(nchannels):
|
||||||
self.comb += [
|
self.comb += [
|
||||||
getattr(self, "cd_rtio_rx" + str(i)).clk.eq(self.gtps[i].cd_rtio_rx.clk),
|
getattr(self, "cd_rtio_rx" + str(i)).clk.eq(self.gtps[i].cd_rtio_rx.clk),
|
||||||
|
|
|
@ -9,7 +9,7 @@ from artiq.gateware.drtio.wrpll import thls, filters
|
||||||
|
|
||||||
|
|
||||||
class FrequencyCounter(Module, AutoCSR):
|
class FrequencyCounter(Module, AutoCSR):
|
||||||
def __init__(self, timer_width=23, counter_width=23, domains=["helper", "rtio", "rtio_rx0"]):
|
def __init__(self, timer_width=23, counter_width=23, domains=["helper", "sys", "rtio_rx0"]):
|
||||||
for domain in domains:
|
for domain in domains:
|
||||||
name = "counter_" + domain
|
name = "counter_" + domain
|
||||||
counter = CSRStatus(counter_width, name=name)
|
counter = CSRStatus(counter_width, name=name)
|
||||||
|
|
|
@ -105,7 +105,7 @@ class MiqroChannel(Module):
|
||||||
self.pulse.eq(pulse),
|
self.pulse.eq(pulse),
|
||||||
self.rtlink.o.busy.eq(stb & ~self.ack),
|
self.rtlink.o.busy.eq(stb & ~self.ack),
|
||||||
]
|
]
|
||||||
self.sync.rtio += [
|
self.sync += [
|
||||||
If(~stb,
|
If(~stb,
|
||||||
dt.eq(dt + 2),
|
dt.eq(dt + 2),
|
||||||
),
|
),
|
||||||
|
@ -162,7 +162,7 @@ class Miqro(Module):
|
||||||
]
|
]
|
||||||
|
|
||||||
re_dly = Signal(3) # stage, send, respond
|
re_dly = Signal(3) # stage, send, respond
|
||||||
self.sync.rtio += [
|
self.sync += [
|
||||||
header.type.eq(3), # body type is miqro pulse data
|
header.type.eq(3), # body type is miqro pulse data
|
||||||
If(self.serializer.stb,
|
If(self.serializer.stb,
|
||||||
header.we.eq(0),
|
header.we.eq(0),
|
||||||
|
|
|
@ -17,7 +17,7 @@ from misoc.integration.builder import builder_args, builder_argdict
|
||||||
from artiq.gateware.amp import AMPSoC
|
from artiq.gateware.amp import AMPSoC
|
||||||
from artiq.gateware import rtio
|
from artiq.gateware import rtio
|
||||||
from artiq.gateware.rtio.phy import ttl_simple, ttl_serdes_7series, edge_counter
|
from artiq.gateware.rtio.phy import ttl_simple, ttl_serdes_7series, edge_counter
|
||||||
from artiq.gateware.rtio.xilinx_clocking import RTIOClockMultiplier, fix_serdes_timing_path
|
from artiq.gateware.rtio.xilinx_clocking import fix_serdes_timing_path
|
||||||
from artiq.gateware import eem
|
from artiq.gateware import eem
|
||||||
from artiq.gateware.drtio.transceiver import gtp_7series
|
from artiq.gateware.drtio.transceiver import gtp_7series
|
||||||
from artiq.gateware.drtio.siphaser import SiPhaser7Series
|
from artiq.gateware.drtio.siphaser import SiPhaser7Series
|
||||||
|
@ -76,6 +76,23 @@ class StandaloneBase(MiniSoC, AMPSoC):
|
||||||
self.platform.request("error_led")))
|
self.platform.request("error_led")))
|
||||||
self.csr_devices.append("error_led")
|
self.csr_devices.append("error_led")
|
||||||
self.submodules += SMAClkinForward(self.platform)
|
self.submodules += SMAClkinForward(self.platform)
|
||||||
|
cdr_clk_out = self.platform.request("cdr_clk_clean")
|
||||||
|
else:
|
||||||
|
cdr_clk_out = self.platform.request("si5324_clkout")
|
||||||
|
|
||||||
|
cdr_clk = Signal()
|
||||||
|
cdr_clk_buf = Signal()
|
||||||
|
self.platform.add_period_constraint(cdr_clk_out, 8.)
|
||||||
|
|
||||||
|
self.specials += [
|
||||||
|
Instance("IBUFDS_GTE2",
|
||||||
|
i_CEB=0,
|
||||||
|
i_I=cdr_clk_out.p, i_IB=cdr_clk_out.n,
|
||||||
|
o_O=cdr_clk),
|
||||||
|
Instance("BUFG", i_I=cdr_clk, o_O=cdr_clk_buf)
|
||||||
|
]
|
||||||
|
|
||||||
|
self.crg.configure(cdr_clk_buf)
|
||||||
|
|
||||||
i2c = self.platform.request("i2c")
|
i2c = self.platform.request("i2c")
|
||||||
self.submodules.i2c = gpio.GPIOTristate([i2c.scl, i2c.sda])
|
self.submodules.i2c = gpio.GPIOTristate([i2c.scl, i2c.sda])
|
||||||
|
@ -218,6 +235,8 @@ class MasterBase(MiniSoC, AMPSoC):
|
||||||
integrated_sram_size=8192,
|
integrated_sram_size=8192,
|
||||||
ethmac_nrxslots=4,
|
ethmac_nrxslots=4,
|
||||||
ethmac_ntxslots=4,
|
ethmac_ntxslots=4,
|
||||||
|
clk_freq=rtio_clk_freq,
|
||||||
|
rtio_sys_merge=True,
|
||||||
**kwargs)
|
**kwargs)
|
||||||
AMPSoC.__init__(self)
|
AMPSoC.__init__(self)
|
||||||
add_identifier(self, gateware_identifier_str=gateware_identifier_str)
|
add_identifier(self, gateware_identifier_str=gateware_identifier_str)
|
||||||
|
@ -256,8 +275,6 @@ class MasterBase(MiniSoC, AMPSoC):
|
||||||
sys_clk_freq=self.clk_freq,
|
sys_clk_freq=self.clk_freq,
|
||||||
rtio_clk_freq=rtio_clk_freq)
|
rtio_clk_freq=rtio_clk_freq)
|
||||||
self.csr_devices.append("drtio_transceiver")
|
self.csr_devices.append("drtio_transceiver")
|
||||||
self.sync += self.disable_cdr_clk_ibuf.eq(
|
|
||||||
~self.drtio_transceiver.stable_clkin.storage)
|
|
||||||
|
|
||||||
if enable_sata:
|
if enable_sata:
|
||||||
sfp_channels = self.drtio_transceiver.channels[1:]
|
sfp_channels = self.drtio_transceiver.channels[1:]
|
||||||
|
@ -307,8 +324,14 @@ class MasterBase(MiniSoC, AMPSoC):
|
||||||
|
|
||||||
rtio_clk_period = 1e9/rtio_clk_freq
|
rtio_clk_period = 1e9/rtio_clk_freq
|
||||||
gtp = self.drtio_transceiver.gtps[0]
|
gtp = self.drtio_transceiver.gtps[0]
|
||||||
|
|
||||||
|
txout_buf = Signal()
|
||||||
|
self.specials += Instance("BUFG", i_I=gtp.txoutclk, o_O=txout_buf)
|
||||||
|
self.crg.configure(txout_buf, clk_sw=gtp.tx_init.done)
|
||||||
|
|
||||||
platform.add_period_constraint(gtp.txoutclk, rtio_clk_period)
|
platform.add_period_constraint(gtp.txoutclk, rtio_clk_period)
|
||||||
platform.add_period_constraint(gtp.rxoutclk, rtio_clk_period)
|
platform.add_period_constraint(gtp.rxoutclk, rtio_clk_period)
|
||||||
|
|
||||||
platform.add_false_path_constraints(
|
platform.add_false_path_constraints(
|
||||||
self.crg.cd_sys.clk,
|
self.crg.cd_sys.clk,
|
||||||
gtp.txoutclk, gtp.rxoutclk)
|
gtp.txoutclk, gtp.rxoutclk)
|
||||||
|
@ -317,8 +340,6 @@ class MasterBase(MiniSoC, AMPSoC):
|
||||||
platform.add_false_path_constraints(
|
platform.add_false_path_constraints(
|
||||||
self.crg.cd_sys.clk, gtp.rxoutclk)
|
self.crg.cd_sys.clk, gtp.rxoutclk)
|
||||||
|
|
||||||
self.submodules.rtio_crg = RTIOClockMultiplier(rtio_clk_freq)
|
|
||||||
self.csr_devices.append("rtio_crg")
|
|
||||||
fix_serdes_timing_path(platform)
|
fix_serdes_timing_path(platform)
|
||||||
|
|
||||||
def add_rtio(self, rtio_channels, sed_lanes=8):
|
def add_rtio(self, rtio_channels, sed_lanes=8):
|
||||||
|
@ -350,19 +371,18 @@ class MasterBase(MiniSoC, AMPSoC):
|
||||||
# Never running out of stupid features, GTs on A7 make you pack
|
# Never running out of stupid features, GTs on A7 make you pack
|
||||||
# unrelated transceiver PLLs into one GTPE2_COMMON yourself.
|
# unrelated transceiver PLLs into one GTPE2_COMMON yourself.
|
||||||
def create_qpll(self):
|
def create_qpll(self):
|
||||||
# The GTP acts up if you send any glitch to its
|
|
||||||
# clock input, even while the PLL is held in reset.
|
|
||||||
self.disable_cdr_clk_ibuf = Signal(reset=1)
|
|
||||||
self.disable_cdr_clk_ibuf.attr.add("no_retiming")
|
|
||||||
if self.platform.hw_rev == "v2.0":
|
if self.platform.hw_rev == "v2.0":
|
||||||
cdr_clk_clean = self.platform.request("cdr_clk_clean")
|
cdr_clk_out = self.platform.request("cdr_clk_clean")
|
||||||
else:
|
else:
|
||||||
cdr_clk_clean = self.platform.request("si5324_clkout")
|
cdr_clk_out = self.platform.request("si5324_clkout")
|
||||||
cdr_clk_clean_buf = Signal()
|
|
||||||
|
cdr_clk = Signal()
|
||||||
|
self.platform.add_period_constraint(cdr_clk_out, 8.)
|
||||||
|
|
||||||
self.specials += Instance("IBUFDS_GTE2",
|
self.specials += Instance("IBUFDS_GTE2",
|
||||||
i_CEB=self.disable_cdr_clk_ibuf,
|
i_CEB=0,
|
||||||
i_I=cdr_clk_clean.p, i_IB=cdr_clk_clean.n,
|
i_I=cdr_clk_out.p, i_IB=cdr_clk_out.n,
|
||||||
o_O=cdr_clk_clean_buf)
|
o_O=cdr_clk)
|
||||||
# Note precisely the rules Xilinx made up:
|
# Note precisely the rules Xilinx made up:
|
||||||
# refclksel=0b001 GTREFCLK0 selected
|
# refclksel=0b001 GTREFCLK0 selected
|
||||||
# refclksel=0b010 GTREFCLK1 selected
|
# refclksel=0b010 GTREFCLK1 selected
|
||||||
|
@ -377,7 +397,8 @@ class MasterBase(MiniSoC, AMPSoC):
|
||||||
fbdiv=4,
|
fbdiv=4,
|
||||||
fbdiv_45=5,
|
fbdiv_45=5,
|
||||||
refclk_div=1)
|
refclk_div=1)
|
||||||
qpll = QPLL(cdr_clk_clean_buf, qpll_drtio_settings,
|
|
||||||
|
qpll = QPLL(cdr_clk, qpll_drtio_settings,
|
||||||
self.crg.clk125_buf, qpll_eth_settings)
|
self.crg.clk125_buf, qpll_eth_settings)
|
||||||
self.submodules += qpll
|
self.submodules += qpll
|
||||||
self.drtio_qpll_channel, self.ethphy_qpll_channel = qpll.channels
|
self.drtio_qpll_channel, self.ethphy_qpll_channel = qpll.channels
|
||||||
|
@ -400,6 +421,8 @@ class SatelliteBase(BaseSoC):
|
||||||
cpu_bus_width=cpu_bus_width,
|
cpu_bus_width=cpu_bus_width,
|
||||||
sdram_controller_type="minicon",
|
sdram_controller_type="minicon",
|
||||||
l2_size=128*1024,
|
l2_size=128*1024,
|
||||||
|
clk_freq=rtio_clk_freq,
|
||||||
|
rtio_sys_merge=True,
|
||||||
**kwargs)
|
**kwargs)
|
||||||
add_identifier(self, gateware_identifier_str=gateware_identifier_str)
|
add_identifier(self, gateware_identifier_str=gateware_identifier_str)
|
||||||
|
|
||||||
|
@ -410,23 +433,24 @@ class SatelliteBase(BaseSoC):
|
||||||
self.platform.request("error_led")))
|
self.platform.request("error_led")))
|
||||||
self.csr_devices.append("error_led")
|
self.csr_devices.append("error_led")
|
||||||
|
|
||||||
disable_cdr_clk_ibuf = Signal(reset=1)
|
|
||||||
disable_cdr_clk_ibuf.attr.add("no_retiming")
|
|
||||||
if self.platform.hw_rev == "v2.0":
|
if self.platform.hw_rev == "v2.0":
|
||||||
cdr_clk_clean = self.platform.request("cdr_clk_clean")
|
cdr_clk_out = self.platform.request("cdr_clk_clean")
|
||||||
else:
|
else:
|
||||||
cdr_clk_clean = self.platform.request("si5324_clkout")
|
cdr_clk_out = self.platform.request("si5324_clkout")
|
||||||
cdr_clk_clean_buf = Signal()
|
|
||||||
|
cdr_clk = Signal()
|
||||||
|
self.platform.add_period_constraint(cdr_clk_out, 8.)
|
||||||
|
|
||||||
self.specials += Instance("IBUFDS_GTE2",
|
self.specials += Instance("IBUFDS_GTE2",
|
||||||
i_CEB=disable_cdr_clk_ibuf,
|
i_CEB=0,
|
||||||
i_I=cdr_clk_clean.p, i_IB=cdr_clk_clean.n,
|
i_I=cdr_clk_out.p, i_IB=cdr_clk_out.n,
|
||||||
o_O=cdr_clk_clean_buf)
|
o_O=cdr_clk)
|
||||||
qpll_drtio_settings = QPLLSettings(
|
qpll_drtio_settings = QPLLSettings(
|
||||||
refclksel=0b001,
|
refclksel=0b001,
|
||||||
fbdiv=4,
|
fbdiv=4,
|
||||||
fbdiv_45=5,
|
fbdiv_45=5,
|
||||||
refclk_div=1)
|
refclk_div=1)
|
||||||
qpll = QPLL(cdr_clk_clean_buf, qpll_drtio_settings)
|
qpll = QPLL(cdr_clk, qpll_drtio_settings)
|
||||||
self.submodules += qpll
|
self.submodules += qpll
|
||||||
|
|
||||||
drtio_data_pads = []
|
drtio_data_pads = []
|
||||||
|
@ -445,8 +469,6 @@ class SatelliteBase(BaseSoC):
|
||||||
sys_clk_freq=self.clk_freq,
|
sys_clk_freq=self.clk_freq,
|
||||||
rtio_clk_freq=rtio_clk_freq)
|
rtio_clk_freq=rtio_clk_freq)
|
||||||
self.csr_devices.append("drtio_transceiver")
|
self.csr_devices.append("drtio_transceiver")
|
||||||
self.sync += disable_cdr_clk_ibuf.eq(
|
|
||||||
~self.drtio_transceiver.stable_clkin.storage)
|
|
||||||
|
|
||||||
if enable_sata:
|
if enable_sata:
|
||||||
sfp_channels = self.drtio_transceiver.channels[1:]
|
sfp_channels = self.drtio_transceiver.channels[1:]
|
||||||
|
@ -542,6 +564,10 @@ class SatelliteBase(BaseSoC):
|
||||||
self.config["SI5324_SOFT_RESET"] = None
|
self.config["SI5324_SOFT_RESET"] = None
|
||||||
|
|
||||||
gtp = self.drtio_transceiver.gtps[0]
|
gtp = self.drtio_transceiver.gtps[0]
|
||||||
|
txout_buf = Signal()
|
||||||
|
self.specials += Instance("BUFG", i_I=gtp.txoutclk, o_O=txout_buf)
|
||||||
|
self.crg.configure(txout_buf, clk_sw=gtp.tx_init.done)
|
||||||
|
|
||||||
platform.add_period_constraint(gtp.txoutclk, rtio_clk_period)
|
platform.add_period_constraint(gtp.txoutclk, rtio_clk_period)
|
||||||
platform.add_period_constraint(gtp.rxoutclk, rtio_clk_period)
|
platform.add_period_constraint(gtp.rxoutclk, rtio_clk_period)
|
||||||
platform.add_false_path_constraints(
|
platform.add_false_path_constraints(
|
||||||
|
@ -555,8 +581,6 @@ class SatelliteBase(BaseSoC):
|
||||||
platform.add_false_path_constraints(
|
platform.add_false_path_constraints(
|
||||||
self.crg.cd_sys.clk, gtp.rxoutclk)
|
self.crg.cd_sys.clk, gtp.rxoutclk)
|
||||||
|
|
||||||
self.submodules.rtio_crg = RTIOClockMultiplier(rtio_clk_freq)
|
|
||||||
self.csr_devices.append("rtio_crg")
|
|
||||||
fix_serdes_timing_path(platform)
|
fix_serdes_timing_path(platform)
|
||||||
|
|
||||||
def add_rtio(self, rtio_channels, sed_lanes=8):
|
def add_rtio(self, rtio_channels, sed_lanes=8):
|
||||||
|
|
|
@ -36,7 +36,7 @@ class TB(Module):
|
||||||
def __init__(self, nwords, dw):
|
def __init__(self, nwords, dw):
|
||||||
self.submodules.link_layer = Loopback(nwords)
|
self.submodules.link_layer = Loopback(nwords)
|
||||||
self.submodules.aux_controller = ClockDomainsRenamer(
|
self.submodules.aux_controller = ClockDomainsRenamer(
|
||||||
{"rtio": "sys", "rtio_rx": "sys"})(DRTIOAuxController(self.link_layer, dw))
|
{"rtio_rx": "sys"})(DRTIOAuxController(self.link_layer, dw))
|
||||||
|
|
||||||
|
|
||||||
class TestAuxController(unittest.TestCase):
|
class TestAuxController(unittest.TestCase):
|
||||||
|
|
|
@ -144,7 +144,7 @@ class OutputsTestbench:
|
||||||
|
|
||||||
|
|
||||||
class TestFullStack(unittest.TestCase):
|
class TestFullStack(unittest.TestCase):
|
||||||
clocks = {"sys": 8, "rtio": 5, "rtio_rx": 5,
|
clocks = {"sys": 8, "rtio_rx": 5,
|
||||||
"rio": 5, "rio_phy": 5}
|
"rio": 5, "rio_phy": 5}
|
||||||
|
|
||||||
def test_pulses(self):
|
def test_pulses(self):
|
||||||
|
@ -169,7 +169,7 @@ class TestFullStack(unittest.TestCase):
|
||||||
yield from tb.sync()
|
yield from tb.sync()
|
||||||
|
|
||||||
run_simulation(tb.dut,
|
run_simulation(tb.dut,
|
||||||
{"sys": test(), "rtio": tb.check_ttls(ttl_changes)}, self.clocks)
|
{"sys": test()}, self.clocks)
|
||||||
self.assertEqual(ttl_changes, correct_ttl_changes)
|
self.assertEqual(ttl_changes, correct_ttl_changes)
|
||||||
|
|
||||||
def test_underflow(self):
|
def test_underflow(self):
|
||||||
|
@ -214,7 +214,7 @@ class TestFullStack(unittest.TestCase):
|
||||||
yield from tb.sync()
|
yield from tb.sync()
|
||||||
|
|
||||||
run_simulation(tb.dut,
|
run_simulation(tb.dut,
|
||||||
{"sys": test(), "rtio": tb.check_ttls(ttl_changes)}, self.clocks)
|
{"sys": test()}, self.clocks)
|
||||||
self.assertEqual(ttl_changes, correct_ttl_changes)
|
self.assertEqual(ttl_changes, correct_ttl_changes)
|
||||||
|
|
||||||
def test_write_underflow(self):
|
def test_write_underflow(self):
|
||||||
|
@ -284,7 +284,7 @@ class TestFullStack(unittest.TestCase):
|
||||||
yield dut.phy2.rtlink.i.stb.eq(0)
|
yield dut.phy2.rtlink.i.stb.eq(0)
|
||||||
|
|
||||||
run_simulation(dut,
|
run_simulation(dut,
|
||||||
{"sys": test(), "rtio": generate_input()}, self.clocks)
|
{"sys": test()}, self.clocks)
|
||||||
|
|
||||||
def test_echo(self):
|
def test_echo(self):
|
||||||
dut = DUT(2)
|
dut = DUT(2)
|
||||||
|
|
|
@ -12,7 +12,7 @@ def create_dut(nwords):
|
||||||
pt = PacketInterface("s2m", nwords*8)
|
pt = PacketInterface("s2m", nwords*8)
|
||||||
pr = PacketInterface("m2s", nwords*8)
|
pr = PacketInterface("m2s", nwords*8)
|
||||||
ts = Signal(64)
|
ts = Signal(64)
|
||||||
dut = ClockDomainsRenamer({"rtio": "sys", "rtio_rx": "sys"})(
|
dut = ClockDomainsRenamer({"rtio_rx": "sys"})(
|
||||||
RTPacketRepeater(
|
RTPacketRepeater(
|
||||||
SimpleNamespace(coarse_ts=ts),
|
SimpleNamespace(coarse_ts=ts),
|
||||||
SimpleNamespace(
|
SimpleNamespace(
|
||||||
|
|
|
@ -130,7 +130,7 @@ class Testbench:
|
||||||
|
|
||||||
|
|
||||||
class TestSwitching(unittest.TestCase):
|
class TestSwitching(unittest.TestCase):
|
||||||
clocks = {"sys": 8, "rtio": 5, "rtio_rx": 5,
|
clocks = {"sys": 8, "rtio_rx": 5,
|
||||||
"rio": 5, "rio_phy": 5}
|
"rio": 5, "rio_phy": 5}
|
||||||
|
|
||||||
def test_outputs(self):
|
def test_outputs(self):
|
||||||
|
@ -183,7 +183,7 @@ class TestSwitching(unittest.TestCase):
|
||||||
current_request = (packet_type, field_dict, trailer)
|
current_request = (packet_type, field_dict, trailer)
|
||||||
|
|
||||||
run_simulation(tb.dut,
|
run_simulation(tb.dut,
|
||||||
{"sys": test(), "rtio": tb.dut.pr.receive(receive), "rtio_rx": send_replies()}, self.clocks)
|
{"sys": test(), "sys": tb.dut.pr.receive(receive), "rtio_rx": send_replies()}, self.clocks)
|
||||||
|
|
||||||
|
|
||||||
def test_inputs(self):
|
def test_inputs(self):
|
||||||
|
@ -244,4 +244,4 @@ class TestSwitching(unittest.TestCase):
|
||||||
current_request = (packet_type, field_dict, trailer)
|
current_request = (packet_type, field_dict, trailer)
|
||||||
|
|
||||||
run_simulation(tb.dut,
|
run_simulation(tb.dut,
|
||||||
{"sys": test(), "rtio": tb.dut.pr.receive(receive), "rtio_rx": send_replies()}, self.clocks)
|
{"sys": test(), "sys": tb.dut.pr.receive(receive), "rtio_rx": send_replies()}, self.clocks)
|
||||||
|
|
Loading…
Reference in New Issue