forked from M-Labs/artiq
drtio: use additive scrambler reset by link init
This commit is contained in:
parent
8a92c2c7e5
commit
e59142e344
|
@ -5,24 +5,6 @@ from migen import *
|
||||||
|
|
||||||
|
|
||||||
class Scrambler(Module):
|
class Scrambler(Module):
|
||||||
def __init__(self, n_io, n_state=23, taps=[17, 22]):
|
|
||||||
self.i = Signal(n_io)
|
|
||||||
self.o = Signal(n_io)
|
|
||||||
|
|
||||||
# # #
|
|
||||||
|
|
||||||
state = Signal(n_state, reset=1)
|
|
||||||
curval = [state[i] for i in range(n_state)]
|
|
||||||
for i in reversed(range(n_io)):
|
|
||||||
out = self.i[i] ^ reduce(xor, [curval[tap] for tap in taps])
|
|
||||||
self.sync += self.o[i].eq(out)
|
|
||||||
curval.insert(0, out)
|
|
||||||
curval.pop()
|
|
||||||
|
|
||||||
self.sync += state.eq(Cat(*curval[:n_state]))
|
|
||||||
|
|
||||||
|
|
||||||
class Descrambler(Module):
|
|
||||||
def __init__(self, n_io, n_state=23, taps=[17, 22]):
|
def __init__(self, n_io, n_state=23, taps=[17, 22]):
|
||||||
self.i = Signal(n_io)
|
self.i = Signal(n_io)
|
||||||
self.o = Signal(n_io)
|
self.o = Signal(n_io)
|
||||||
|
@ -33,8 +15,8 @@ class Descrambler(Module):
|
||||||
curval = [state[i] for i in range(n_state)]
|
curval = [state[i] for i in range(n_state)]
|
||||||
for i in reversed(range(n_io)):
|
for i in reversed(range(n_io)):
|
||||||
flip = reduce(xor, [curval[tap] for tap in taps])
|
flip = reduce(xor, [curval[tap] for tap in taps])
|
||||||
self.sync += self.o[i].eq(self.i[i] ^ flip)
|
self.sync += self.o[i].eq(flip ^ self.i[i])
|
||||||
curval.insert(0, self.i[i])
|
curval.insert(0, flip)
|
||||||
curval.pop()
|
curval.pop()
|
||||||
|
|
||||||
self.sync += state.eq(Cat(*curval[:n_state]))
|
self.sync += state.eq(Cat(*curval[:n_state]))
|
||||||
|
@ -70,7 +52,7 @@ class LinkLayerTX(Module):
|
||||||
# the following meanings:
|
# the following meanings:
|
||||||
# 100 idle/auxiliary framing
|
# 100 idle/auxiliary framing
|
||||||
# 0AB 2 bits of auxiliary data
|
# 0AB 2 bits of auxiliary data
|
||||||
aux_scrambler = CEInserter()(Scrambler(3*nwords))
|
aux_scrambler = ResetInserter()(CEInserter()(Scrambler(3*nwords)))
|
||||||
self.submodules += aux_scrambler
|
self.submodules += aux_scrambler
|
||||||
aux_data_ctl = []
|
aux_data_ctl = []
|
||||||
for i in range(nwords):
|
for i in range(nwords):
|
||||||
|
@ -82,6 +64,7 @@ class LinkLayerTX(Module):
|
||||||
).Else(
|
).Else(
|
||||||
aux_scrambler.i.eq(Replicate(0b100, nwords))
|
aux_scrambler.i.eq(Replicate(0b100, nwords))
|
||||||
),
|
),
|
||||||
|
aux_scrambler.reset.eq(self.link_init),
|
||||||
aux_scrambler.ce.eq(~self.rt_frame),
|
aux_scrambler.ce.eq(~self.rt_frame),
|
||||||
self.aux_ack.eq(~self.rt_frame)
|
self.aux_ack.eq(~self.rt_frame)
|
||||||
]
|
]
|
||||||
|
@ -98,10 +81,11 @@ class LinkLayerTX(Module):
|
||||||
|
|
||||||
# Real-time traffic uses data characters and is framed by the special
|
# Real-time traffic uses data characters and is framed by the special
|
||||||
# characters of auxiliary traffic. RT traffic is also scrambled.
|
# characters of auxiliary traffic. RT traffic is also scrambled.
|
||||||
rt_scrambler = CEInserter()(Scrambler(8*nwords))
|
rt_scrambler = ResetInserter()(CEInserter()(Scrambler(8*nwords)))
|
||||||
self.submodules += rt_scrambler
|
self.submodules += rt_scrambler
|
||||||
self.comb += [
|
self.comb += [
|
||||||
rt_scrambler.i.eq(self.rt_data),
|
rt_scrambler.i.eq(self.rt_data),
|
||||||
|
rt_scrambler.reset.eq(self.link_init),
|
||||||
rt_scrambler.ce.eq(self.rt_frame)
|
rt_scrambler.ce.eq(self.rt_frame)
|
||||||
]
|
]
|
||||||
rt_frame_r = Signal()
|
rt_frame_r = Signal()
|
||||||
|
@ -153,8 +137,8 @@ class LinkLayerRX(Module):
|
||||||
|
|
||||||
# # #
|
# # #
|
||||||
|
|
||||||
aux_descrambler = CEInserter()(Descrambler(2*nwords))
|
aux_descrambler = ResetInserter()(CEInserter()(Scrambler(2*nwords)))
|
||||||
rt_descrambler = CEInserter()(Descrambler(8*nwords))
|
rt_descrambler = ResetInserter()(CEInserter()(Scrambler(8*nwords)))
|
||||||
self.submodules += aux_descrambler, rt_descrambler
|
self.submodules += aux_descrambler, rt_descrambler
|
||||||
self.comb += [
|
self.comb += [
|
||||||
self.aux_frame.eq(~aux_descrambler.o[2]),
|
self.aux_frame.eq(~aux_descrambler.o[2]),
|
||||||
|
@ -173,7 +157,9 @@ class LinkLayerRX(Module):
|
||||||
self.comb += [
|
self.comb += [
|
||||||
If(decoders[0].k,
|
If(decoders[0].k,
|
||||||
If((decoders[0].d == K(28, 7)) | (decoders[0].d == K(29, 7)),
|
If((decoders[0].d == K(28, 7)) | (decoders[0].d == K(29, 7)),
|
||||||
link_init_d.eq(1)
|
link_init_d.eq(1),
|
||||||
|
aux_descrambler.reset.eq(1),
|
||||||
|
rt_descrambler.reset.eq(1)
|
||||||
),
|
),
|
||||||
aux_descrambler.ce.eq(1)
|
aux_descrambler.ce.eq(1)
|
||||||
).Else(
|
).Else(
|
||||||
|
|
|
@ -6,7 +6,8 @@ from migen import *
|
||||||
from artiq.gateware.drtio.link_layer import *
|
from artiq.gateware.drtio.link_layer import *
|
||||||
|
|
||||||
|
|
||||||
def process(dut, seq):
|
def process(seq):
|
||||||
|
dut = Scrambler(8)
|
||||||
rseq = []
|
rseq = []
|
||||||
def pump():
|
def pump():
|
||||||
yield dut.i.eq(seq[0])
|
yield dut.i.eq(seq[0])
|
||||||
|
@ -24,17 +25,11 @@ def process(dut, seq):
|
||||||
class TestScrambler(unittest.TestCase):
|
class TestScrambler(unittest.TestCase):
|
||||||
def test_roundtrip(self):
|
def test_roundtrip(self):
|
||||||
seq = list(range(256))*3
|
seq = list(range(256))*3
|
||||||
scrambled_seq = process(Scrambler(8), seq)
|
scrambled_seq = process(seq)
|
||||||
descrambled_seq = process(Descrambler(8), scrambled_seq)
|
descrambled_seq = process(scrambled_seq)
|
||||||
self.assertNotEqual(seq, scrambled_seq)
|
self.assertNotEqual(seq, scrambled_seq)
|
||||||
self.assertEqual(seq, descrambled_seq)
|
self.assertEqual(seq, descrambled_seq)
|
||||||
|
|
||||||
def test_resync(self):
|
|
||||||
seq = list(range(256))
|
|
||||||
scrambled_seq = process(Scrambler(8), seq)
|
|
||||||
descrambled_seq = process(Descrambler(8), scrambled_seq[20:])
|
|
||||||
self.assertEqual(seq[100:], descrambled_seq[80:])
|
|
||||||
|
|
||||||
|
|
||||||
class Loopback(Module):
|
class Loopback(Module):
|
||||||
def __init__(self, nwords):
|
def __init__(self, nwords):
|
||||||
|
@ -50,12 +45,24 @@ class TestLinkLayer(unittest.TestCase):
|
||||||
def test_packets(self):
|
def test_packets(self):
|
||||||
dut = Loopback(4)
|
dut = Loopback(4)
|
||||||
|
|
||||||
|
def link_init():
|
||||||
|
yield dut.tx.link_init.eq(1)
|
||||||
|
yield
|
||||||
|
yield
|
||||||
|
yield dut.tx.link_init.eq(0)
|
||||||
|
yield
|
||||||
|
|
||||||
rt_packets = [
|
rt_packets = [
|
||||||
[0x12459970, 0x9938cdef, 0x12340000],
|
[0x12459970, 0x9938cdef, 0x12340000],
|
||||||
[0xabcdef00, 0x12345678],
|
[0xabcdef00, 0x12345678],
|
||||||
[0xeeeeeeee, 0xffffffff, 0x01020304, 0x11223344]
|
[0xeeeeeeee, 0xffffffff, 0x01020304, 0x11223344]
|
||||||
]
|
]
|
||||||
def transmit_rt_packets():
|
def transmit_rt_packets():
|
||||||
|
while not (yield dut.tx.link_init):
|
||||||
|
yield
|
||||||
|
while (yield dut.tx.link_init):
|
||||||
|
yield
|
||||||
|
|
||||||
for packet in rt_packets:
|
for packet in rt_packets:
|
||||||
yield dut.tx.rt_frame.eq(1)
|
yield dut.tx.rt_frame.eq(1)
|
||||||
for data in packet:
|
for data in packet:
|
||||||
|
@ -70,6 +77,11 @@ class TestLinkLayer(unittest.TestCase):
|
||||||
rx_rt_packets = []
|
rx_rt_packets = []
|
||||||
@passive
|
@passive
|
||||||
def receive_rt_packets():
|
def receive_rt_packets():
|
||||||
|
while not (yield dut.tx.link_init):
|
||||||
|
yield
|
||||||
|
while (yield dut.tx.link_init):
|
||||||
|
yield
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
packet = []
|
packet = []
|
||||||
rx_rt_packets.append(packet)
|
rx_rt_packets.append(packet)
|
||||||
|
@ -78,7 +90,9 @@ class TestLinkLayer(unittest.TestCase):
|
||||||
while (yield dut.rx.rt_frame):
|
while (yield dut.rx.rt_frame):
|
||||||
packet.append((yield dut.rx.rt_data))
|
packet.append((yield dut.rx.rt_data))
|
||||||
yield
|
yield
|
||||||
run_simulation(dut, [transmit_rt_packets(), receive_rt_packets()])
|
|
||||||
|
run_simulation(dut, [link_init(),
|
||||||
|
transmit_rt_packets(), receive_rt_packets()])
|
||||||
|
|
||||||
for packet in rx_rt_packets:
|
for packet in rx_rt_packets:
|
||||||
print(" ".join("{:08x}".format(x) for x in packet))
|
print(" ".join("{:08x}".format(x) for x in packet))
|
||||||
|
|
Loading…
Reference in New Issue