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: 6b843b5be6fd
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: ea25806971ff
Choose a head ref
  • 2 commits
  • 1 file changed
  • 1 contributor

Commits on Jul 2, 2019

  1. back.rtlil: do not emit $next wires for comb signals.

    According to RTLIL semantics (that was undocumented before today),
    the only purpose of `sync always` is to enable inference of latches,
    because there is no other way to express them in terms of RTLIL
    processes without ending up with a combinatorial loop. But, nMigen
    specifically avoids latches, so this is not necessary.
    
    This change results in major improvements in Verilog readability.
    
    See also #98.
    whitequark committed Jul 2, 2019
    Copy the full SHA
    dd5e513 View commit details
  2. back.rtlil: emit \sig$next wires instead of \$next\sig. NFC.

    Just a bit more readable.
    whitequark committed Jul 2, 2019
    Copy the full SHA
    ea25806 View commit details
Showing with 20 additions and 19 deletions.
  1. +20 −19 nmigen/back/rtlil.py
39 changes: 20 additions & 19 deletions nmigen/back/rtlil.py
Original file line number Diff line number Diff line change
@@ -269,8 +269,8 @@ def resolve(self, signal, prefix=None):
wire_curr = self.rtlil.wire(width=signal.nbits, name=wire_name,
port_id=port_id, port_kind=port_kind,
src=src(signal.src_loc))
if signal in self.driven:
wire_next = self.rtlil.wire(width=signal.nbits, name="$next" + wire_curr,
if signal in self.driven and self.driven[signal]:
wire_next = self.rtlil.wire(width=signal.nbits, name=wire_curr + "$next",
src=src(signal.src_loc))
else:
wire_next = None
@@ -559,10 +559,10 @@ def match_shape(self, value, new_bits, new_sign):
return self(value)

def on_Signal(self, value):
wire_curr, wire_next = self.s.resolve(value)
if wire_next is None:
if value not in self.s.driven:
raise ValueError("No LHS wire for non-driven signal {}".format(repr(value)))
return wire_next
wire_curr, wire_next = self.s.resolve(value)
return wire_next or wire_curr

def _prepare_value_for_Slice(self, value):
assert isinstance(value, (ast.Signal, ast.Slice, ast.Cat, rec.Record))
@@ -695,7 +695,7 @@ def convert_fragment(builder, fragment, hierarchy):
verilog_trigger_sync_emitted = False

# Register all signals driven in the current fragment. This must be done first, as it
# affects further codegen; e.g. whether $next\sig signals will be generated and used.
# affects further codegen; e.g. whether \sig$next signals will be generated and used.
for domain, signal in fragment.iter_drivers():
compiler_state.add_driven(signal, sync=domain is not None)

@@ -781,8 +781,8 @@ def convert_fragment(builder, fragment, hierarchy):

with module.process(name="$group_{}".format(group)) as process:
with process.case() as case:
# For every signal in comb domain, assign $next\sig to the reset value.
# For every signal in sync domains, assign $next\sig to the current
# For every signal in comb domain, assign \sig$next to the reset value.
# For every signal in sync domains, assign \sig$next to the current
# value (\sig).
for domain, signal in fragment.iter_drivers():
if signal not in group_signals:
@@ -824,23 +824,24 @@ def convert_fragment(builder, fragment, hierarchy):
sync.update(verilog_trigger, "1'0")
verilog_trigger_sync_emitted = True

# For every signal in every domain, assign \sig to $next\sig. The sensitivity list,
# however, differs between domains: for comb domains, it is `always`, for sync
# domains with sync reset, it is `posedge clk`, for sync domains with async reset
# it is `posedge clk or posedge rst`.
# 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`.
for domain, signals in fragment.drivers.items():
if domain is None:
continue

signals = signals & group_signals
if not signals:
continue

cd = fragment.domains[domain]

triggers = []
if domain is None:
triggers.append(("always",))
else:
cd = fragment.domains[domain]
triggers.append(("posedge", compiler_state.resolve_curr(cd.clk)))
if cd.async_reset:
triggers.append(("posedge", compiler_state.resolve_curr(cd.rst)))
triggers.append(("posedge", compiler_state.resolve_curr(cd.clk)))
if cd.async_reset:
triggers.append(("posedge", compiler_state.resolve_curr(cd.rst)))

for trigger in triggers:
with process.sync(*trigger) as sync: