20
20
21
21
class _S7SerdesClocking (LiteXModule ):
22
22
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"
24
26
self .refclk = Signal ()
25
27
26
28
# # #
27
29
30
+ master_shiftin1 = Signal ()
31
+ master_shiftin2 = Signal ()
28
32
# Master Mode.
29
33
# ------------
30
34
# Generate the linerate/10 clock. Slave will re-multiply it.
@@ -47,10 +51,34 @@ def __init__(self, pads, mode="master", data_width=8):
47
51
i_RST = ResetSignal ("sys" ),
48
52
i_CLK = ClockSignal (f"sys{ data_width // 2 } x" ),
49
53
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 ,
51
57
o_OQ = self .refclk ,
52
58
)
53
59
]
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 )]
54
82
if hasattr (pads , "clk_p" ):
55
83
self .specials += DifferentialOutput (self .refclk , pads .clk_p , pads .clk_n )
56
84
else :
@@ -69,7 +97,10 @@ def __init__(self, pads, mode="master", data_width=8):
69
97
70
98
class _S7SerdesTX (LiteXModule ):
71
99
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
+
73
104
# Control
74
105
self .idle = idle = Signal ()
75
106
self .comma = comma = Signal ()
@@ -94,6 +125,8 @@ def __init__(self, pads, data_width=8):
94
125
# -----------------------------
95
126
self .data = data = Signal (data_width )
96
127
data_serialized = Signal ()
128
+ master_shiftin1 = Signal ()
129
+ master_shiftin2 = Signal ()
97
130
self .comb += data .eq (datapath .source .data )
98
131
self .specials += [
99
132
Instance ("OSERDESE2" ,
@@ -107,10 +140,35 @@ def __init__(self, pads, data_width=8):
107
140
i_RST = ResetSignal ("sys" ),
108
141
i_CLK = ClockSignal (f"sys{ data_width // 2 } x" ),
109
142
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 ,
111
146
o_OQ = data_serialized ,
112
147
)
113
148
]
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
+
114
172
if hasattr (pads , "tx_p" ):
115
173
self .specials += DifferentialOutput (data_serialized , pads .tx_p , pads .tx_n )
116
174
else :
@@ -120,7 +178,9 @@ def __init__(self, pads, data_width=8):
120
178
121
179
class _S7SerdesRX (LiteXModule ):
122
180
def __init__ (self , pads , data_width = 8 ):
123
- assert data_width in [4 ,6 ,8 ] # valid serdese2 ddr rates
181
+ assert data_width in [4 ,6 ,8 ,10 ,14 ] # valid serdese2 ddr rates
182
+ if data_width >= 10 :
183
+ assert hasattr (pads , "rx_p" ), "Width expansion can only be used for differential outputs"
124
184
# Control.
125
185
self .delay_rst = delay_rst = Signal ()
126
186
self .delay_inc = delay_inc = Signal ()
@@ -142,6 +202,8 @@ def __init__(self, pads, data_width=8):
142
202
# ----------------------------
143
203
data_nodelay = Signal ()
144
204
data_delayed = Signal ()
205
+ master_shiftout1 = Signal ()
206
+ master_shiftout2 = Signal ()
145
207
self .data = data = Signal (data_width )
146
208
147
209
if hasattr (pads , "rx_p" ):
@@ -183,9 +245,37 @@ def __init__(self, pads, data_width=8):
183
245
i_CLKB = ~ ClockSignal (f"sys{ data_width // 2 } x" ),
184
246
i_CLKDIV = ClockSignal ("sys" ),
185
247
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 ,
187
251
)
188
252
]
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 = shift_inc ,
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 )]
189
279
190
280
# Datapath.
191
281
# ---------
0 commit comments