forked from M-Labs/artiq
1
0
Fork 0

drtio: reset link from CPU

This commit is contained in:
Sebastien Bourdeauducq 2016-11-18 17:45:33 +08:00
parent f040e27041
commit 4d07974a34
2 changed files with 39 additions and 25 deletions

View File

@ -3,7 +3,7 @@ from operator import xor, or_
from migen import * from migen import *
from migen.genlib.fsm import * from migen.genlib.fsm import *
from migen.genlib.cdc import MultiReg from migen.genlib.cdc import MultiReg, PulseSynchronizer
from migen.genlib.misc import WaitTimer from migen.genlib.misc import WaitTimer
from misoc.interconnect.csr import * from misoc.interconnect.csr import *
@ -223,10 +223,8 @@ class LinkLayerRX(Module):
class LinkLayer(Module, AutoCSR): class LinkLayer(Module, AutoCSR):
def __init__(self, encoder, decoders): def __init__(self, encoder, decoders):
self.link_status = CSRStatus() self.link_status = CSRStatus()
self.link_reset = CSR()
# control signals, in rtio clock domain
self.reset = Signal()
self.ready = Signal()
# pulsed to reset receiver, rx_ready must immediately go low # pulsed to reset receiver, rx_ready must immediately go low
self.rx_reset = Signal() self.rx_reset = Signal()
# receiver locked including comma alignment # receiver locked including comma alignment
@ -252,37 +250,46 @@ class LinkLayer(Module, AutoCSR):
# # # # # #
ready_r = Signal() ready = Signal()
reset_ps = PulseSynchronizer("sys", "rtio")
done_ps = PulseSynchronizer("rtio", "sys")
self.submodules += reset_ps, done_ps
self.comb += reset_ps.i.eq(self.link_reset.re)
self.sync += [
If(done_ps.o, ready.eq(1)),
If(reset_ps.i, ready.eq(0)),
]
self.comb += self.link_status.status.eq(ready)
ready_rx = Signal() ready_rx = Signal()
self.sync.rtio += ready_r.eq(self.ready) ready.attr.add("no_retiming")
ready_r.attr.add("no_retiming") self.specials += MultiReg(ready, ready_rx, "rtio_rx")
self.specials += MultiReg(ready_r, ready_rx, "rtio_rx")
self.comb += [ self.comb += [
self.rx_aux_frame.eq(rx.aux_frame & ready_rx), self.rx_aux_frame.eq(rx.aux_frame & ready_rx),
self.rx_rt_frame.eq(rx.rt_frame & ready_rx), self.rx_rt_frame.eq(rx.rt_frame & ready_rx),
] ]
self.specials += MultiReg(ready_r, self.link_status.status)
wait_scrambler = WaitTimer(15) wait_scrambler = ClockDomainsRenamer("rtio")(WaitTimer(15))
self.submodules += wait_scrambler self.submodules += wait_scrambler
fsm = ClockDomainsRenamer("rtio")( fsm = ClockDomainsRenamer("rtio")(FSM(reset_state="RESET_RX"))
ResetInserter()(FSM(reset_state="RESET_RX")))
self.submodules += fsm self.submodules += fsm
self.comb += fsm.reset.eq(self.reset)
fsm.act("RESET_RX", fsm.act("RESET_RX",
self.rx_reset.eq(1), self.rx_reset.eq(1),
NextState("WAIT_RX_READY") NextState("WAIT_RX_READY")
) )
fsm.act("WAIT_RX_READY", fsm.act("WAIT_RX_READY",
If(self.rx_ready, NextState("WAIT_SCRAMBLER_SYNC")) If(self.rx_ready, NextState("WAIT_SCRAMBLER_SYNC")),
If(reset_ps.o, NextState("RESET_RX"))
) )
fsm.act("WAIT_SCRAMBLER_SYNC", fsm.act("WAIT_SCRAMBLER_SYNC",
wait_scrambler.wait.eq(1), wait_scrambler.wait.eq(1),
If(wait_scrambler.done, NextState("READY")), If(wait_scrambler.done,
done_ps.i.eq(1),
NextState("READY")
),
) )
fsm.act("READY", fsm.act("READY",
self.ready.eq(1) If(reset_ps.o, NextState("RESET_RX"))
) )

View File

@ -7,6 +7,12 @@ fn drtio_link_is_up() -> bool {
} }
} }
fn drtio_reset_link() {
unsafe {
csr::drtio::link_reset_write(1)
}
}
fn drtio_sync_tsc() { fn drtio_sync_tsc() {
unsafe { unsafe {
csr::drtio::set_time_write(1); csr::drtio::set_time_write(1);
@ -33,7 +39,7 @@ pub fn link_thread(waiter: Waiter, _spawner: Spawner) {
waiter.until(drtio_link_is_up).unwrap(); waiter.until(drtio_link_is_up).unwrap();
info!("link RX is up"); info!("link RX is up");
waiter.sleep(300); waiter.sleep(300).unwrap();
info!("wait for remote side done"); info!("wait for remote side done");
drtio_sync_tsc(); drtio_sync_tsc();
@ -48,23 +54,24 @@ pub fn link_thread(waiter: Waiter, _spawner: Spawner) {
} }
} }
fn drtio_error_present() -> bool { fn drtio_packet_error_present() -> bool {
unsafe { unsafe {
csr::drtio::err_present_read() != 0 csr::drtio::packet_err_present_read() != 0
} }
} }
fn drtio_get_error() -> u8 { fn drtio_get_packet_error() -> u8 {
unsafe { unsafe {
let err = csr::drtio::err_code_read(); let err = csr::drtio::packet_err_code_read();
csr::drtio::err_present_write(1); csr::drtio::packet_err_present_write(1);
err err
} }
} }
pub fn error_thread(waiter: Waiter, _spawner: Spawner) { pub fn error_thread(waiter: Waiter, _spawner: Spawner) {
loop { loop {
waiter.until(drtio_error_present).unwrap(); waiter.until(drtio_packet_error_present).unwrap();
error!("DRTIO error {}", drtio_get_error()); error!("DRTIO packet error {}", drtio_get_packet_error());
drtio_reset_link();
} }
} }