@@ -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 ),
@@ -88,7 +88,18 @@ def _make_oereg(m, domain, oe, q):
8888        )
8989
9090
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 ):
92103    def  elaborate (self , platform ):
93104        m  =  Module ()
94105
@@ -118,7 +129,42 @@ def elaborate(self, platform):
118129                    i_D = o_inv [bit ],
119130                    o_Q = buf .o [bit ],
120131                )
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 )
122168
123169        return  m 
124170
@@ -159,7 +205,7 @@ def elaborate(self, platform):
159205                    i_D1 = o1_inv [bit ],
160206                    o_Q = buf .o [bit ],
161207                )
162-             _make_oereg (m , self .o_domain , ~ self .oe , buf .t )
208+             _make_oereg_ecp5_machxo2 (m , self .o_domain , ~ self .oe , buf .t )
163209
164210        return  m 
165211
@@ -200,7 +246,7 @@ def elaborate(self, platform):
200246                    i_D1 = o1_inv [bit ],
201247                    o_Q = buf .o [bit ],
202248                )
203-             _make_oereg (m , self .o_domain , ~ self .oe , buf .t )
249+             _make_oereg_ecp5_machxo2 (m , self .o_domain , ~ self .oe , buf .t )
204250
205251        return  m 
206252
@@ -241,7 +287,7 @@ def elaborate(self, platform):
241287                    i_D1 = o1_inv [bit ],
242288                    o_Q = buf .o [bit ],
243289                )
244-             _make_oereg (m , self .o_domain , ~ self .oe , buf .t )
290+             _make_oereg_nexus (m , self .o_domain , ~ self .oe , buf .t )
245291
246292        return  m 
247293
@@ -951,7 +997,12 @@ def get_io_buffer(self, buffer):
951997        if  isinstance (buffer , io .Buffer ):
952998            result  =  IOBuffer (buffer .direction , buffer .port )
953999        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: 
9551006        elif  isinstance (buffer , io .DDRBuffer ):
9561007            if  self .family  ==  "ecp5" :
9571008                result  =  DDRBufferECP5 (buffer .direction , buffer .port )
0 commit comments