diff --git a/luna/gateware/utils/cdc.py b/luna/gateware/utils/cdc.py index cc11dbac..afdabd2f 100644 --- a/luna/gateware/utils/cdc.py +++ b/luna/gateware/utils/cdc.py @@ -53,6 +53,14 @@ def create_synchronizer(signal, output): # Otherwise, we'll need to make sure we only synchronize # elements with non-output directions. for name, layout, direction in signal.layout: + # Skip any output elements, as they're already + # in our clock domain, and we don't want to drive them. + if (direction == DIR_FANOUT): + m.d.comb += signal[name].eq(output[name]) + continue + elif hasattr(signal[name], 'o') and ~hasattr(signal[name], 'i'): + m.d.comb += signal[name].o.eq(output[name]) + continue # If this is a record itself, we'll need to recurse. if isinstance(signal[name], (Record, Pin)): @@ -60,12 +68,6 @@ def create_synchronizer(signal, output): o_domain=o_domain, stages=stages) continue - # Skip any output elements, as they're already - # in our clock domain, and we don't want to drive them. - if (direction == DIR_FANOUT) or (hasattr(signal[name], 'o') and ~hasattr(signal[name], 'i')): - m.d.comb += signal[name].eq(output[name]) - continue - m.submodules += create_synchronizer(signal[name], output[name]) return output diff --git a/tests/test_cdc.py b/tests/test_cdc.py index 2852ac25..628b792c 100644 --- a/tests/test_cdc.py +++ b/tests/test_cdc.py @@ -8,6 +8,7 @@ from unittest import TestCase from amaranth import Module, Record, Signal +from amaranth.lib.io import Pin from amaranth.hdl.rec import DIR_FANIN, DIR_FANOUT from luna.gateware.utils.cdc import synchronize, stretch_strobe_signal @@ -39,6 +40,17 @@ def test_nested_record(self): ]) synchronize(m, record) + def test_pins(self): + m = Module() + pins = { + "sig_in": Pin(1, "i"), + "sig_out": Pin(1, "o"), + } + record = Record([ + (f_name, f.layout) for (f_name, f) in pins.items() + ], fields=pins) + synchronize(m, record) + class StrobeStretcherTest(LunaGatewareTestCase): """ Test case for our strobe stretcher function. """