Skip to content

Commit 7c9248b

Browse files
committed
serwb/s7serdes: Implement Width Expansion
1 parent 3fe0317 commit 7c9248b

File tree

1 file changed

+95
-5
lines changed

1 file changed

+95
-5
lines changed

liteiclink/serwb/s7serdes.py

Lines changed: 95 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,15 @@
2020

2121
class _S7SerdesClocking(LiteXModule):
2222
def __init__(self, pads, mode="master", data_width=8):
23-
assert data_width in [4,6,8] # valid serdese2 ddr rates
23+
assert data_width in [4,6,8,10,14] # valid serdese2 ddr rates
24+
if data_width>=10:
25+
assert hasattr(pads, "tx_p"), "Width expansion can only be used for differential outputs"
2426
self.refclk = Signal()
2527

2628
# # #
2729

30+
master_shiftin1 = Signal()
31+
master_shiftin2 = Signal()
2832
# Master Mode.
2933
# ------------
3034
# Generate the linerate/10 clock. Slave will re-multiply it.
@@ -47,10 +51,34 @@ def __init__(self, pads, mode="master", data_width=8):
4751
i_RST = ResetSignal("sys"),
4852
i_CLK = ClockSignal(f"sys{data_width//2}x"),
4953
i_CLKDIV = ClockSignal("sys"),
50-
**{f"i_D{i+1}" : converter.source.data[i] for i in range(data_width)},
54+
**{f"i_D{i+1}" : converter.source.data[i] for i in range(min(data_width,8))},
55+
i_SHIFTIN1 = master_shiftin1,
56+
i_SHIFTIN2 = master_shiftin2,
5157
o_OQ = self.refclk,
5258
)
5359
]
60+
if data_width>=10:
61+
slave_shiftout1 = Signal()
62+
slave_shiftout2 = Signal()
63+
self.specials += [
64+
Instance("OSERDESE2",
65+
p_DATA_WIDTH = data_width,
66+
p_TRISTATE_WIDTH = 1,
67+
p_DATA_RATE_OQ = "DDR",
68+
p_DATA_RATE_TQ = "BUF",
69+
p_SERDES_MODE = "SLAVE",
70+
71+
i_OCE = 1,
72+
i_RST = ResetSignal("sys"),
73+
i_CLK = ClockSignal(f"sys{data_width//2}x"),
74+
i_CLKDIV = ClockSignal("sys"),
75+
**{f"i_D{i+3}" : converter.source.data[i+8] for i in range(data_width-8)}, #d3-d8 see UG471:168
76+
o_SHIFTOUT1 = slave_shiftout1,
77+
o_SHIFTOUT2 = slave_shiftout2,
78+
)
79+
]
80+
self.comb += [master_shiftin1.eq(slave_shiftout1),
81+
master_shiftin2.eq(slave_shiftout2)]
5482
if hasattr(pads, "clk_p"):
5583
self.specials += DifferentialOutput(self.refclk, pads.clk_p, pads.clk_n)
5684
else:
@@ -69,7 +97,10 @@ def __init__(self, pads, mode="master", data_width=8):
6997

