forked from M-Labs/artiq
DRTIO: RTIO/SYS clock merge
This commit is contained in:
parent
ad000609ce
commit
17efc28dbe
|
@ -1,10 +1,7 @@
|
|||
use board_misoc::config;
|
||||
#[cfg(si5324_as_synthesizer)]
|
||||
use board_artiq::si5324;
|
||||
#[cfg(any(soc_platform = "kasli", has_drtio))]
|
||||
use board_misoc::csr;
|
||||
#[cfg(has_drtio)]
|
||||
use board_misoc::clock;
|
||||
use board_misoc::{csr, clock};
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
#[allow(non_camel_case_types)]
|
||||
|
@ -212,15 +209,12 @@ fn setup_si5324_as_synthesizer(cfg: RtioClock) {
|
|||
|
||||
#[cfg(si5324_as_synthesizer)]
|
||||
fn setup_si5324(clock_cfg: RtioClock) {
|
||||
#[cfg(soc_platform = "kasli")]
|
||||
{
|
||||
let switched = unsafe {
|
||||
csr::crg::switch_done_read()
|
||||
};
|
||||
if switched == 1 {
|
||||
info!("Clocking has already been set up.");
|
||||
return;
|
||||
}
|
||||
let switched = unsafe {
|
||||
csr::crg::switch_done_read()
|
||||
};
|
||||
if switched == 1 {
|
||||
info!("Clocking has already been set up.");
|
||||
return;
|
||||
}
|
||||
#[cfg(all(soc_platform = "kasli", hw_rev = "v2.0"))]
|
||||
let si5324_ext_input = si5324::Input::Ckin1;
|
||||
|
@ -239,12 +233,14 @@ fn setup_si5324(clock_cfg: RtioClock) {
|
|||
}
|
||||
|
||||
// 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 {
|
||||
csr::crg::clock_sel_write(1);
|
||||
loop {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -257,15 +253,28 @@ pub fn init() {
|
|||
|
||||
#[cfg(has_drtio)]
|
||||
{
|
||||
unsafe {
|
||||
csr::drtio_transceiver::stable_clkin_write(1);
|
||||
let switched = unsafe {
|
||||
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
|
||||
unsafe {
|
||||
csr::drtio_transceiver::txenable_write(0xffffffffu32 as _);
|
||||
else {
|
||||
// enable TX after the reboot, with stable clock
|
||||
unsafe {
|
||||
csr::drtio_transceiver::txenable_write(0xffffffffu32 as _);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[cfg(has_rtio_crg)]
|
||||
{
|
||||
#[cfg(has_rtio_clock_switch)]
|
||||
|
|
|
@ -465,6 +465,30 @@ const SI5324_SETTINGS: si5324::FrequencySettings
|
|||
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]
|
||||
pub extern fn main() -> i32 {
|
||||
extern {
|
||||
|
@ -517,21 +541,15 @@ pub extern fn main() -> i32 {
|
|||
io_expander1.service().unwrap();
|
||||
}
|
||||
|
||||
#[cfg(has_si5324)]
|
||||
si5324::setup(&SI5324_SETTINGS, si5324::Input::Ckin1).expect("cannot initialize Si5324");
|
||||
#[cfg(has_wrpll)]
|
||||
wrpll::init();
|
||||
sysclk_setup();
|
||||
|
||||
unsafe {
|
||||
csr::drtio_transceiver::stable_clkin_write(1);
|
||||
}
|
||||
clock::spin_us(1500); // wait for CPLL/QPLL lock
|
||||
#[cfg(not(has_jdcg))]
|
||||
unsafe {
|
||||
csr::drtio_transceiver::txenable_write(0xffffffffu32 as _);
|
||||
}
|
||||
#[cfg(has_wrpll)]
|
||||
wrpll::diagnostics();
|
||||
|
||||
init_rtio_crg();
|
||||
|
||||
#[cfg(has_hmc830_7043)]
|
||||
|
|
|
@ -22,8 +22,7 @@ class Transmitter(Module, AutoCSR):
|
|||
self.aux_tx = CSR()
|
||||
self.specials.mem = Memory(mem_dw, max_packet//(mem_dw//8))
|
||||
|
||||
converter = ClockDomainsRenamer("rtio")(
|
||||
stream.Converter(mem_dw, ll_dw))
|
||||
converter = stream.Converter(mem_dw, ll_dw)
|
||||
self.submodules += converter
|
||||
|
||||
# when continuously fed, the Converter outputs data continuously
|
||||
|
@ -36,7 +35,7 @@ class Transmitter(Module, AutoCSR):
|
|||
seen_eop_rst = Signal()
|
||||
frame_r = Signal()
|
||||
seen_eop = Signal()
|
||||
self.sync.rtio += [
|
||||
self.sync += [
|
||||
If(link_layer.tx_aux_ack,
|
||||
frame_r.eq(link_layer.tx_aux_frame),
|
||||
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))
|
||||
]
|
||||
|
||||
mem_port = self.mem.get_port(clock_domain="rtio")
|
||||
mem_port = self.mem.get_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 = 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),
|
||||
converter.sink.data.eq(mem_port.dat_r)
|
||||
]
|
||||
self.sync.rtio += frame_counter.eq(frame_counter_next)
|
||||
|
||||
start_tx = PulseSynchronizer("sys", "rtio")
|
||||
tx_done = PulseSynchronizer("rtio", "sys")
|
||||
self.submodules += start_tx, tx_done
|
||||
self.comb += start_tx.i.eq(self.aux_tx.re)
|
||||
tx_done = Signal()
|
||||
self.sync += [
|
||||
If(tx_done.o, self.aux_tx.w.eq(0)),
|
||||
If(self.aux_tx.re, self.aux_tx.w.eq(1))
|
||||
frame_counter.eq(frame_counter_next),
|
||||
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
|
||||
|
||||
fsm.act("IDLE",
|
||||
frame_counter_rst.eq(1),
|
||||
seen_eop_rst.eq(1),
|
||||
If(start_tx.o, NextState("TRANSMIT"))
|
||||
If(self.aux_tx.re, NextState("TRANSMIT"))
|
||||
)
|
||||
fsm.act("TRANSMIT",
|
||||
converter.sink.stb.eq(1),
|
||||
If(converter.sink.ack,
|
||||
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",
|
||||
If(seen_eop,
|
||||
tx_done.i.eq(1),
|
||||
tx_done.eq(1),
|
||||
NextState("IDLE")
|
||||
)
|
||||
)
|
||||
|
|
|
@ -2,7 +2,6 @@ from types import SimpleNamespace
|
|||
|
||||
from migen import *
|
||||
from migen.genlib.resetsync import AsyncResetSynchronizer
|
||||
from migen.genlib.cdc import PulseSynchronizer
|
||||
from misoc.interconnect.csr import *
|
||||
|
||||
from artiq.gateware.rtio import cri, rtlink
|
||||
|
@ -31,7 +30,6 @@ class TransceiverInterface(AutoCSR):
|
|||
def __init__(self, channel_interfaces):
|
||||
self.stable_clkin = CSRStorage()
|
||||
self.txenable = CSRStorage(len(channel_interfaces))
|
||||
self.clock_domains.cd_rtio = ClockDomain()
|
||||
for i in range(len(channel_interfaces)):
|
||||
name = "rtio_rx" + str(i)
|
||||
setattr(self.clock_domains, "cd_"+name, ClockDomain(name=name))
|
||||
|
@ -65,7 +63,7 @@ class SyncRTIO(Module):
|
|||
enable_spread=False, report_buffer_space=True,
|
||||
interface=self.cri))
|
||||
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")(
|
||||
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_phy = ClockDomain()
|
||||
self.comb += [
|
||||
self.cd_rio.clk.eq(ClockSignal("rtio")),
|
||||
self.cd_rio_phy.clk.eq(ClockSignal("rtio"))
|
||||
self.cd_rio.clk.eq(ClockSignal("sys")),
|
||||
self.cd_rio_phy.clk.eq(ClockSignal("sys"))
|
||||
]
|
||||
reset = 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_data=rx_synchronizer.resync(self.link_layer.rx_rt_data)
|
||||
)
|
||||
self.submodules.link_stats = link_layer.LinkLayerStats(link_layer_sync, "rtio")
|
||||
self.submodules.rt_packet = ClockDomainsRenamer("rtio")(
|
||||
rt_packet_satellite.RTPacketSatellite(link_layer_sync, interface=self.cri))
|
||||
self.submodules.link_stats = link_layer.LinkLayerStats(link_layer_sync, "sys")
|
||||
self.submodules.rt_packet = rt_packet_satellite.RTPacketSatellite(
|
||||
link_layer_sync, interface=self.cri)
|
||||
self.comb += self.rt_packet.reset.eq(self.cd_rio.rst)
|
||||
|
||||
self.comb += [
|
||||
|
@ -135,12 +133,9 @@ class DRTIOSatellite(Module):
|
|||
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 += [
|
||||
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(
|
||||
|
|
|
@ -232,7 +232,7 @@ class LinkLayer(Module, AutoCSR):
|
|||
# receiver locked, comma aligned, receiving valid 8b10b symbols
|
||||
self.rx_ready = Signal()
|
||||
|
||||
tx = ClockDomainsRenamer("rtio")(LinkLayerTX(encoder))
|
||||
tx = LinkLayerTX(encoder)
|
||||
rx = ClockDomainsRenamer("rtio_rx")(LinkLayerRX(decoders))
|
||||
self.submodules += tx, rx
|
||||
|
||||
|
@ -256,31 +256,23 @@ class LinkLayer(Module, AutoCSR):
|
|||
|
||||
rx_up = 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_r.attr.add("no_retiming")
|
||||
self.specials += [
|
||||
MultiReg(rx_up_r, rx_up_rx, "rtio_rx"),
|
||||
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()
|
||||
self.rx_disable.storage.attr.add("no_retiming")
|
||||
self.specials += MultiReg(self.rx_disable.storage, rx_disable_rx, "rtio_rx")
|
||||
|
||||
self.comb += [
|
||||
tx.aux_frame.eq(self.tx_aux_frame | tx_force_aux_zero_rtio),
|
||||
tx.aux_data.eq(Mux(tx_force_aux_zero_rtio, 0, self.tx_aux_data)),
|
||||
tx.aux_frame.eq(self.tx_aux_frame | self.tx_force_aux_zero.storage),
|
||||
tx.aux_data.eq(Mux(self.tx_force_aux_zero.storage, 0, self.tx_aux_data)),
|
||||
self.tx_aux_ack.eq(tx.aux_ack),
|
||||
tx.rt_frame.eq(self.tx_rt_frame | tx_force_rt_zero_rtio),
|
||||
tx.rt_data.eq(Mux(tx_force_rt_zero_rtio, 0, self.tx_rt_data))
|
||||
tx.rt_frame.eq(self.tx_rt_frame | self.tx_force_rt_zero.storage),
|
||||
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
|
||||
# to be recaptured by RXSynchronizer.
|
||||
|
@ -294,10 +286,10 @@ class LinkLayer(Module, AutoCSR):
|
|||
self.rx_rt_data.eq(rx.rt_data)
|
||||
]
|
||||
|
||||
wait_scrambler = ClockDomainsRenamer("rtio")(WaitTimer(15))
|
||||
wait_scrambler = WaitTimer(15)
|
||||
self.submodules += wait_scrambler
|
||||
|
||||
fsm = ClockDomainsRenamer("rtio")(FSM(reset_state="WAIT_RX_READY"))
|
||||
fsm = FSM(reset_state="WAIT_RX_READY")
|
||||
self.submodules += fsm
|
||||
|
||||
fsm.act("WAIT_RX_READY",
|
||||
|
|
|
@ -108,7 +108,7 @@ class RTController(Module):
|
|||
|
||||
cond_underflow = Signal()
|
||||
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 = Memory(16, 256)
|
||||
|
|
|
@ -15,15 +15,11 @@ class RTController(Module, AutoCSR):
|
|||
self.command_missed_chan_sel = CSRStatus(24)
|
||||
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_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 += [
|
||||
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))
|
||||
]
|
||||
self.comb += self.set_time.w.eq(set_time_stb)
|
||||
|
@ -31,10 +27,10 @@ class RTController(Module, AutoCSR):
|
|||
errors = [
|
||||
(rt_packet.err_unknown_packet_type, "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(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)
|
||||
]
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
from migen 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 artiq.gateware.rtio.cdc import GrayCodeTransfer
|
||||
|
@ -76,8 +76,8 @@ class RTPacketMaster(Module):
|
|||
assert len(link_layer.tx_rt_data) % 8 == 0
|
||||
ws = len(link_layer.tx_rt_data)
|
||||
tx_plm = get_m2s_layouts(ws)
|
||||
tx_dp = ClockDomainsRenamer("rtio")(TransmitDatapath(
|
||||
link_layer.tx_rt_frame, link_layer.tx_rt_data, tx_plm))
|
||||
tx_dp = TransmitDatapath(
|
||||
link_layer.tx_rt_frame, link_layer.tx_rt_data, tx_plm)
|
||||
self.submodules += tx_dp
|
||||
rx_plm = get_s2m_layouts(ws)
|
||||
rx_dp = ClockDomainsRenamer("rtio_rx")(ReceiveDatapath(
|
||||
|
@ -85,8 +85,7 @@ class RTPacketMaster(Module):
|
|||
self.submodules += rx_dp
|
||||
|
||||
# Write FIFO and extra data count
|
||||
sr_fifo = ClockDomainsRenamer({"write": "sys", "read": "rtio"})(
|
||||
AsyncFIFO(1+64+24+8+512, sr_fifo_depth))
|
||||
sr_fifo = SyncFIFO(1+64+24+8+512, sr_fifo_depth)
|
||||
self.submodules += sr_fifo
|
||||
sr_notwrite_d = Signal()
|
||||
sr_timestamp_d = Signal(64)
|
||||
|
@ -106,7 +105,7 @@ class RTPacketMaster(Module):
|
|||
sr_buf_re = Signal()
|
||||
|
||||
self.comb += sr_fifo.re.eq(sr_fifo.readable & (~sr_buf_readable | sr_buf_re))
|
||||
self.sync.rtio += \
|
||||
self.sync += \
|
||||
If(sr_fifo.re,
|
||||
sr_buf_readable.eq(1),
|
||||
).Elif(sr_buf_re,
|
||||
|
@ -120,7 +119,7 @@ class RTPacketMaster(Module):
|
|||
sr_extra_data_cnt = Signal(8)
|
||||
sr_data = Signal(512)
|
||||
|
||||
self.sync.rtio += If(sr_fifo.re,
|
||||
self.sync += If(sr_fifo.re,
|
||||
sr_notwrite.eq(sr_notwrite_d),
|
||||
sr_timestamp.eq(sr_timestamp_d),
|
||||
sr_chan_sel.eq(sr_chan_sel_d),
|
||||
|
@ -131,11 +130,11 @@ class RTPacketMaster(Module):
|
|||
sr_extra_data_d = Signal(512)
|
||||
self.comb += sr_extra_data_d.eq(sr_data_d[short_data_len:])
|
||||
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)))
|
||||
|
||||
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_last = Signal()
|
||||
|
@ -146,7 +145,7 @@ class RTPacketMaster(Module):
|
|||
for i in range(512//ws)}),
|
||||
extra_data_last.eq(extra_data_counter == sr_extra_data_cnt)
|
||||
]
|
||||
self.sync.rtio += \
|
||||
self.sync += \
|
||||
If(extra_data_ce,
|
||||
extra_data_counter.eq(extra_data_counter + 1),
|
||||
).Else(
|
||||
|
@ -160,18 +159,6 @@ class RTPacketMaster(Module):
|
|||
buffer_space_not, 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_no_event = Signal()
|
||||
read_is_overflow = Signal()
|
||||
|
@ -199,14 +186,14 @@ class RTPacketMaster(Module):
|
|||
]
|
||||
|
||||
# TX FSM
|
||||
tx_fsm = ClockDomainsRenamer("rtio")(FSM(reset_state="IDLE"))
|
||||
tx_fsm = FSM(reset_state="IDLE")
|
||||
self.submodules += tx_fsm
|
||||
|
||||
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_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",
|
||||
# Ensure 2 cycles between frames on the link.
|
||||
|
@ -223,10 +210,10 @@ class RTPacketMaster(Module):
|
|||
NextState("WRITE")
|
||||
)
|
||||
).Else(
|
||||
If(echo_stb,
|
||||
If(self.echo_stb,
|
||||
echo_sent_now.eq(1),
|
||||
NextState("ECHO")
|
||||
).Elif(set_time_stb,
|
||||
).Elif(self.set_time_stb,
|
||||
tsc_value_load.eq(1),
|
||||
NextState("SET_TIME")
|
||||
)
|
||||
|
@ -273,14 +260,14 @@ class RTPacketMaster(Module):
|
|||
tx_fsm.act("ECHO",
|
||||
tx_dp.send("echo_request"),
|
||||
If(tx_dp.packet_last,
|
||||
echo_ack.eq(1),
|
||||
self.echo_ack.eq(1),
|
||||
NextState("IDLE")
|
||||
)
|
||||
)
|
||||
tx_fsm.act("SET_TIME",
|
||||
tx_dp.send("set_time", timestamp=tsc_value),
|
||||
If(tx_dp.packet_last,
|
||||
set_time_ack.eq(1),
|
||||
self.set_time_ack.eq(1),
|
||||
NextState("IDLE")
|
||||
)
|
||||
)
|
||||
|
@ -334,16 +321,14 @@ class RTPacketMaster(Module):
|
|||
# packet counters
|
||||
tx_frame_r = Signal()
|
||||
packet_cnt_tx = Signal(32)
|
||||
self.sync.rtio += [
|
||||
self.sync += [
|
||||
tx_frame_r.eq(link_layer.tx_rt_frame),
|
||||
If(link_layer.tx_rt_frame & ~tx_frame_r,
|
||||
packet_cnt_tx.eq(packet_cnt_tx + 1))
|
||||
]
|
||||
cdc_packet_cnt_tx = GrayCodeTransfer(32)
|
||||
self.submodules += cdc_packet_cnt_tx
|
||||
|
||||
self.comb += [
|
||||
cdc_packet_cnt_tx.i.eq(packet_cnt_tx),
|
||||
self.packet_cnt_tx.eq(cdc_packet_cnt_tx.o)
|
||||
self.packet_cnt_tx.eq(packet_cnt_tx)
|
||||
]
|
||||
|
||||
rx_frame_r = Signal()
|
||||
|
@ -353,7 +338,7 @@ class RTPacketMaster(Module):
|
|||
If(link_layer.rx_rt_frame & ~rx_frame_r,
|
||||
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))
|
||||
self.submodules += cdc_packet_cnt_rx
|
||||
self.comb += [
|
||||
|
|
|
@ -38,8 +38,8 @@ class RTPacketRepeater(Module):
|
|||
assert len(link_layer.tx_rt_data) % 8 == 0
|
||||
ws = len(link_layer.tx_rt_data)
|
||||
tx_plm = get_m2s_layouts(ws)
|
||||
tx_dp = ClockDomainsRenamer("rtio")(TransmitDatapath(
|
||||
link_layer.tx_rt_frame, link_layer.tx_rt_data, tx_plm))
|
||||
tx_dp = TransmitDatapath(
|
||||
link_layer.tx_rt_frame, link_layer.tx_rt_data, tx_plm)
|
||||
self.submodules += tx_dp
|
||||
rx_plm = get_s2m_layouts(ws)
|
||||
rx_dp = ClockDomainsRenamer("rtio_rx")(ReceiveDatapath(
|
||||
|
@ -49,7 +49,7 @@ class RTPacketRepeater(Module):
|
|||
# TSC sync
|
||||
tsc_value = Signal(64)
|
||||
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
|
||||
cb0_loaded = Signal()
|
||||
|
@ -60,7 +60,7 @@ class RTPacketRepeater(Module):
|
|||
cb0_chan_sel = Signal(24)
|
||||
cb0_o_address = Signal(8)
|
||||
cb0_o_data = Signal(512)
|
||||
self.sync.rtio += [
|
||||
self.sync += [
|
||||
If(self.reset | cb0_ack,
|
||||
cb0_loaded.eq(0),
|
||||
cb0_cmd.eq(cri.commands["nop"])
|
||||
|
@ -91,7 +91,7 @@ class RTPacketRepeater(Module):
|
|||
cb_chan_sel = Signal(24)
|
||||
cb_o_address = Signal(8)
|
||||
cb_o_data = Signal(512)
|
||||
self.sync.rtio += [
|
||||
self.sync += [
|
||||
If(self.reset | cb_ack,
|
||||
cb_loaded.eq(0),
|
||||
cb_cmd.eq(cri.commands["nop"])
|
||||
|
@ -112,11 +112,11 @@ class RTPacketRepeater(Module):
|
|||
wb_extra_data_a = Signal(512)
|
||||
self.comb += wb_extra_data_a.eq(self.cri.o_data[short_data_len:])
|
||||
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)))
|
||||
|
||||
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))
|
||||
|
||||
extra_data_ce = Signal()
|
||||
|
@ -128,7 +128,7 @@ class RTPacketRepeater(Module):
|
|||
for i in range(512//ws)}),
|
||||
extra_data_last.eq(extra_data_counter == wb_extra_data_cnt)
|
||||
]
|
||||
self.sync.rtio += \
|
||||
self.sync += \
|
||||
If(extra_data_ce,
|
||||
extra_data_counter.eq(extra_data_counter + 1),
|
||||
).Else(
|
||||
|
@ -136,19 +136,19 @@ class RTPacketRepeater(Module):
|
|||
)
|
||||
|
||||
# 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:]))
|
||||
|
||||
rx_buffer_space_not = Signal()
|
||||
rx_buffer_space = Signal(16)
|
||||
buffer_space_not = 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,
|
||||
buffer_space_not, buffer_space_not_ack,
|
||||
self.cri.o_buffer_space)
|
||||
|
||||
timeout_counter = ClockDomainsRenamer("rtio")(WaitTimer(8191))
|
||||
timeout_counter = WaitTimer(8191)
|
||||
self.submodules += timeout_counter
|
||||
|
||||
# Read
|
||||
|
@ -163,7 +163,7 @@ class RTPacketRepeater(Module):
|
|||
rtio_read_is_overflow = Signal()
|
||||
rtio_read_data = Signal(32)
|
||||
rtio_read_timestamp = Signal(64)
|
||||
self.submodules += CrossDomainNotification("rtio_rx", "rtio",
|
||||
self.submodules += CrossDomainNotification("rtio_rx", "sys",
|
||||
read_not,
|
||||
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))
|
||||
|
||||
load_read_reply = Signal()
|
||||
self.sync.rtio += [
|
||||
self.sync += [
|
||||
If(load_read_reply,
|
||||
i_status_wait_event.eq(0),
|
||||
i_status_overflow.eq(0),
|
||||
|
@ -200,7 +200,7 @@ class RTPacketRepeater(Module):
|
|||
]
|
||||
|
||||
# TX and CRI FSM
|
||||
tx_fsm = ClockDomainsRenamer("rtio")(FSM(reset_state="IDLE"))
|
||||
tx_fsm = FSM(reset_state="IDLE")
|
||||
self.submodules += tx_fsm
|
||||
|
||||
tx_fsm.act("IDLE",
|
||||
|
|
|
@ -17,7 +17,7 @@ class GenericRXSynchronizer(Module):
|
|||
return synchronized
|
||||
|
||||
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.comb += [
|
||||
eb.din.eq(Cat(*[s[0] for s in self.signals])),
|
||||
|
@ -57,6 +57,6 @@ class XilinxRXSynchronizer(Module):
|
|||
self.specials += [
|
||||
Instance("FD", i_C=ClockSignal("rtio_rx"), i_D=din[i], o_Q=inter[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))})
|
||||
]
|
||||
|
|
|
@ -1,23 +1,23 @@
|
|||
from migen import *
|
||||
from migen.genlib.cdc import MultiReg, PulseSynchronizer
|
||||
from migen.genlib.cdc import MultiReg
|
||||
|
||||
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.
|
||||
|
||||
class SiPhaser7Series(Module, AutoCSR):
|
||||
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.phase_shift = CSR()
|
||||
self.phase_shift_done = CSRStatus(reset=1)
|
||||
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,
|
||||
# we do not use the crystal reference so that the PFD (f3) frequency
|
||||
# can be high.
|
||||
|
@ -97,17 +97,14 @@ class SiPhaser7Series(Module, AutoCSR):
|
|||
toggle_out = rx_synchronizer.resync(toggle_in)
|
||||
|
||||
toggle_out_expected = Signal()
|
||||
self.sync.rtio += toggle_out_expected.eq(~toggle_out)
|
||||
self.sync += toggle_out_expected.eq(~toggle_out)
|
||||
|
||||
error = Signal()
|
||||
error_clear = PulseSynchronizer("sys", "rtio")
|
||||
self.submodules += error_clear
|
||||
self.sync.rtio += [
|
||||
self.sync += [
|
||||
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.comb += error_clear.i.eq(self.error.re)
|
||||
|
||||
# expose MMCM outputs - used for clock constraints
|
||||
self.mmcm_freerun_output = mmcm_freerun_output
|
||||
|
|
|
@ -33,7 +33,7 @@ class BruteforceClockAligner(Module):
|
|||
check_counter = Signal(max=check_max_val+1)
|
||||
check = Signal()
|
||||
reset_check_counter = Signal()
|
||||
self.sync.rtio_tx += [
|
||||
self.sync += [
|
||||
check.eq(0),
|
||||
If(reset_check_counter,
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
fsm.act("WAIT_COMMA",
|
||||
|
|
|
@ -20,8 +20,7 @@ class GTPSingle(Module):
|
|||
|
||||
self.stable_clkin = Signal()
|
||||
self.txenable = Signal()
|
||||
self.submodules.encoder = encoder = ClockDomainsRenamer("rtio_tx")(
|
||||
Encoder(2, True))
|
||||
self.submodules.encoder = encoder = Encoder(2, True)
|
||||
self.submodules.decoders = decoders = [ClockDomainsRenamer("rtio_rx")(
|
||||
(Decoder(True))) for _ in range(2)]
|
||||
self.rx_ready = Signal()
|
||||
|
@ -33,10 +32,11 @@ class GTPSingle(Module):
|
|||
|
||||
# # #
|
||||
|
||||
# TX generates RTIO clock, init must be in system domain
|
||||
self.submodules.tx_init = tx_init = GTPTXInit(sys_clk_freq, mode)
|
||||
# RX receives restart commands from RTIO domain
|
||||
rx_init = ClockDomainsRenamer("rtio_tx")(GTPRXInit(rtio_clk_freq))
|
||||
# TX generates RTIO clock, init must be in bootstrap domain
|
||||
self.submodules.tx_init = tx_init = ClockDomainsRenamer("bootstrap")(
|
||||
GTPTXInit(125e6, mode))
|
||||
# RX receives restart commands from SYS domain
|
||||
rx_init = GTPRXInit(rtio_clk_freq)
|
||||
self.submodules += rx_init
|
||||
|
||||
self.comb += [
|
||||
|
@ -367,7 +367,7 @@ class GTPSingle(Module):
|
|||
|
||||
# Channel - DRP Ports
|
||||
i_DRPADDR=rx_init.drpaddr,
|
||||
i_DRPCLK=ClockSignal("rtio_tx"),
|
||||
i_DRPCLK=ClockSignal("sys"),
|
||||
i_DRPDI=rx_init.drpdi,
|
||||
o_DRPDO=rx_init.drpdo,
|
||||
i_DRPEN=rx_init.drpen,
|
||||
|
@ -566,8 +566,8 @@ class GTPSingle(Module):
|
|||
i_PMARSVDIN1 =0b0,
|
||||
# Transmit Ports - FPGA TX Interface Ports
|
||||
i_TXDATA =Cat(txdata[:8], txdata[10:18]),
|
||||
i_TXUSRCLK =ClockSignal("rtio_tx"),
|
||||
i_TXUSRCLK2 =ClockSignal("rtio_tx"),
|
||||
i_TXUSRCLK =ClockSignal("sys"),
|
||||
i_TXUSRCLK2 =ClockSignal("sys"),
|
||||
|
||||
# Transmit Ports - PCI Express Ports
|
||||
i_TXELECIDLE =0,
|
||||
|
@ -665,19 +665,10 @@ class GTPSingle(Module):
|
|||
raise ValueError
|
||||
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_reset_deglitched = Signal()
|
||||
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.specials += [
|
||||
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 = []
|
||||
for i in range(nchannels):
|
||||
if nchannels == 1:
|
||||
|
@ -735,10 +725,6 @@ class GTP(Module, TransceiverInterface):
|
|||
else:
|
||||
mode = "master" if i == master else "slave"
|
||||
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)
|
||||
setattr(self.submodules, "gtp"+str(i), gtp)
|
||||
channel_interface = ChannelInterface(gtp.encoder, gtp.decoders)
|
||||
|
@ -754,10 +740,6 @@ class GTP(Module, TransceiverInterface):
|
|||
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):
|
||||
self.comb += [
|
||||
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):
|
||||
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:
|
||||
name = "counter_" + domain
|
||||
counter = CSRStatus(counter_width, name=name)
|
||||
|
|
|
@ -105,7 +105,7 @@ class MiqroChannel(Module):
|
|||
self.pulse.eq(pulse),
|
||||
self.rtlink.o.busy.eq(stb & ~self.ack),
|
||||
]
|
||||
self.sync.rtio += [
|
||||
self.sync += [
|
||||
If(~stb,
|
||||
dt.eq(dt + 2),
|
||||
),
|
||||
|
@ -162,7 +162,7 @@ class Miqro(Module):
|
|||
]
|
||||
|
||||
re_dly = Signal(3) # stage, send, respond
|
||||
self.sync.rtio += [
|
||||
self.sync += [
|
||||
header.type.eq(3), # body type is miqro pulse data
|
||||
If(self.serializer.stb,
|
||||
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 import rtio
|
||||
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.drtio.transceiver import gtp_7series
|
||||
from artiq.gateware.drtio.siphaser import SiPhaser7Series
|
||||
|
@ -76,6 +76,23 @@ class StandaloneBase(MiniSoC, AMPSoC):
|
|||
self.platform.request("error_led")))
|
||||
self.csr_devices.append("error_led")
|
||||
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")
|
||||
self.submodules.i2c = gpio.GPIOTristate([i2c.scl, i2c.sda])
|
||||
|
@ -218,6 +235,8 @@ class MasterBase(MiniSoC, AMPSoC):
|
|||
integrated_sram_size=8192,
|
||||
ethmac_nrxslots=4,
|
||||
ethmac_ntxslots=4,
|
||||
clk_freq=rtio_clk_freq,
|
||||
rtio_sys_merge=True,
|
||||
**kwargs)
|
||||
AMPSoC.__init__(self)
|
||||
add_identifier(self, gateware_identifier_str=gateware_identifier_str)
|
||||
|
@ -256,8 +275,6 @@ class MasterBase(MiniSoC, AMPSoC):
|
|||
sys_clk_freq=self.clk_freq,
|
||||
rtio_clk_freq=rtio_clk_freq)
|
||||
self.csr_devices.append("drtio_transceiver")
|
||||
self.sync += self.disable_cdr_clk_ibuf.eq(
|
||||
~self.drtio_transceiver.stable_clkin.storage)
|
||||
|
||||
if enable_sata:
|
||||
sfp_channels = self.drtio_transceiver.channels[1:]
|
||||
|
@ -307,8 +324,14 @@ class MasterBase(MiniSoC, AMPSoC):
|
|||
|
||||
rtio_clk_period = 1e9/rtio_clk_freq
|
||||
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.rxoutclk, rtio_clk_period)
|
||||
|
||||
platform.add_false_path_constraints(
|
||||
self.crg.cd_sys.clk,
|
||||
gtp.txoutclk, gtp.rxoutclk)
|
||||
|
@ -317,8 +340,6 @@ class MasterBase(MiniSoC, AMPSoC):
|
|||
platform.add_false_path_constraints(
|
||||
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)
|
||||
|
||||
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
|
||||
# unrelated transceiver PLLs into one GTPE2_COMMON yourself.
|
||||
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":
|
||||
cdr_clk_clean = self.platform.request("cdr_clk_clean")
|
||||
cdr_clk_out = self.platform.request("cdr_clk_clean")
|
||||
else:
|
||||
cdr_clk_clean = self.platform.request("si5324_clkout")
|
||||
cdr_clk_clean_buf = Signal()
|
||||
cdr_clk_out = self.platform.request("si5324_clkout")
|
||||
|
||||
cdr_clk = Signal()
|
||||
self.platform.add_period_constraint(cdr_clk_out, 8.)
|
||||
|
||||
self.specials += Instance("IBUFDS_GTE2",
|
||||
i_CEB=self.disable_cdr_clk_ibuf,
|
||||
i_I=cdr_clk_clean.p, i_IB=cdr_clk_clean.n,
|
||||
o_O=cdr_clk_clean_buf)
|
||||
i_CEB=0,
|
||||
i_I=cdr_clk_out.p, i_IB=cdr_clk_out.n,
|
||||
o_O=cdr_clk)
|
||||
# Note precisely the rules Xilinx made up:
|
||||
# refclksel=0b001 GTREFCLK0 selected
|
||||
# refclksel=0b010 GTREFCLK1 selected
|
||||
|
@ -377,7 +397,8 @@ class MasterBase(MiniSoC, AMPSoC):
|
|||
fbdiv=4,
|
||||
fbdiv_45=5,
|
||||
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.submodules += qpll
|
||||
self.drtio_qpll_channel, self.ethphy_qpll_channel = qpll.channels
|
||||
|
@ -400,6 +421,8 @@ class SatelliteBase(BaseSoC):
|
|||
cpu_bus_width=cpu_bus_width,
|
||||
sdram_controller_type="minicon",
|
||||
l2_size=128*1024,
|
||||
clk_freq=rtio_clk_freq,
|
||||
rtio_sys_merge=True,
|
||||
**kwargs)
|
||||
add_identifier(self, gateware_identifier_str=gateware_identifier_str)
|
||||
|
||||
|
@ -410,23 +433,24 @@ class SatelliteBase(BaseSoC):
|
|||
self.platform.request("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":
|
||||
cdr_clk_clean = self.platform.request("cdr_clk_clean")
|
||||
cdr_clk_out = self.platform.request("cdr_clk_clean")
|
||||
else:
|
||||
cdr_clk_clean = self.platform.request("si5324_clkout")
|
||||
cdr_clk_clean_buf = Signal()
|
||||
cdr_clk_out = self.platform.request("si5324_clkout")
|
||||
|
||||
cdr_clk = Signal()
|
||||
self.platform.add_period_constraint(cdr_clk_out, 8.)
|
||||
|
||||
self.specials += Instance("IBUFDS_GTE2",
|
||||
i_CEB=disable_cdr_clk_ibuf,
|
||||
i_I=cdr_clk_clean.p, i_IB=cdr_clk_clean.n,
|
||||
o_O=cdr_clk_clean_buf)
|
||||
i_CEB=0,
|
||||
i_I=cdr_clk_out.p, i_IB=cdr_clk_out.n,
|
||||
o_O=cdr_clk)
|
||||
qpll_drtio_settings = QPLLSettings(
|
||||
refclksel=0b001,
|
||||
fbdiv=4,
|
||||
fbdiv_45=5,
|
||||
refclk_div=1)
|
||||
qpll = QPLL(cdr_clk_clean_buf, qpll_drtio_settings)
|
||||
qpll = QPLL(cdr_clk, qpll_drtio_settings)
|
||||
self.submodules += qpll
|
||||
|
||||
drtio_data_pads = []
|
||||
|
@ -445,8 +469,6 @@ class SatelliteBase(BaseSoC):
|
|||
sys_clk_freq=self.clk_freq,
|
||||
rtio_clk_freq=rtio_clk_freq)
|
||||
self.csr_devices.append("drtio_transceiver")
|
||||
self.sync += disable_cdr_clk_ibuf.eq(
|
||||
~self.drtio_transceiver.stable_clkin.storage)
|
||||
|
||||
if enable_sata:
|
||||
sfp_channels = self.drtio_transceiver.channels[1:]
|
||||
|
@ -542,6 +564,10 @@ class SatelliteBase(BaseSoC):
|
|||
self.config["SI5324_SOFT_RESET"] = None
|
||||
|
||||
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.rxoutclk, rtio_clk_period)
|
||||
platform.add_false_path_constraints(
|
||||
|
@ -555,8 +581,6 @@ class SatelliteBase(BaseSoC):
|
|||
platform.add_false_path_constraints(
|
||||
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)
|
||||
|
||||
def add_rtio(self, rtio_channels, sed_lanes=8):
|
||||
|
|
|
@ -36,7 +36,7 @@ class TB(Module):
|
|||
def __init__(self, nwords, dw):
|
||||
self.submodules.link_layer = Loopback(nwords)
|
||||
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):
|
||||
|
|
|
@ -144,7 +144,7 @@ class OutputsTestbench:
|
|||
|
||||
|
||||
class TestFullStack(unittest.TestCase):
|
||||
clocks = {"sys": 8, "rtio": 5, "rtio_rx": 5,
|
||||
clocks = {"sys": 8, "rtio_rx": 5,
|
||||
"rio": 5, "rio_phy": 5}
|
||||
|
||||
def test_pulses(self):
|
||||
|
@ -169,7 +169,7 @@ class TestFullStack(unittest.TestCase):
|
|||
yield from tb.sync()
|
||||
|
||||
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)
|
||||
|
||||
def test_underflow(self):
|
||||
|
@ -214,7 +214,7 @@ class TestFullStack(unittest.TestCase):
|
|||
yield from tb.sync()
|
||||
|
||||
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)
|
||||
|
||||
def test_write_underflow(self):
|
||||
|
@ -284,7 +284,7 @@ class TestFullStack(unittest.TestCase):
|
|||
yield dut.phy2.rtlink.i.stb.eq(0)
|
||||
|
||||
run_simulation(dut,
|
||||
{"sys": test(), "rtio": generate_input()}, self.clocks)
|
||||
{"sys": test()}, self.clocks)
|
||||
|
||||
def test_echo(self):
|
||||
dut = DUT(2)
|
||||
|
|
|
@ -12,7 +12,7 @@ def create_dut(nwords):
|
|||
pt = PacketInterface("s2m", nwords*8)
|
||||
pr = PacketInterface("m2s", nwords*8)
|
||||
ts = Signal(64)
|
||||
dut = ClockDomainsRenamer({"rtio": "sys", "rtio_rx": "sys"})(
|
||||
dut = ClockDomainsRenamer({"rtio_rx": "sys"})(
|
||||
RTPacketRepeater(
|
||||
SimpleNamespace(coarse_ts=ts),
|
||||
SimpleNamespace(
|
||||
|
|
|
@ -130,7 +130,7 @@ class Testbench:
|
|||
|
||||
|
||||
class TestSwitching(unittest.TestCase):
|
||||
clocks = {"sys": 8, "rtio": 5, "rtio_rx": 5,
|
||||
clocks = {"sys": 8, "rtio_rx": 5,
|
||||
"rio": 5, "rio_phy": 5}
|
||||
|
||||
def test_outputs(self):
|
||||
|
@ -183,7 +183,7 @@ class TestSwitching(unittest.TestCase):
|
|||
current_request = (packet_type, field_dict, trailer)
|
||||
|
||||
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):
|
||||
|
@ -244,4 +244,4 @@ class TestSwitching(unittest.TestCase):
|
|||
current_request = (packet_type, field_dict, trailer)
|
||||
|
||||
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