Skip to content

Commit

Permalink
Merge pull request #263 from antoinevg/antoinevg/fix-cdc
Browse files Browse the repository at this point in the history
gateware: fix an order-of-operations bug with cdc.synchronize
  • Loading branch information
miek authored Jun 8, 2024
2 parents fe7d811 + 2d6df09 commit 640da58
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 6 deletions.
14 changes: 8 additions & 6 deletions luna/gateware/utils/cdc.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,19 +53,21 @@ 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)):
synchronize(m, signal[name], output=output[name],
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
Expand Down
12 changes: 12 additions & 0 deletions tests/test_cdc.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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. """
Expand Down

0 comments on commit 640da58

Please sign in to comment.