7098
class _S7SerdesTX(LiteXModule):
7199
def __init__(self, pads, data_width=8):
72-
assert data_width in [4,6,8] # valid serdese2 ddr rates
100+
assert data_width in [4,6,8,10,14] # valid serdese2 ddr rates
101+
if data_width>=10:
102+
assert hasattr(pads, "tx_p"), "Width expansion can only be used for differential outputs"
103+
73104
# Control
74105
self.idle = idle = Signal()
75106
self.comma = comma = Signal()
@@ -94,6 +125,8 @@ def __init__(self, pads, data_width=8):
94125
# -----------------------------
95126
self.data = data = Signal(data_width)
96127
data_serialized = Signal()
128+
master_shiftin1 = Signal()
129+
master_shiftin2 = Signal()
97130
self.comb += data.eq(datapath.source.data)
98131
self.specials += [
99132
Instance("OSERDESE2",
@@ -107,10 +140,35 @@ def __init__(self, pads, data_width=8):
107140
i_RST = ResetSignal("sys"),
108141
i_CLK = ClockSignal(f"sys{data_width//2}x"),
109142
i_CLKDIV = ClockSignal("sys"),
110-
**{f"i_D{i+1}" : data[i] for i in range(data_width)},
143+
**{f"i_D{i+1}" : data[i] for i in range(min(data_width,8))},
144+
i_SHIFTIN1 = master_shiftin1,
145+
i_SHIFTIN2 = master_shiftin2,
111146
o_OQ = data_serialized,
112147
)
113148
]
149+
if data_width>=10:
150+
slave_shiftout1 = Signal()
151+
slave_shiftout2 = Signal()
152+
self.specials += [
153+
Instance("OSERDESE2",
154+
p_DATA_WIDTH = data_width,
155+
p_TRISTATE_WIDTH = 1,
156+
p_DATA_RATE_OQ = "DDR",
157+
p_DATA_RATE_TQ = "BUF",
158+
p_SERDES_MODE = "SLAVE",
159+
160+
i_OCE = 1,
161+
i_RST = ResetSignal("sys"),
162+
i_CLK = ClockSignal(f"sys{data_width//2}x"),
163+
i_CLKDIV = ClockSignal("sys"),
164+
**{f"i_D{i+3}" : data[i+8] for i in range(data_width-8)}, #d3-d8 see UG471:168
165+
o_SHIFTOUT1 = slave_shiftout1,
166+
o_SHIFTOUT2 = slave_shiftout2,
167+
)
168+
]
169+
self.comb += [master_shiftin1.eq(slave_shiftout1),
170+
master_shiftin2.eq(slave_shiftout2)]
171+
114172
if hasattr(pads, "tx_p"):
115173
self.specials += DifferentialOutput(data_serialized, pads.tx_p, pads.tx_n)
116174
else:
@@ -121,6 +179,8 @@ def __init__(self, pads, data_width=8):
121179
class _S7SerdesRX(LiteXModule):
122180
def __init__(self, pads, data_width=8):
123181
assert data_width in [4,6,8] # valid serdese2 ddr rates
182+
if data_width>=10:
183+
assert hasattr(pads, "rx_p"), "Width expansion can only be used for differential outputs"
124184
# Control.
125185
self.delay_rst = delay_rst = Signal()
126186
self.delay_inc = delay_inc = Signal()
@@ -142,6 +202,8 @@ def __init__(self, pads, data_width=8):
142202
# ----------------------------
143203
data_nodelay = Signal()
144204
data_delayed = Signal()
205+
master_shiftout1 = Signal()
206+
master_shiftout2 = Signal()
145207
self.data = data = Signal(data_width)
146208

147209
if hasattr(pads, "rx_p"):
@@ -183,9 +245,37 @@ def __init__(self, pads, data_width=8):
183245
i_CLKB =~ClockSignal(f"sys{data_width//2}x"),
184246
i_CLKDIV = ClockSignal("sys"),
185247
i_BITSLIP = shift_inc,
186-
**{f"o_Q{data_width-i}" : data[i] for i in range(data_width)},
248+
**{f"o_Q{i+1}" : data[data_width-i-1] for i in range(min(8,data_width))},
249+
o_SHIFTOUT1 = master_shiftout1,
250+
o_SHIFTOUT2 = master_shiftout2,
187251
)
188252
]
253+
if data_width>=10:
254+
slave_shiftin1 = Signal()
255+
slave_shiftin2 = Signal()
256+
remaining_bits = data_width-8
257+
self.specials += [
258+
Instance("ISERDESE2",
259+
p_DATA_WIDTH = data_width,
260+
p_DATA_RATE = "DDR",
261+
p_SERDES_MODE = "SLAVE",
262+
p_INTERFACE_TYPE = "NETWORKING",
263+
p_NUM_CE = 1,
264+
p_IOBDELAY = "IFD",
265+
266+
i_CE1 = 1,
267+
i_RST = ResetSignal("sys"),
268+
i_CLK = ClockSignal(f"sys{data_width//2}x"),
269+
i_CLKB =~ClockSignal(f"sys{data_width//2}x"),
270+
i_CLKDIV = ClockSignal("sys"),
271+
i_BITSLIP = self.shift,
272+
i_SHIFTIN1 = slave_shiftin1,
273+
i_SHIFTIN2 = slave_shiftin2,
274+
**{f"o_Q{i+3}" : data[remaining_bits-i-1] for i in range(remaining_bits)}, #d3-d8 see UG471:155
275+
)
276+
]
277+
self.comb += [slave_shiftin1.eq(master_shiftout1),
278+
slave_shiftin2.eq(master_shiftout2)]
189279

190280
# Datapath.
191281
# ---------

0 commit comments

Comments
 (0)