@@ -353,41 +353,61 @@ def elaborate(self, platform):
353353
354354class Converter (Elaboratable ):
355355 def __init__ (self , nbits_from , nbits_to , cd_from = "sync" , cd_to = "sync" ,
356- reverse = False , buffered = True ):
356+ reverse = False , buffered = True ,
357+ put_width_converter_first = True ):
357358 self .nbits_from = nbits_from
358359 self .nbits_to = nbits_to
359360 self .cd_from = cd_from
360361 self .cd_to = cd_to
361362 self .reverse = reverse
362363 self .buffered = buffered
364+ self .put_width_converter_first = put_width_converter_first
363365
364366 self .sink = Endpoint ([("data" , nbits_from )])
365367 self .source = Endpoint ([("data" , nbits_to )])
366368
367- def elaborate (self , platform ):
368- sin = self .sink
369-
370- m = Module ()
371-
369+ def put_width_converter (self , m , s ):
372370 # Need width converter ?
373371 if self .nbits_from != self .nbits_to :
374372 m .submodules .cvt = cvt = DomainRenamer (self .cd_from )(
375373 _Converter (self .nbits_from , self .nbits_to , reverse = self .reverse )
376374 )
377375
378- m .d .comb += sin .connect (cvt .sink )
379- sin = cvt .source
376+ m .d .comb += s .connect (cvt .sink )
377+ return cvt .source
378+
379+ return s
380380
381+ def put_cross_domain (self , m , s ):
381382 # Need cross domain clocking ?
382383 if self .cd_from != self .cd_to :
383384 m .submodules .asc = asc = AsyncFIFO (
384- sin .description , 8 , buffered = self .buffered ,
385+ s .description , 8 , buffered = self .buffered ,
385386 w_domain = self .cd_from , r_domain = self .cd_to ,
386387 )
387388
388- m .d .comb += sin .connect (asc .sink )
389- sin = asc .source
389+ m .d .comb += s .connect (asc .sink )
390+ return asc .source
390391
391- m .d .comb += sin .connect (self .source )
392+ return s
393+
394+ def elaborate (self , platform ):
395+ m = Module ()
396+
397+ # Depending on the design we give the choice to change the
398+ # conversion order. This has an importance:
399+ # - Cross domain FIFO is gate costly, we might want to put
400+ # it on the smallest width side to save gates.
401+ # - But clock frequencies are important too:
402+ # we might want to perform the width conversion in the fastest
403+ # clock domain to preserve the overall data throughput.
404+ s = self .sink
405+ if self .put_width_converter_first :
406+ s = self .put_width_converter (m , s )
407+ s = self .put_cross_domain (m , s )
408+ else :
409+ s = self .put_cross_domain (m , s )
410+ s = self .put_width_converter (m , s )
411+ m .d .comb += s .connect (self .source )
392412
393413 return m
0 commit comments