@@ -77,7 +77,7 @@ def elaborate(self, platform):
7777 return m
7878
7979
80- def _make_oereg (m , domain , oe , q ):
80+ def _make_oereg_ecp5_machxo2 (m , domain , oe , q ):
8181 for bit in range (len (q )):
8282 m .submodules [f"oe_ff{ bit } " ] = Instance ("OFS1P3DX" ,
8383 i_SCLK = ClockSignal (domain ),
@@ -87,8 +87,18 @@ def _make_oereg(m, domain, oe, q):
8787 o_Q = q [bit ],
8888 )
8989
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+
90100
91- class FFBuffer (io .FFBuffer ):
101+ class FFBufferECP5 (io .FFBuffer ):
92102 def elaborate (self , platform ):
93103 m = Module ()
94104
@@ -118,7 +128,41 @@ def elaborate(self, platform):
118128 i_D = o_inv [bit ],
119129 o_Q = buf .o [bit ],
120130 )
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 )
122166
123167 return m
124168
@@ -159,7 +203,7 @@ def elaborate(self, platform):
159203 i_D1 = o1_inv [bit ],
160204 o_Q = buf .o [bit ],
161205 )
162- _make_oereg (m , self .o_domain , ~ self .oe , buf .t )
206+ _make_oereg_ecp5_machxo2 (m , self .o_domain , ~ self .oe , buf .t )
163207
164208 return m
165209
@@ -200,7 +244,7 @@ def elaborate(self, platform):
200244 i_D1 = o1_inv [bit ],
201245 o_Q = buf .o [bit ],
202246 )
203- _make_oereg (m , self .o_domain , ~ self .oe , buf .t )
247+ _make_oereg_ecp5_machxo2 (m , self .o_domain , ~ self .oe , buf .t )
204248
205249 return m
206250
@@ -241,7 +285,7 @@ def elaborate(self, platform):
241285 i_D1 = o1_inv [bit ],
242286 o_Q = buf .o [bit ],
243287 )
244- _make_oereg (m , self .o_domain , ~ self .oe , buf .t )
288+ _make_oereg_nexus (m , self .o_domain , ~ self .oe , buf .t )
245289
246290 return m
247291
@@ -951,7 +995,12 @@ def get_io_buffer(self, buffer):
951995 if isinstance (buffer , io .Buffer ):
952996 result = IOBuffer (buffer .direction , buffer .port )
953997 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:
9551004 elif isinstance (buffer , io .DDRBuffer ):
9561005 if self .family == "ecp5" :
9571006 result = DDRBufferECP5 (buffer .direction , buffer .port )
0 commit comments