DRTIO: RTIO/SYS clock merge

pull/2045/head
Spaqin 2022-12-17 15:39:54 +08:00 committed by GitHub
parent ad000609ce
commit 17efc28dbe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 210 additions and 219 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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 += [

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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