Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: m-labs/nmigen
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: c4e8ac734f3f
Choose a base ref
...
head repository: m-labs/nmigen
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 2e206220462c
Choose a head ref
  • 1 commit
  • 4 files changed
  • 1 contributor

Commits on Aug 31, 2019

  1. hdl.cd: add negedge clock domains.

    Fixes #185.
    whitequark committed Aug 31, 2019
    Copy the full SHA
    2e20622 View commit details
Showing with 29 additions and 5 deletions.
  1. +4 −1 nmigen/back/pysim.py
  2. +3 −3 nmigen/back/rtlil.py
  3. +9 −1 nmigen/hdl/cd.py
  4. +13 −0 nmigen/test/test_hdl_cd.py
5 changes: 4 additions & 1 deletion nmigen/back/pysim.py
Original file line number Diff line number Diff line change
@@ -364,6 +364,7 @@ def __init__(self, fragment, vcd_file=None, gtkw_file=None, traces=()):
self._slot_signals = list() # int/slot -> Signal

self._domains = list() # [ClockDomain]
self._clk_edges = dict() # ClockDomain -> int/edge
self._domain_triggers = list() # int/slot -> ClockDomain

self._signals = SignalSet() # {Signal}
@@ -488,6 +489,7 @@ def add_fragment(fragment, scope=()):
add_fragment(subfragment, (*scope, name))
add_fragment(root_fragment, scope=("top",))
self._domains = list(domains)
self._clk_edges = {domain: 1 if domain.clk_edge == "pos" else 0 for domain in domains}

def add_signal(signal):
if signal not in self._signals:
@@ -642,7 +644,8 @@ def _commit_signal(self, signal_slot, domains):
return

# If the signal is a clock that triggers synchronous logic, record that fact.
if new == 1 and self._domain_triggers[signal_slot] is not None:
if (self._domain_triggers[signal_slot] is not None and
self._clk_edges[self._domain_triggers[signal_slot]] == new):
domains.add(self._domain_triggers[signal_slot])

if self._vcd_writer:
6 changes: 3 additions & 3 deletions nmigen/back/rtlil.py
Original file line number Diff line number Diff line change
@@ -884,8 +884,8 @@ def _convert_fragment(builder, fragment, hierarchy):

# For every signal in every sync domain, assign \sig to \sig$next. The sensitivity
# list, however, differs between domains: for domains with sync reset, it is
# `posedge clk`, for sync domains with async reset it is `posedge clk or
# posedge rst`.
# `[pos|neg]edge clk`, for sync domains with async reset it is `[pos|neg]edge clk
# or posedge rst`.
for domain, signals in fragment.drivers.items():
if domain is None:
continue
@@ -897,7 +897,7 @@ def _convert_fragment(builder, fragment, hierarchy):
cd = fragment.domains[domain]

triggers = []
triggers.append(("posedge", compiler_state.resolve_curr(cd.clk)))
triggers.append((cd.clk_edge + "edge", compiler_state.resolve_curr(cd.clk)))
if cd.async_reset:
triggers.append(("posedge", compiler_state.resolve_curr(cd.rst)))

10 changes: 9 additions & 1 deletion nmigen/hdl/cd.py
Original file line number Diff line number Diff line change
@@ -45,7 +45,8 @@ def _name_for(domain_name, signal_name):
else:
return "{}_{}".format(domain_name, signal_name)

def __init__(self, name=None, reset_less=False, async_reset=False, local=False):
def __init__(self, name=None, *, clk_edge="pos", reset_less=False, async_reset=False,
local=False):
if name is None:
try:
name = tracer.get_var_name()
@@ -55,9 +56,16 @@ def __init__(self, name=None, reset_less=False, async_reset=False, local=False):
name = name[3:]
if name == "comb":
raise ValueError("Domain '{}' may not be clocked".format(name))

if clk_edge not in ("pos", "neg"):
raise ValueError("Domain clock edge must be one of 'pos' or 'neg', not {!r}"
.format(clk_edge))

self.name = name

self.clk = Signal(name=self._name_for(name, "clk"), src_loc_at=1)
self.clk_edge = clk_edge

if reset_less:
self.rst = None
else:
13 changes: 13 additions & 0 deletions nmigen/test/test_hdl_cd.py
Original file line number Diff line number Diff line change
@@ -23,6 +23,19 @@ def test_name(self):
cd_reset = ClockDomain(local=True)
self.assertEqual(cd_reset.local, True)

def test_edge(self):
sync = ClockDomain()
self.assertEqual(sync.clk_edge, "pos")
sync = ClockDomain(clk_edge="pos")
self.assertEqual(sync.clk_edge, "pos")
sync = ClockDomain(clk_edge="neg")
self.assertEqual(sync.clk_edge, "neg")

def test_edge_wrong(self):
with self.assertRaises(ValueError,
msg="Domain clock edge must be one of 'pos' or 'neg', not 'xxx'"):
ClockDomain("sync", clk_edge="xxx")

def test_with_reset(self):
pix = ClockDomain()
self.assertIsNotNone(pix.clk)