Skip to content

Commit ba94ed8

Browse files
committedNov 18, 2016
drtio: check for absence of disparity errors before claiming RX ready
1 parent 4d07974 commit ba94ed8

File tree

2 files changed

+56
-21
lines changed

2 files changed

+56
-21
lines changed
 

‎artiq/gateware/drtio/link_layer.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,7 @@ def __init__(self, encoder, decoders):
288288
If(wait_scrambler.done,
289289
done_ps.i.eq(1),
290290
NextState("READY")
291-
),
291+
)
292292
)
293293
fsm.act("READY",
294294
If(reset_ps.o, NextState("RESET_RX"))

‎artiq/gateware/drtio/transceiver/gtx_7series_init.py

+55-20
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
from math import ceil
2+
from functools import reduce
3+
from operator import add
24

35
from migen import *
46
from migen.genlib.cdc import MultiReg, PulseSynchronizer
@@ -134,7 +136,7 @@ def __init__(self, sys_clk_freq, rx):
134136
# Warning: Xilinx transceivers are LSB first, and comma needs to be flipped
135137
# compared to the usual 8b10b binary representation.
136138
class BruteforceClockAligner(Module):
137-
def __init__(self, comma, rtio_clk_freq, check_period=6e-3, ready_time=50e-3):
139+
def __init__(self, comma, rtio_clk_freq, check_period=6e-3):
138140
self.rxdata = Signal(20)
139141
self.restart = Signal()
140142

@@ -144,9 +146,12 @@ def __init__(self, comma, rtio_clk_freq, check_period=6e-3, ready_time=50e-3):
144146
check_max_val = ceil(check_period*rtio_clk_freq)
145147
check_counter = Signal(max=check_max_val+1)
146148
check = Signal()
149+
reset_check_counter = Signal()
147150
self.sync.rtio += [
148151
check.eq(0),
149-
If(~self.ready,
152+
If(reset_check_counter,
153+
check_counter.eq(check_max_val)
154+
).Else(
150155
If(check_counter == 0,
151156
check.eq(1),
152157
check_counter.eq(check_max_val)
@@ -156,37 +161,67 @@ def __init__(self, comma, rtio_clk_freq, check_period=6e-3, ready_time=50e-3):
156161
)
157162
]
158163

164+
checks_reset = PulseSynchronizer("rtio", "rtio_rx")
165+
self.submodules += checks_reset
166+
159167
comma_n = ~comma & 0b1111111111
160168
comma_seen_rxclk = Signal()
161169
comma_seen = Signal()
162170
comma_seen_rxclk.attr.add("no_retiming")
163171
self.specials += MultiReg(comma_seen_rxclk, comma_seen)
164-
comma_seen_reset = PulseSynchronizer("rtio", "rtio_rx")
165-
self.submodules += comma_seen_reset
166172
self.sync.rtio_rx += \
167-
If(comma_seen_reset.o,
173+
If(checks_reset.o,
168174
comma_seen_rxclk.eq(0)
169175
).Elif((self.rxdata[:10] == comma) | (self.rxdata[:10] == comma_n),
170176
comma_seen_rxclk.eq(1)
171177
)
172178

173-
self.comb += \
174-
If(check,
175-
If(~comma_seen, self.restart.eq(1)),
176-
comma_seen_reset.i.eq(1)
179+
error_seen_rxclk = Signal()
180+
error_seen = Signal()
181+
error_seen_rxclk.attr.add("no_retiming")
182+
self.specials += MultiReg(error_seen_rxclk, error_seen)
183+
rx1cnt = Signal(max=11)
184+
self.sync.rtio_rx += [
185+
rx1cnt.eq(reduce(add, [self.rxdata[i] for i in range(10)])),
186+
If(checks_reset.o,
187+
error_seen_rxclk.eq(0)
188+
).Elif((rx1cnt != 4) & (rx1cnt != 5) & (rx1cnt != 6),
189+
error_seen_rxclk.eq(1)
177190
)
191+
]
178192

179-
ready_counts = ceil(ready_time/check_period)
180-
assert ready_counts > 1
181-
ready_counter = Signal(max=ready_counts+1, reset=ready_counts)
182-
self.sync.rtio += [
193+
fsm = ClockDomainsRenamer("rtio")(FSM(reset_state="WAIT_COMMA"))
194+
self.submodules += fsm
195+
196+
fsm.act("WAIT_COMMA",
183197
If(check,
198+
# Errors are still OK at this stage, as the transceiver
199+
# has just been reset and may output garbage data.
184200
If(comma_seen,
185-
If(ready_counter != 0, ready_counter.eq(ready_counter-1))
201+
NextState("WAIT_NOERROR")
186202
).Else(
187-
ready_counter.eq(ready_counts)
188-
)
189-
),
190-
If(self.reset, ready_counter.eq(ready_counts))
191-
]
192-
self.comb += self.ready.eq(ready_counter == 0)
203+
self.restart.eq(1)
204+
),
205+
checks_reset.i.eq(1)
206+
)
207+
)
208+
fsm.act("WAIT_NOERROR",
209+
If(check,
210+
If(comma_seen & ~error_seen,
211+
NextState("READY")
212+
).Else(
213+
self.restart.eq(1),
214+
NextState("WAIT_COMMA")
215+
),
216+
checks_reset.i.eq(1)
217+
)
218+
)
219+
fsm.act("READY",
220+
reset_check_counter.eq(1),
221+
self.ready.eq(1),
222+
If(self.reset,
223+
checks_reset.i.eq(1),
224+
self.restart.eq(1),
225+
NextState("WAIT_COMMA")
226+
)
227+
)

0 commit comments

Comments
 (0)
Please sign in to comment.