forked from M-Labs/artiq
serwb: new version using only sys/sys4x clocks domains, scrambling deactivated.
This commit is contained in:
parent
dd21c07b85
commit
73b727cade
|
@ -17,37 +17,37 @@ class SERWBCore(Module):
|
||||||
packetizer = Packetizer()
|
packetizer = Packetizer()
|
||||||
self.submodules += depacketizer, packetizer
|
self.submodules += depacketizer, packetizer
|
||||||
|
|
||||||
# clock domain crossing
|
# fifos
|
||||||
tx_cdc = stream.AsyncFIFO([("data", 32)], 16)
|
tx_fifo = stream.SyncFIFO([("data", 32)], 16)
|
||||||
tx_cdc = ClockDomainsRenamer({"write": "sys", "read": phy.cd})(tx_cdc)
|
rx_fifo = stream.SyncFIFO([("data", 32)], 16)
|
||||||
rx_cdc = stream.AsyncFIFO([("data", 32)], 16)
|
self.submodules += tx_fifo, rx_fifo
|
||||||
rx_cdc = ClockDomainsRenamer({"write": phy.cd, "read": "sys"})(rx_cdc)
|
|
||||||
self.submodules += tx_cdc, rx_cdc
|
|
||||||
|
|
||||||
# scrambling
|
# scrambling
|
||||||
scrambler = ClockDomainsRenamer(phy.cd)(Scrambler(enable=with_scrambling))
|
scrambler = Scrambler(enable=with_scrambling)
|
||||||
descrambler = ClockDomainsRenamer(phy.cd)(Descrambler(enable=with_scrambling))
|
descrambler = Descrambler(enable=with_scrambling)
|
||||||
self.submodules += scrambler, descrambler
|
self.submodules += scrambler, descrambler
|
||||||
|
|
||||||
# modules connection
|
# modules connection
|
||||||
self.comb += [
|
self.comb += [
|
||||||
# core --> phy
|
# core --> phy
|
||||||
packetizer.source.connect(tx_cdc.sink),
|
packetizer.source.connect(tx_fifo.sink),
|
||||||
tx_cdc.source.connect(scrambler.sink),
|
tx_fifo.source.connect(scrambler.sink),
|
||||||
If(phy.init.ready,
|
If(phy.init.ready,
|
||||||
If(scrambler.source.stb,
|
If(scrambler.source.valid,
|
||||||
phy.serdes.tx_k.eq(scrambler.source.k),
|
phy.serdes.tx_k.eq(scrambler.source.k),
|
||||||
phy.serdes.tx_d.eq(scrambler.source.d)
|
phy.serdes.tx_d.eq(scrambler.source.d)
|
||||||
),
|
),
|
||||||
scrambler.source.ack.eq(1)
|
scrambler.source.ready.eq(phy.serdes.tx_ce)
|
||||||
),
|
),
|
||||||
|
|
||||||
# phy --> core
|
# phy --> core
|
||||||
descrambler.sink.stb.eq(phy.init.ready),
|
If(phy.init.ready,
|
||||||
descrambler.sink.k.eq(phy.serdes.rx_k),
|
descrambler.sink.valid.eq(phy.serdes.rx_ce),
|
||||||
descrambler.sink.d.eq(phy.serdes.rx_d),
|
descrambler.sink.k.eq(phy.serdes.rx_k),
|
||||||
descrambler.source.connect(rx_cdc.sink),
|
descrambler.sink.d.eq(phy.serdes.rx_d)
|
||||||
rx_cdc.source.connect(depacketizer.sink),
|
),
|
||||||
|
descrambler.source.connect(rx_fifo.sink),
|
||||||
|
rx_fifo.source.connect(depacketizer.sink),
|
||||||
|
|
||||||
# etherbone <--> core
|
# etherbone <--> core
|
||||||
depacketizer.source.connect(etherbone.sink),
|
depacketizer.source.connect(etherbone.sink),
|
||||||
|
|
|
@ -1,18 +1,26 @@
|
||||||
from migen import *
|
from migen import *
|
||||||
from migen.genlib.resetsync import AsyncResetSynchronizer
|
|
||||||
from migen.genlib.cdc import MultiReg, PulseSynchronizer, Gearbox
|
|
||||||
from migen.genlib.misc import BitSlip
|
from migen.genlib.misc import BitSlip
|
||||||
|
from migen.genlib.misc import WaitTimer
|
||||||
|
|
||||||
|
from misoc.interconnect import stream
|
||||||
from misoc.cores.code_8b10b import Encoder, Decoder
|
from misoc.cores.code_8b10b import Encoder, Decoder
|
||||||
|
|
||||||
|
|
||||||
|
def K(x, y):
|
||||||
|
return (y << 5) | x
|
||||||
|
|
||||||
|
|
||||||
|
@ResetInserter()
|
||||||
class KUSSerdes(Module):
|
class KUSSerdes(Module):
|
||||||
def __init__(self, pads, mode="master"):
|
def __init__(self, pads, mode="master"):
|
||||||
if mode == "slave":
|
if mode == "slave":
|
||||||
self.refclk = Signal()
|
self.refclk = Signal()
|
||||||
|
|
||||||
|
self.tx_ce = Signal()
|
||||||
self.tx_k = Signal(4)
|
self.tx_k = Signal(4)
|
||||||
self.tx_d = Signal(32)
|
self.tx_d = Signal(32)
|
||||||
|
|
||||||
|
self.rx_ce = Signal()
|
||||||
self.rx_k = Signal(4)
|
self.rx_k = Signal(4)
|
||||||
self.rx_d = Signal(32)
|
self.rx_d = Signal(32)
|
||||||
|
|
||||||
|
@ -24,16 +32,14 @@ class KUSSerdes(Module):
|
||||||
self.rx_bitslip_value = Signal(6)
|
self.rx_bitslip_value = Signal(6)
|
||||||
self.rx_delay_rst = Signal()
|
self.rx_delay_rst = Signal()
|
||||||
self.rx_delay_inc = Signal()
|
self.rx_delay_inc = Signal()
|
||||||
self.rx_delay_ce = Signal()
|
|
||||||
self.rx_delay_en_vtc = Signal()
|
self.rx_delay_en_vtc = Signal()
|
||||||
|
|
||||||
# # #
|
# # #
|
||||||
|
|
||||||
self.submodules.encoder = ClockDomainsRenamer("sys0p2x")(
|
self.submodules.encoder = encoder = CEInserter()(Encoder(4, True))
|
||||||
Encoder(4, True))
|
self.comb += encoder.ce.eq(self.tx_ce)
|
||||||
self.decoders = [ClockDomainsRenamer("sys0p2x")(
|
self.submodules.decoders = decoders = [CEInserter()(Decoder(True)) for _ in range(4)]
|
||||||
Decoder(True)) for _ in range(4)]
|
self.comb += [decoders[i].ce.eq(self.rx_ce) for i in range(4)]
|
||||||
self.submodules += self.decoders
|
|
||||||
|
|
||||||
# clocking:
|
# clocking:
|
||||||
|
|
||||||
|
@ -42,53 +48,26 @@ class KUSSerdes(Module):
|
||||||
# In Slave mode:
|
# In Slave mode:
|
||||||
# - linerate/10 refclk provided by clk_pads
|
# - linerate/10 refclk provided by clk_pads
|
||||||
|
|
||||||
# control/status cdc
|
|
||||||
tx_idle = Signal()
|
|
||||||
tx_comma = Signal()
|
|
||||||
rx_idle = Signal()
|
|
||||||
rx_comma = Signal()
|
|
||||||
rx_bitslip_value = Signal(6)
|
|
||||||
rx_delay_rst = Signal()
|
|
||||||
rx_delay_inc = Signal()
|
|
||||||
rx_delay_en_vtc = Signal()
|
|
||||||
rx_delay_ce = Signal()
|
|
||||||
self.specials += [
|
|
||||||
MultiReg(self.tx_idle, tx_idle, "sys0p2x"),
|
|
||||||
MultiReg(self.tx_comma, tx_comma, "sys0p2x"),
|
|
||||||
MultiReg(rx_idle, self.rx_idle, "sys"),
|
|
||||||
MultiReg(rx_comma, self.rx_comma, "sys"),
|
|
||||||
MultiReg(self.rx_bitslip_value, rx_bitslip_value, "sys0p2x"),
|
|
||||||
MultiReg(self.rx_delay_inc, rx_delay_inc, "sys"),
|
|
||||||
MultiReg(self.rx_delay_en_vtc, rx_delay_en_vtc, "sys")
|
|
||||||
]
|
|
||||||
self.submodules.do_rx_delay_rst = PulseSynchronizer("sys", "sys")
|
|
||||||
self.comb += [
|
|
||||||
rx_delay_rst.eq(self.do_rx_delay_rst.o),
|
|
||||||
self.do_rx_delay_rst.i.eq(self.rx_delay_rst)
|
|
||||||
]
|
|
||||||
self.submodules.do_rx_delay_ce = PulseSynchronizer("sys", "sys")
|
|
||||||
self.comb += [
|
|
||||||
rx_delay_ce.eq(self.do_rx_delay_ce.o),
|
|
||||||
self.do_rx_delay_ce.i.eq(self.rx_delay_ce)
|
|
||||||
]
|
|
||||||
|
|
||||||
# tx clock (linerate/10)
|
# tx clock (linerate/10)
|
||||||
if mode == "master":
|
if mode == "master":
|
||||||
self.submodules.tx_clk_gearbox = Gearbox(40, "sys0p2x", 8, "sys")
|
clk_converter = stream.Converter(40, 8)
|
||||||
self.comb += self.tx_clk_gearbox.i.eq((0b1111100000 << 30) |
|
self.submodules += clk_converter
|
||||||
(0b1111100000 << 20) |
|
self.comb += [
|
||||||
(0b1111100000 << 10) |
|
clk_converter.sink.valid.eq(1),
|
||||||
(0b1111100000 << 0))
|
clk_converter.sink.data.eq(Replicate(Signal(10, reset=0b1111100000), 4)),
|
||||||
|
clk_converter.source.ready.eq(1)
|
||||||
|
]
|
||||||
clk_o = Signal()
|
clk_o = Signal()
|
||||||
self.specials += [
|
self.specials += [
|
||||||
Instance("OSERDESE3",
|
Instance("OSERDESE3",
|
||||||
p_DATA_WIDTH=8, p_INIT=0,
|
p_DATA_WIDTH=8, p_INIT=0,
|
||||||
p_IS_CLK_INVERTED=0, p_IS_CLKDIV_INVERTED=0, p_IS_RST_INVERTED=0,
|
p_IS_CLK_INVERTED=0, p_IS_CLKDIV_INVERTED=0,
|
||||||
|
p_IS_RST_INVERTED=0,
|
||||||
|
|
||||||
o_OQ=clk_o,
|
o_OQ=clk_o,
|
||||||
i_RST=ResetSignal("sys"),
|
i_RST=ResetSignal("sys"),
|
||||||
i_CLK=ClockSignal("sys4x"), i_CLKDIV=ClockSignal("sys"),
|
i_CLK=ClockSignal("sys4x"), i_CLKDIV=ClockSignal("sys"),
|
||||||
i_D=self.tx_clk_gearbox.o
|
i_D=clk_converter.source.data
|
||||||
),
|
),
|
||||||
Instance("OBUFDS",
|
Instance("OBUFDS",
|
||||||
i_I=clk_o,
|
i_I=clk_o,
|
||||||
|
@ -98,29 +77,32 @@ class KUSSerdes(Module):
|
||||||
]
|
]
|
||||||
|
|
||||||
# tx datapath
|
# tx datapath
|
||||||
# tx_data -> encoders -> gearbox -> serdes
|
# tx_data -> encoders -> converter -> serdes
|
||||||
self.submodules.tx_gearbox = Gearbox(40, "sys0p2x", 8, "sys")
|
self.submodules.tx_converter = tx_converter = stream.Converter(40, 8)
|
||||||
self.comb += [
|
self.comb += [
|
||||||
If(tx_comma,
|
tx_converter.sink.valid.eq(1),
|
||||||
self.encoder.k[0].eq(1),
|
self.tx_ce.eq(tx_converter.sink.ready),
|
||||||
self.encoder.d[0].eq(0xbc)
|
tx_converter.source.ready.eq(1),
|
||||||
|
If(self.tx_idle,
|
||||||
|
tx_converter.sink.data.eq(0)
|
||||||
).Else(
|
).Else(
|
||||||
self.encoder.k[0].eq(self.tx_k[0]),
|
tx_converter.sink.data.eq(
|
||||||
self.encoder.k[1].eq(self.tx_k[1]),
|
Cat(*[encoder.output[i] for i in range(4)]))
|
||||||
self.encoder.k[2].eq(self.tx_k[2]),
|
),
|
||||||
self.encoder.k[3].eq(self.tx_k[3]),
|
If(self.tx_comma,
|
||||||
self.encoder.d[0].eq(self.tx_d[0:8]),
|
encoder.k[0].eq(1),
|
||||||
self.encoder.d[1].eq(self.tx_d[8:16]),
|
encoder.d[0].eq(K(28,5)),
|
||||||
self.encoder.d[2].eq(self.tx_d[16:24]),
|
).Else(
|
||||||
self.encoder.d[3].eq(self.tx_d[24:32])
|
encoder.k[0].eq(self.tx_k[0]),
|
||||||
|
encoder.k[1].eq(self.tx_k[1]),
|
||||||
|
encoder.k[2].eq(self.tx_k[2]),
|
||||||
|
encoder.k[3].eq(self.tx_k[3]),
|
||||||
|
encoder.d[0].eq(self.tx_d[0:8]),
|
||||||
|
encoder.d[1].eq(self.tx_d[8:16]),
|
||||||
|
encoder.d[2].eq(self.tx_d[16:24]),
|
||||||
|
encoder.d[3].eq(self.tx_d[24:32])
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
self.sync.sys0p2x += \
|
|
||||||
If(tx_idle,
|
|
||||||
self.tx_gearbox.i.eq(0)
|
|
||||||
).Else(
|
|
||||||
self.tx_gearbox.i.eq(Cat(*[self.encoder.output[i] for i in range(4)]))
|
|
||||||
)
|
|
||||||
|
|
||||||
serdes_o = Signal()
|
serdes_o = Signal()
|
||||||
self.specials += [
|
self.specials += [
|
||||||
|
@ -131,7 +113,7 @@ class KUSSerdes(Module):
|
||||||
o_OQ=serdes_o,
|
o_OQ=serdes_o,
|
||||||
i_RST=ResetSignal("sys"),
|
i_RST=ResetSignal("sys"),
|
||||||
i_CLK=ClockSignal("sys4x"), i_CLKDIV=ClockSignal("sys"),
|
i_CLK=ClockSignal("sys4x"), i_CLKDIV=ClockSignal("sys"),
|
||||||
i_D=self.tx_gearbox.o
|
i_D=tx_converter.source.data
|
||||||
),
|
),
|
||||||
Instance("OBUFDS",
|
Instance("OBUFDS",
|
||||||
i_I=serdes_o,
|
i_I=serdes_o,
|
||||||
|
@ -163,9 +145,14 @@ class KUSSerdes(Module):
|
||||||
self.comb += self.refclk.eq(clk_i_bufg)
|
self.comb += self.refclk.eq(clk_i_bufg)
|
||||||
|
|
||||||
# rx datapath
|
# rx datapath
|
||||||
# serdes -> gearbox -> bitslip -> decoders -> rx_data
|
# serdes -> converter -> bitslip -> decoders -> rx_data
|
||||||
self.submodules.rx_gearbox = Gearbox(8, "sys", 40, "sys0p2x")
|
self.submodules.rx_converter = rx_converter = stream.Converter(8, 40)
|
||||||
self.submodules.rx_bitslip = ClockDomainsRenamer("sys0p2x")(BitSlip(40))
|
self.comb += [
|
||||||
|
self.rx_ce.eq(rx_converter.source.valid),
|
||||||
|
rx_converter.source.ready.eq(1)
|
||||||
|
]
|
||||||
|
self.submodules.rx_bitslip = rx_bitslip = CEInserter()(BitSlip(40))
|
||||||
|
self.comb += rx_bitslip.ce.eq(self.rx_ce)
|
||||||
|
|
||||||
serdes_i_nodelay = Signal()
|
serdes_i_nodelay = Signal()
|
||||||
self.specials += [
|
self.specials += [
|
||||||
|
@ -186,9 +173,9 @@ class KUSSerdes(Module):
|
||||||
p_DELAY_TYPE="VARIABLE", p_DELAY_VALUE=0,
|
p_DELAY_TYPE="VARIABLE", p_DELAY_VALUE=0,
|
||||||
|
|
||||||
i_CLK=ClockSignal("sys"),
|
i_CLK=ClockSignal("sys"),
|
||||||
i_RST=rx_delay_rst, i_LOAD=0,
|
i_RST=self.rx_delay_rst, i_LOAD=0,
|
||||||
i_INC=rx_delay_inc, i_EN_VTC=rx_delay_en_vtc,
|
i_INC=1, i_EN_VTC=self.rx_delay_en_vtc,
|
||||||
i_CE=rx_delay_ce,
|
i_CE=self.rx_delay_inc,
|
||||||
|
|
||||||
i_IDATAIN=serdes_i_nodelay, o_DATAOUT=serdes_i_delayed
|
i_IDATAIN=serdes_i_nodelay, o_DATAOUT=serdes_i_delayed
|
||||||
),
|
),
|
||||||
|
@ -208,19 +195,20 @@ class KUSSerdes(Module):
|
||||||
]
|
]
|
||||||
|
|
||||||
self.comb += [
|
self.comb += [
|
||||||
self.rx_gearbox.i.eq(serdes_q),
|
rx_converter.sink.valid.eq(1),
|
||||||
self.rx_bitslip.value.eq(rx_bitslip_value),
|
rx_converter.sink.data.eq(serdes_q),
|
||||||
self.rx_bitslip.i.eq(self.rx_gearbox.o),
|
rx_bitslip.value.eq(self.rx_bitslip_value),
|
||||||
self.decoders[0].input.eq(self.rx_bitslip.o[0:10]),
|
rx_bitslip.i.eq(rx_converter.source.data),
|
||||||
self.decoders[1].input.eq(self.rx_bitslip.o[10:20]),
|
decoders[0].input.eq(rx_bitslip.o[0:10]),
|
||||||
self.decoders[2].input.eq(self.rx_bitslip.o[20:30]),
|
decoders[1].input.eq(rx_bitslip.o[10:20]),
|
||||||
self.decoders[3].input.eq(self.rx_bitslip.o[30:40]),
|
decoders[2].input.eq(rx_bitslip.o[20:30]),
|
||||||
self.rx_k.eq(Cat(*[self.decoders[i].k for i in range(4)])),
|
decoders[3].input.eq(rx_bitslip.o[30:40]),
|
||||||
self.rx_d.eq(Cat(*[self.decoders[i].d for i in range(4)])),
|
self.rx_k.eq(Cat(*[decoders[i].k for i in range(4)])),
|
||||||
rx_idle.eq(self.rx_bitslip.o == 0),
|
self.rx_d.eq(Cat(*[decoders[i].d for i in range(4)])),
|
||||||
rx_comma.eq(((self.decoders[0].d == 0xbc) & (self.decoders[0].k == 1)) &
|
self.rx_comma.eq((decoders[0].k == 1) & (decoders[0].d == K(28,5)))
|
||||||
((self.decoders[1].d == 0x00) & (self.decoders[1].k == 0)) &
|
]
|
||||||
((self.decoders[2].d == 0x00) & (self.decoders[2].k == 0)) &
|
|
||||||
((self.decoders[3].d == 0x00) & (self.decoders[3].k == 0)))
|
|
||||||
|
|
||||||
]
|
idle_timer = WaitTimer(32)
|
||||||
|
self.submodules += idle_timer
|
||||||
|
self.comb += idle_timer.wait.eq(1)
|
||||||
|
self.sync += self.rx_idle.eq(idle_timer.done & (rx_bitslip.o == 0))
|
||||||
|
|
|
@ -14,11 +14,12 @@ from artiq.gateware.serwb.s7phy import S7Serdes
|
||||||
# 3) Slave sends K28.5 commas to allow Master to calibrate, Master sends K28.5 commas.
|
# 3) Slave sends K28.5 commas to allow Master to calibrate, Master sends K28.5 commas.
|
||||||
# 4) Master stops sending K28.5 commas.
|
# 4) Master stops sending K28.5 commas.
|
||||||
# 5) Slave stops sending K28.5 commas.
|
# 5) Slave stops sending K28.5 commas.
|
||||||
# 6) Link is ready.
|
# 6) Physical link is ready.
|
||||||
|
|
||||||
|
|
||||||
|
@ResetInserter()
|
||||||
class _SerdesMasterInit(Module):
|
class _SerdesMasterInit(Module):
|
||||||
def __init__(self, serdes, taps, timeout=4096):
|
def __init__(self, serdes, taps, timeout=2**14):
|
||||||
self.reset = Signal()
|
|
||||||
self.ready = Signal()
|
self.ready = Signal()
|
||||||
self.error = Signal()
|
self.error = Signal()
|
||||||
|
|
||||||
|
@ -31,14 +32,9 @@ class _SerdesMasterInit(Module):
|
||||||
self.delay_max_found = delay_max_found = Signal()
|
self.delay_max_found = delay_max_found = Signal()
|
||||||
self.bitslip = bitslip = Signal(max=40)
|
self.bitslip = bitslip = Signal(max=40)
|
||||||
|
|
||||||
timer = WaitTimer(timeout)
|
self.submodules.timer = timer = WaitTimer(timeout)
|
||||||
self.submodules += timer
|
|
||||||
|
|
||||||
self.submodules.fsm = fsm = ResetInserter()(FSM(reset_state="IDLE"))
|
|
||||||
self.comb += self.fsm.reset.eq(self.reset)
|
|
||||||
|
|
||||||
self.comb += serdes.rx_delay_inc.eq(1)
|
|
||||||
|
|
||||||
|
self.submodules.fsm = fsm = FSM(reset_state="IDLE")
|
||||||
fsm.act("IDLE",
|
fsm.act("IDLE",
|
||||||
NextValue(delay, 0),
|
NextValue(delay, 0),
|
||||||
NextValue(delay_min, 0),
|
NextValue(delay_min, 0),
|
||||||
|
@ -109,14 +105,12 @@ class _SerdesMasterInit(Module):
|
||||||
serdes.rx_delay_rst.eq(1)
|
serdes.rx_delay_rst.eq(1)
|
||||||
).Else(
|
).Else(
|
||||||
NextValue(delay, delay + 1),
|
NextValue(delay, delay + 1),
|
||||||
serdes.rx_delay_ce.eq(1)
|
serdes.rx_delay_inc.eq(1)
|
||||||
),
|
),
|
||||||
serdes.tx_comma.eq(1)
|
serdes.tx_comma.eq(1)
|
||||||
)
|
)
|
||||||
fsm.act("CHECK_SAMPLING_WINDOW",
|
fsm.act("CHECK_SAMPLING_WINDOW",
|
||||||
If((delay_min == 0) |
|
If((delay_max - delay_min) < taps//16,
|
||||||
(delay_max == (taps - 1)) |
|
|
||||||
((delay_max - delay_min) < taps//16),
|
|
||||||
NextValue(delay_min_found, 0),
|
NextValue(delay_min_found, 0),
|
||||||
NextValue(delay_max_found, 0),
|
NextValue(delay_max_found, 0),
|
||||||
NextState("WAIT_STABLE")
|
NextState("WAIT_STABLE")
|
||||||
|
@ -131,7 +125,6 @@ class _SerdesMasterInit(Module):
|
||||||
).Else(
|
).Else(
|
||||||
NextValue(delay, delay + 1),
|
NextValue(delay, delay + 1),
|
||||||
serdes.rx_delay_inc.eq(1),
|
serdes.rx_delay_inc.eq(1),
|
||||||
serdes.rx_delay_ce.eq(1),
|
|
||||||
NextState("WAIT_SAMPLING_WINDOW")
|
NextState("WAIT_SAMPLING_WINDOW")
|
||||||
),
|
),
|
||||||
serdes.tx_comma.eq(1)
|
serdes.tx_comma.eq(1)
|
||||||
|
@ -147,13 +140,16 @@ class _SerdesMasterInit(Module):
|
||||||
fsm.act("READY",
|
fsm.act("READY",
|
||||||
self.ready.eq(1)
|
self.ready.eq(1)
|
||||||
)
|
)
|
||||||
|
if hasattr(serdes, "rx_delay_en_vtc"):
|
||||||
|
self.comb += serdes.rx_delay_en_vtc.eq(self.ready)
|
||||||
fsm.act("ERROR",
|
fsm.act("ERROR",
|
||||||
self.error.eq(1)
|
self.error.eq(1)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ResetInserter()
|
||||||
class _SerdesSlaveInit(Module, AutoCSR):
|
class _SerdesSlaveInit(Module, AutoCSR):
|
||||||
def __init__(self, serdes, taps, timeout=4096):
|
def __init__(self, serdes, taps, timeout=2**14):
|
||||||
self.ready = Signal()
|
self.ready = Signal()
|
||||||
self.error = Signal()
|
self.error = Signal()
|
||||||
|
|
||||||
|
@ -166,13 +162,10 @@ class _SerdesSlaveInit(Module, AutoCSR):
|
||||||
self.delay_max_found = delay_max_found = Signal()
|
self.delay_max_found = delay_max_found = Signal()
|
||||||
self.bitslip = bitslip = Signal(max=40)
|
self.bitslip = bitslip = Signal(max=40)
|
||||||
|
|
||||||
timer = WaitTimer(timeout)
|
self.submodules.timer = timer = WaitTimer(timeout)
|
||||||
self.submodules += timer
|
|
||||||
|
|
||||||
self.comb += serdes.rx_delay_inc.eq(1)
|
self.submodules.fsm = fsm = FSM(reset_state="IDLE")
|
||||||
|
# reset
|
||||||
self.submodules.fsm = fsm = ResetInserter()(FSM(reset_state="IDLE"))
|
|
||||||
self.comb += fsm.reset.eq(serdes.rx_idle)
|
|
||||||
fsm.act("IDLE",
|
fsm.act("IDLE",
|
||||||
NextValue(delay, 0),
|
NextValue(delay, 0),
|
||||||
NextValue(delay_min, 0),
|
NextValue(delay_min, 0),
|
||||||
|
@ -181,7 +174,11 @@ class _SerdesSlaveInit(Module, AutoCSR):
|
||||||
NextValue(delay_max_found, 0),
|
NextValue(delay_max_found, 0),
|
||||||
serdes.rx_delay_rst.eq(1),
|
serdes.rx_delay_rst.eq(1),
|
||||||
NextValue(bitslip, 0),
|
NextValue(bitslip, 0),
|
||||||
NextState("WAIT_STABLE"),
|
timer.wait.eq(1),
|
||||||
|
If(timer.done,
|
||||||
|
timer.wait.eq(0),
|
||||||
|
NextState("WAIT_STABLE"),
|
||||||
|
),
|
||||||
serdes.tx_idle.eq(1)
|
serdes.tx_idle.eq(1)
|
||||||
)
|
)
|
||||||
fsm.act("WAIT_STABLE",
|
fsm.act("WAIT_STABLE",
|
||||||
|
@ -229,14 +226,12 @@ class _SerdesSlaveInit(Module, AutoCSR):
|
||||||
serdes.rx_delay_rst.eq(1)
|
serdes.rx_delay_rst.eq(1)
|
||||||
).Else(
|
).Else(
|
||||||
NextValue(delay, delay + 1),
|
NextValue(delay, delay + 1),
|
||||||
serdes.rx_delay_ce.eq(1)
|
serdes.rx_delay_inc.eq(1)
|
||||||
),
|
),
|
||||||
serdes.tx_idle.eq(1)
|
serdes.tx_idle.eq(1)
|
||||||
)
|
)
|
||||||
fsm.act("CHECK_SAMPLING_WINDOW",
|
fsm.act("CHECK_SAMPLING_WINDOW",
|
||||||
If((delay_min == 0) |
|
If((delay_max - delay_min) < taps//16,
|
||||||
(delay_max == (taps - 1)) |
|
|
||||||
((delay_max - delay_min) < taps//16),
|
|
||||||
NextValue(delay_min_found, 0),
|
NextValue(delay_min_found, 0),
|
||||||
NextValue(delay_max_found, 0),
|
NextValue(delay_max_found, 0),
|
||||||
NextState("WAIT_STABLE")
|
NextState("WAIT_STABLE")
|
||||||
|
@ -251,7 +246,6 @@ class _SerdesSlaveInit(Module, AutoCSR):
|
||||||
).Else(
|
).Else(
|
||||||
NextValue(delay, delay + 1),
|
NextValue(delay, delay + 1),
|
||||||
serdes.rx_delay_inc.eq(1),
|
serdes.rx_delay_inc.eq(1),
|
||||||
serdes.rx_delay_ce.eq(1),
|
|
||||||
NextState("WAIT_SAMPLING_WINDOW")
|
NextState("WAIT_SAMPLING_WINDOW")
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
@ -274,13 +268,15 @@ class _SerdesSlaveInit(Module, AutoCSR):
|
||||||
fsm.act("READY",
|
fsm.act("READY",
|
||||||
self.ready.eq(1)
|
self.ready.eq(1)
|
||||||
)
|
)
|
||||||
|
if hasattr(serdes, "rx_delay_en_vtc"):
|
||||||
|
self.comb += serdes.rx_delay_en_vtc.eq(self.ready)
|
||||||
fsm.act("ERROR",
|
fsm.act("ERROR",
|
||||||
self.error.eq(1)
|
self.error.eq(1)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class _SerdesControl(Module, AutoCSR):
|
class _SerdesControl(Module, AutoCSR):
|
||||||
def __init__(self, init, mode="master"):
|
def __init__(self, serdes, init, mode="master"):
|
||||||
if mode == "master":
|
if mode == "master":
|
||||||
self.reset = CSR()
|
self.reset = CSR()
|
||||||
self.ready = CSRStatus()
|
self.ready = CSRStatus()
|
||||||
|
@ -296,7 +292,18 @@ class _SerdesControl(Module, AutoCSR):
|
||||||
# # #
|
# # #
|
||||||
|
|
||||||
if mode == "master":
|
if mode == "master":
|
||||||
|
# In Master mode, reset is coming from CSR,
|
||||||
|
# it resets the Master that will also reset
|
||||||
|
# the Slave by putting the link in idle.
|
||||||
self.comb += init.reset.eq(self.reset.re)
|
self.comb += init.reset.eq(self.reset.re)
|
||||||
|
else:
|
||||||
|
# In Slave mode, reset is coming from link,
|
||||||
|
# Master reset the Slave by putting the link
|
||||||
|
# in idle.
|
||||||
|
self.comb += [
|
||||||
|
init.reset.eq(serdes.rx_idle),
|
||||||
|
serdes.reset.eq(serdes.rx_idle)
|
||||||
|
]
|
||||||
self.comb += [
|
self.comb += [
|
||||||
self.ready.status.eq(init.ready),
|
self.ready.status.eq(init.ready),
|
||||||
self.error.status.eq(init.error),
|
self.error.status.eq(init.error),
|
||||||
|
@ -310,7 +317,6 @@ class _SerdesControl(Module, AutoCSR):
|
||||||
|
|
||||||
|
|
||||||
class SERWBPHY(Module, AutoCSR):
|
class SERWBPHY(Module, AutoCSR):
|
||||||
cd = "sys0p2x"
|
|
||||||
def __init__(self, device, pads, mode="master"):
|
def __init__(self, device, pads, mode="master"):
|
||||||
assert mode in ["master", "slave"]
|
assert mode in ["master", "slave"]
|
||||||
if device[:4] == "xcku":
|
if device[:4] == "xcku":
|
||||||
|
@ -325,4 +331,4 @@ class SERWBPHY(Module, AutoCSR):
|
||||||
self.submodules.init = _SerdesMasterInit(self.serdes, taps)
|
self.submodules.init = _SerdesMasterInit(self.serdes, taps)
|
||||||
else:
|
else:
|
||||||
self.submodules.init = _SerdesSlaveInit(self.serdes, taps)
|
self.submodules.init = _SerdesSlaveInit(self.serdes, taps)
|
||||||
self.submodules.control = _SerdesControl(self.init, mode)
|
self.submodules.control = _SerdesControl(self.serdes, self.init, mode)
|
||||||
|
|
|
@ -1,18 +1,26 @@
|
||||||
from migen import *
|
from migen import *
|
||||||
from migen.genlib.resetsync import AsyncResetSynchronizer
|
|
||||||
from migen.genlib.cdc import MultiReg, Gearbox
|
|
||||||
from migen.genlib.misc import BitSlip
|
from migen.genlib.misc import BitSlip
|
||||||
|
from migen.genlib.misc import WaitTimer
|
||||||
|
|
||||||
|
from misoc.interconnect import stream
|
||||||
from misoc.cores.code_8b10b import Encoder, Decoder
|
from misoc.cores.code_8b10b import Encoder, Decoder
|
||||||
|
|
||||||
|
|
||||||
|
def K(x, y):
|
||||||
|
return (y << 5) | x
|
||||||
|
|
||||||
|
|
||||||
|
@ResetInserter()
|
||||||
class S7Serdes(Module):
|
class S7Serdes(Module):
|
||||||
def __init__(self, pads, mode="master"):
|
def __init__(self, pads, mode="master"):
|
||||||
if mode == "slave":
|
if mode == "slave":
|
||||||
self.refclk = Signal()
|
self.refclk = Signal()
|
||||||
|
|
||||||
|
self.tx_ce = Signal()
|
||||||
self.tx_k = Signal(4)
|
self.tx_k = Signal(4)
|
||||||
self.tx_d = Signal(32)
|
self.tx_d = Signal(32)
|
||||||
|
|
||||||
|
self.rx_ce = Signal()
|
||||||
self.rx_k = Signal(4)
|
self.rx_k = Signal(4)
|
||||||
self.rx_d = Signal(32)
|
self.rx_d = Signal(32)
|
||||||
|
|
||||||
|
@ -24,44 +32,30 @@ class S7Serdes(Module):
|
||||||
self.rx_bitslip_value = Signal(6)
|
self.rx_bitslip_value = Signal(6)
|
||||||
self.rx_delay_rst = Signal()
|
self.rx_delay_rst = Signal()
|
||||||
self.rx_delay_inc = Signal()
|
self.rx_delay_inc = Signal()
|
||||||
self.rx_delay_ce = Signal()
|
|
||||||
|
|
||||||
# # #
|
# # #
|
||||||
|
|
||||||
self.submodules.encoder = ClockDomainsRenamer("sys0p2x")(
|
self.submodules.encoder = encoder = CEInserter()(Encoder(4, True))
|
||||||
Encoder(4, True))
|
self.comb += encoder.ce.eq(self.tx_ce)
|
||||||
self.decoders = [ClockDomainsRenamer("sys0p2x")(
|
self.submodules.decoders = decoders = [CEInserter()(Decoder(True)) for _ in range(4)]
|
||||||
Decoder(True)) for _ in range(4)]
|
self.comb += [decoders[i].ce.eq(self.rx_ce) for i in range(4)]
|
||||||
self.submodules += self.decoders
|
|
||||||
|
|
||||||
# clocking:
|
# clocking:
|
||||||
|
|
||||||
# In master mode:
|
# In Master mode:
|
||||||
# - linerate/10 slave refclk generated on clk_pads
|
# - linerate/10 refclk is generated on clk_pads
|
||||||
# In Slave mode:
|
# In Slave mode:
|
||||||
# - linerate/10 refclk provided by clk_pads
|
# - linerate/10 refclk is provided by clk_pads
|
||||||
|
|
||||||
# control/status cdc
|
|
||||||
tx_idle = Signal()
|
|
||||||
tx_comma = Signal()
|
|
||||||
rx_idle = Signal()
|
|
||||||
rx_comma = Signal()
|
|
||||||
rx_bitslip_value = Signal(6)
|
|
||||||
self.specials += [
|
|
||||||
MultiReg(self.tx_idle, tx_idle, "sys0p2x"),
|
|
||||||
MultiReg(self.tx_comma, tx_comma, "sys0p2x"),
|
|
||||||
MultiReg(rx_idle, self.rx_idle, "sys"),
|
|
||||||
MultiReg(rx_comma, self.rx_comma, "sys")
|
|
||||||
]
|
|
||||||
self.specials += MultiReg(self.rx_bitslip_value, rx_bitslip_value, "sys0p2x"),
|
|
||||||
|
|
||||||
# tx clock (linerate/10)
|
# tx clock (linerate/10)
|
||||||
if mode == "master":
|
if mode == "master":
|
||||||
self.submodules.tx_clk_gearbox = Gearbox(40, "sys0p2x", 8, "sys")
|
clk_converter = stream.Converter(40, 8)
|
||||||
self.comb += self.tx_clk_gearbox.i.eq((0b1111100000 << 30) |
|
self.submodules += clk_converter
|
||||||
(0b1111100000 << 20) |
|
self.comb += [
|
||||||
(0b1111100000 << 10) |
|
clk_converter.sink.valid.eq(1),
|
||||||
(0b1111100000 << 0))
|
clk_converter.sink.data.eq(Replicate(Signal(10, reset=0b1111100000), 4)),
|
||||||
|
clk_converter.source.ready.eq(1)
|
||||||
|
]
|
||||||
clk_o = Signal()
|
clk_o = Signal()
|
||||||
self.specials += [
|
self.specials += [
|
||||||
Instance("OSERDESE2",
|
Instance("OSERDESE2",
|
||||||
|
@ -73,10 +67,10 @@ class S7Serdes(Module):
|
||||||
i_OCE=1,
|
i_OCE=1,
|
||||||
i_RST=ResetSignal("sys"),
|
i_RST=ResetSignal("sys"),
|
||||||
i_CLK=ClockSignal("sys4x"), i_CLKDIV=ClockSignal("sys"),
|
i_CLK=ClockSignal("sys4x"), i_CLKDIV=ClockSignal("sys"),
|
||||||
i_D1=self.tx_clk_gearbox.o[0], i_D2=self.tx_clk_gearbox.o[1],
|
i_D1=clk_converter.source.data[0], i_D2=clk_converter.source.data[1],
|
||||||
i_D3=self.tx_clk_gearbox.o[2], i_D4=self.tx_clk_gearbox.o[3],
|
i_D3=clk_converter.source.data[2], i_D4=clk_converter.source.data[3],
|
||||||
i_D5=self.tx_clk_gearbox.o[4], i_D6=self.tx_clk_gearbox.o[5],
|
i_D5=clk_converter.source.data[4], i_D6=clk_converter.source.data[5],
|
||||||
i_D7=self.tx_clk_gearbox.o[6], i_D8=self.tx_clk_gearbox.o[7]
|
i_D7=clk_converter.source.data[6], i_D8=clk_converter.source.data[7]
|
||||||
),
|
),
|
||||||
Instance("OBUFDS",
|
Instance("OBUFDS",
|
||||||
i_I=clk_o,
|
i_I=clk_o,
|
||||||
|
@ -86,29 +80,32 @@ class S7Serdes(Module):
|
||||||
]
|
]
|
||||||
|
|
||||||
# tx datapath
|
# tx datapath
|
||||||
# tx_data -> encoders -> gearbox -> serdes
|
# tx_data -> encoders -> converter -> serdes
|
||||||
self.submodules.tx_gearbox = Gearbox(40, "sys0p2x", 8, "sys")
|
self.submodules.tx_converter = tx_converter = stream.Converter(40, 8)
|
||||||
self.comb += [
|
self.comb += [
|
||||||
If(tx_comma,
|
tx_converter.sink.valid.eq(1),
|
||||||
self.encoder.k[0].eq(1),
|
self.tx_ce.eq(tx_converter.sink.ready),
|
||||||
self.encoder.d[0].eq(0xbc)
|
tx_converter.source.ready.eq(1),
|
||||||
|
If(self.tx_idle,
|
||||||
|
tx_converter.sink.data.eq(0)
|
||||||
).Else(
|
).Else(
|
||||||
self.encoder.k[0].eq(self.tx_k[0]),
|
tx_converter.sink.data.eq(
|
||||||
self.encoder.k[1].eq(self.tx_k[1]),
|
Cat(*[encoder.output[i] for i in range(4)]))
|
||||||
self.encoder.k[2].eq(self.tx_k[2]),
|
),
|
||||||
self.encoder.k[3].eq(self.tx_k[3]),
|
If(self.tx_comma,
|
||||||
self.encoder.d[0].eq(self.tx_d[0:8]),
|
encoder.k[0].eq(1),
|
||||||
self.encoder.d[1].eq(self.tx_d[8:16]),
|
encoder.d[0].eq(K(28,5)),
|
||||||
self.encoder.d[2].eq(self.tx_d[16:24]),
|
).Else(
|
||||||
self.encoder.d[3].eq(self.tx_d[24:32])
|
encoder.k[0].eq(self.tx_k[0]),
|
||||||
|
encoder.k[1].eq(self.tx_k[1]),
|
||||||
|
encoder.k[2].eq(self.tx_k[2]),
|
||||||
|
encoder.k[3].eq(self.tx_k[3]),
|
||||||
|
encoder.d[0].eq(self.tx_d[0:8]),
|
||||||
|
encoder.d[1].eq(self.tx_d[8:16]),
|
||||||
|
encoder.d[2].eq(self.tx_d[16:24]),
|
||||||
|
encoder.d[3].eq(self.tx_d[24:32])
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
self.sync.sys0p2x += \
|
|
||||||
If(tx_idle,
|
|
||||||
self.tx_gearbox.i.eq(0)
|
|
||||||
).Else(
|
|
||||||
self.tx_gearbox.i.eq(Cat(*[self.encoder.output[i] for i in range(4)]))
|
|
||||||
)
|
|
||||||
|
|
||||||
serdes_o = Signal()
|
serdes_o = Signal()
|
||||||
self.specials += [
|
self.specials += [
|
||||||
|
@ -121,10 +118,10 @@ class S7Serdes(Module):
|
||||||
i_OCE=1,
|
i_OCE=1,
|
||||||
i_RST=ResetSignal("sys"),
|
i_RST=ResetSignal("sys"),
|
||||||
i_CLK=ClockSignal("sys4x"), i_CLKDIV=ClockSignal("sys"),
|
i_CLK=ClockSignal("sys4x"), i_CLKDIV=ClockSignal("sys"),
|
||||||
i_D1=self.tx_gearbox.o[0], i_D2=self.tx_gearbox.o[1],
|
i_D1=tx_converter.source.data[0], i_D2=tx_converter.source.data[1],
|
||||||
i_D3=self.tx_gearbox.o[2], i_D4=self.tx_gearbox.o[3],
|
i_D3=tx_converter.source.data[2], i_D4=tx_converter.source.data[3],
|
||||||
i_D5=self.tx_gearbox.o[4], i_D6=self.tx_gearbox.o[5],
|
i_D5=tx_converter.source.data[4], i_D6=tx_converter.source.data[5],
|
||||||
i_D7=self.tx_gearbox.o[6], i_D8=self.tx_gearbox.o[7]
|
i_D7=tx_converter.source.data[6], i_D8=tx_converter.source.data[7]
|
||||||
),
|
),
|
||||||
Instance("OBUFDS",
|
Instance("OBUFDS",
|
||||||
i_I=serdes_o,
|
i_I=serdes_o,
|
||||||
|
@ -156,9 +153,14 @@ class S7Serdes(Module):
|
||||||
self.comb += self.refclk.eq(clk_i_bufg)
|
self.comb += self.refclk.eq(clk_i_bufg)
|
||||||
|
|
||||||
# rx datapath
|
# rx datapath
|
||||||
# serdes -> gearbox -> bitslip -> decoders -> rx_data
|
# serdes -> converter -> bitslip -> decoders -> rx_data
|
||||||
self.submodules.rx_gearbox = Gearbox(8, "sys", 40, "sys0p2x")
|
self.submodules.rx_converter = rx_converter = stream.Converter(8, 40)
|
||||||
self.submodules.rx_bitslip = ClockDomainsRenamer("sys0p2x")(BitSlip(40))
|
self.comb += [
|
||||||
|
self.rx_ce.eq(rx_converter.source.valid),
|
||||||
|
rx_converter.source.ready.eq(1)
|
||||||
|
]
|
||||||
|
self.submodules.rx_bitslip = rx_bitslip = CEInserter()(BitSlip(40))
|
||||||
|
self.comb += rx_bitslip.ce.eq(self.rx_ce)
|
||||||
|
|
||||||
serdes_i_nodelay = Signal()
|
serdes_i_nodelay = Signal()
|
||||||
self.specials += [
|
self.specials += [
|
||||||
|
@ -180,8 +182,8 @@ class S7Serdes(Module):
|
||||||
|
|
||||||
i_C=ClockSignal(),
|
i_C=ClockSignal(),
|
||||||
i_LD=self.rx_delay_rst,
|
i_LD=self.rx_delay_rst,
|
||||||
i_CE=self.rx_delay_ce,
|
i_CE=self.rx_delay_inc,
|
||||||
i_LDPIPEEN=0, i_INC=self.rx_delay_inc,
|
i_LDPIPEEN=0, i_INC=1,
|
||||||
|
|
||||||
i_IDATAIN=serdes_i_nodelay, o_DATAOUT=serdes_i_delayed
|
i_IDATAIN=serdes_i_nodelay, o_DATAOUT=serdes_i_delayed
|
||||||
),
|
),
|
||||||
|
@ -204,19 +206,20 @@ class S7Serdes(Module):
|
||||||
]
|
]
|
||||||
|
|
||||||
self.comb += [
|
self.comb += [
|
||||||
self.rx_gearbox.i.eq(serdes_q),
|
rx_converter.sink.valid.eq(1),
|
||||||
self.rx_bitslip.value.eq(rx_bitslip_value),
|
rx_converter.sink.data.eq(serdes_q),
|
||||||
self.rx_bitslip.i.eq(self.rx_gearbox.o),
|
rx_bitslip.value.eq(self.rx_bitslip_value),
|
||||||
self.decoders[0].input.eq(self.rx_bitslip.o[0:10]),
|
rx_bitslip.i.eq(rx_converter.source.data),
|
||||||
self.decoders[1].input.eq(self.rx_bitslip.o[10:20]),
|
decoders[0].input.eq(rx_bitslip.o[0:10]),
|
||||||
self.decoders[2].input.eq(self.rx_bitslip.o[20:30]),
|
decoders[1].input.eq(rx_bitslip.o[10:20]),
|
||||||
self.decoders[3].input.eq(self.rx_bitslip.o[30:40]),
|
decoders[2].input.eq(rx_bitslip.o[20:30]),
|
||||||
self.rx_k.eq(Cat(*[self.decoders[i].k for i in range(4)])),
|
decoders[3].input.eq(rx_bitslip.o[30:40]),
|
||||||
self.rx_d.eq(Cat(*[self.decoders[i].d for i in range(4)])),
|
self.rx_k.eq(Cat(*[decoders[i].k for i in range(4)])),
|
||||||
rx_idle.eq(self.rx_bitslip.o == 0),
|
self.rx_d.eq(Cat(*[decoders[i].d for i in range(4)])),
|
||||||
rx_comma.eq(((self.decoders[0].d == 0xbc) & (self.decoders[0].k == 1)) &
|
self.rx_comma.eq((decoders[0].k == 1) & (decoders[0].d == K(28,5)))
|
||||||
((self.decoders[1].d == 0x00) & (self.decoders[1].k == 0)) &
|
]
|
||||||
((self.decoders[2].d == 0x00) & (self.decoders[2].k == 0)) &
|
|
||||||
((self.decoders[3].d == 0x00) & (self.decoders[3].k == 0)))
|
|
||||||
|
|
||||||
]
|
idle_timer = WaitTimer(32)
|
||||||
|
self.submodules += idle_timer
|
||||||
|
self.comb += idle_timer.wait.eq(1)
|
||||||
|
self.sync += self.rx_idle.eq(idle_timer.done & (rx_bitslip.o == 0))
|
||||||
|
|
|
@ -174,7 +174,7 @@ class Standalone(MiniSoC, AMPSoC):
|
||||||
self.submodules.serwb_phy_amc = serwb_phy_amc
|
self.submodules.serwb_phy_amc = serwb_phy_amc
|
||||||
self.csr_devices.append("serwb_phy_amc")
|
self.csr_devices.append("serwb_phy_amc")
|
||||||
|
|
||||||
serwb_core = serwb.core.SERWBCore(serwb_phy_amc, int(self.clk_freq), mode="slave", with_scrambling=True)
|
serwb_core = serwb.core.SERWBCore(serwb_phy_amc, int(self.clk_freq), mode="slave", with_scrambling=False)
|
||||||
self.submodules += serwb_core
|
self.submodules += serwb_core
|
||||||
self.add_wb_slave(self.mem_map["serwb"], 8192, serwb_core.etherbone.wishbone.bus)
|
self.add_wb_slave(self.mem_map["serwb"], 8192, serwb_core.etherbone.wishbone.bus)
|
||||||
|
|
||||||
|
|
|
@ -168,7 +168,7 @@ class SaymaRTM(Module):
|
||||||
self.comb += self.crg.serwb_refclk.eq(serwb_phy_rtm.serdes.refclk)
|
self.comb += self.crg.serwb_refclk.eq(serwb_phy_rtm.serdes.refclk)
|
||||||
csr_devices.append("serwb_phy_rtm")
|
csr_devices.append("serwb_phy_rtm")
|
||||||
|
|
||||||
serwb_core = serwb.core.SERWBCore(serwb_phy_rtm, int(clk_freq), mode="master", with_scrambling=True)
|
serwb_core = serwb.core.SERWBCore(serwb_phy_rtm, int(clk_freq), mode="master", with_scrambling=False)
|
||||||
self.submodules += serwb_core
|
self.submodules += serwb_core
|
||||||
|
|
||||||
# process CSR devices and connect them to serwb
|
# process CSR devices and connect them to serwb
|
||||||
|
|
Loading…
Reference in New Issue