@@ -77,7 +77,7 @@ def elaborate(self, platform):
77
77
return m
78
78
79
79
80
- def _make_oereg (m , domain , oe , q ):
80
+ def _make_oereg_ecp5_machxo2 (m , domain , oe , q ):
81
81
for bit in range (len (q )):
82
82
m .submodules [f"oe_ff{ bit } " ] = Instance ("OFS1P3DX" ,
83
83
i_SCLK = ClockSignal (domain ),
@@ -88,7 +88,18 @@ def _make_oereg(m, domain, oe, q):
88
88
)
89
89
90
90
91
- class FFBuffer (io .FFBuffer ):
91
+ def _make_oereg_nexus (m , domain , oe , q ):
92
+ for bit in range (len (q )):
93
+ m .submodules [f"oe_ff{ bit } " ] = Instance ("OFD1P3DX" ,
94
+ i_CK = ClockSignal (domain ),
95
+ i_SP = Const (1 ),
96
+ i_CD = Const (0 ),
97
+ i_D = oe ,
98
+ o_Q = q [bit ],
99
+ )
100
+
101
+
102
+ class FFBufferECP5 (io .FFBuffer ):
92
103
def elaborate (self , platform ):
93
104
m = Module ()
94
105
@@ -118,7 +129,42 @@ def elaborate(self, platform):
118
129
i_D = o_inv [bit ],
119
130
o_Q = buf .o [bit ],
120
131
)
121
- _make_oereg (m , self .o_domain , ~ self .oe , buf .t )
132
+ _make_oereg_ecp5_machxo2 (m , self .o_domain , ~ self .oe , buf .t )
133
+
134
+ return m
135
+
136
+
137
+ class FFBufferNexus (io .FFBuffer ):
138
+ def elaborate (self , platform ):
139
+ m = Module ()
140
+
141
+ m .submodules .buf = buf = InnerBuffer (self .direction , self .port )
142
+ inv_mask = sum (inv << bit for bit , inv in enumerate (self .port .invert ))
143
+
144
+ if self .direction is not io .Direction .Output :
145
+ i_inv = Signal .like (self .i )
146
+ for bit in range (len (self .port )):
147
+ m .submodules [f"i_ff{ bit } " ] = Instance ("IFD1P3DX" ,
148
+ i_CK = ClockSignal (self .i_domain ),
149
+ i_SP = Const (1 ),
150
+ i_CD = Const (0 ),
151
+ i_D = buf .i [bit ],
152
+ o_Q = i_inv [bit ],
153
+ )
154
+ m .d .comb += self .i .eq (i_inv ^ inv_mask )
155
+
156
+ if self .direction is not io .Direction .Input :
157
+ o_inv = Signal .like (self .o )
158
+ m .d .comb += o_inv .eq (self .o ^ inv_mask )
159
+ for bit in range (len (self .port )):
160
+ m .submodules [f"o_ff{ bit } " ] = Instance ("OFD1P3DX" ,
161
+ i_CK = ClockSignal (self .o_domain ),
162
+ i_SP = Const (1 ),
163
+ i_CD = Const (0 ),
164
+ i_D = o_inv [bit ],
165
+ o_Q = buf .o [bit ],
166
+ )
167
+ _make_oereg_nexus (m , self .o_domain , ~ self .oe , buf .t )
122
168
123
169
return m
124
170
@@ -159,7 +205,7 @@ def elaborate(self, platform):
159
205
i_D1 = o1_inv [bit ],
160
206
o_Q = buf .o [bit ],
161
207
)
162
- _make_oereg (m , self .o_domain , ~ self .oe , buf .t )
208
+ _make_oereg_ecp5_machxo2 (m , self .o_domain , ~ self .oe , buf .t )
163
209
164
210
return m
165
211
@@ -200,7 +246,7 @@ def elaborate(self, platform):
200
246
i_D1 = o1_inv [bit ],
201
247
o_Q = buf .o [bit ],
202
248
)
203
- _make_oereg (m , self .o_domain , ~ self .oe , buf .t )
249
+ _make_oereg_ecp5_machxo2 (m , self .o_domain , ~ self .oe , buf .t )
204
250
205
251
return m
206
252
@@ -241,7 +287,7 @@ def elaborate(self, platform):
241
287
i_D1 = o1_inv [bit ],
242
288
o_Q = buf .o [bit ],
243
289
)
244
- _make_oereg (m , self .o_domain , ~ self .oe , buf .t )
290
+ _make_oereg_nexus (m , self .o_domain , ~ self .oe , buf .t )
245
291
246
292
return m
247
293
@@ -951,7 +997,12 @@ def get_io_buffer(self, buffer):
951
997
if isinstance (buffer , io .Buffer ):
952
998
result = IOBuffer (buffer .direction , buffer .port )
953
999
elif isinstance (buffer , io .FFBuffer ):
954
- result = FFBuffer (buffer .direction , buffer .port )
1000
+ if self .family in ("ecp5" , "machxo2" ):
1001
+ result = FFBufferECP5 (buffer .direction , buffer .port )
1002
+ elif self .family == "nexus" :
1003
+ result = FFBufferNexus (buffer .direction , buffer .port )
1004
+ else :
1005
+ raise NotImplementedError # :nocov:
955
1006
elif isinstance (buffer , io .DDRBuffer ):
956
1007
if self .family == "ecp5" :
957
1008
result = DDRBufferECP5 (buffer .direction , buffer .port )
0 commit comments