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