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/migen
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 3a591c358cd7
Choose a base ref
...
head repository: m-labs/migen
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 6abac5907b38
Choose a head ref
  • 3 commits
  • 3 files changed
  • 1 contributor

Commits on Feb 23, 2013

  1. fhdl/verilog: support special lowering and overrides

    Sebastien Bourdeauducq committed Feb 23, 2013

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    7c4e6c3 View commit details
  2. genlib: clock domain crossing elements

    Sebastien Bourdeauducq committed Feb 23, 2013
    3
    Copy the full SHA
    a878db1 View commit details
  3. examples/basic/psync: demonstrate the new features

    Sebastien Bourdeauducq committed Feb 23, 2013
    Copy the full SHA
    6abac59 View commit details
Showing with 111 additions and 27 deletions.
  1. +13 −23 examples/basic/psync.py
  2. +29 −4 migen/fhdl/verilog.py
  3. +69 −0 migen/genlib/cdc.py
36 changes: 13 additions & 23 deletions examples/basic/psync.py
Original file line number Diff line number Diff line change
@@ -1,30 +1,20 @@
from migen.fhdl.structure import *
from migen.fhdl.specials import SynthesisDirective
from migen.fhdl import verilog
from migen.genlib.cdc import *

# convert pulse into level change
i = Signal()
level = Signal()
isync = [If(i, level.eq(~level))]
class XilinxMultiRegImpl(MultiRegImpl):
def get_fragment(self):
disable_srl = set(SynthesisDirective("attribute shreg_extract of {r} is no", r=r)
for r in self.regs)
return MultiRegImpl.get_fragment(self) + Fragment(specials=disable_srl)

# synchronize level to oclk domain
slevel = [Signal() for i in range(3)]
osync = [
slevel[0].eq(level),
slevel[1].eq(slevel[0]),
slevel[2].eq(slevel[1])
]
class XilinxMultiReg(Special):
@staticmethod
def lower(dr):
return XilinxMultiRegImpl(dr.i, dr.idomain, dr.o, dr.odomain, dr.n)

# disable shift register extraction
disable_srl = {
SynthesisDirective("attribute shreg_extract of {signal} is no", signal=slevel[0]),
SynthesisDirective("attribute shreg_extract of {signal} is no", signal=slevel[1])
}

# regenerate pulse
o = Signal()
comb = [o.eq(slevel[1] ^ slevel[2])]

f = Fragment(comb, {"i": isync, "o": osync}, specials=disable_srl)
v = verilog.convert(f, {i, o})
ps = PulseSynchronizer("from", "to")
f = ps.get_fragment()
v = verilog.convert(f, {ps.i, ps.o}, special_overrides={MultiReg: XilinxMultiReg})
print(v)
33 changes: 29 additions & 4 deletions migen/fhdl/verilog.py
Original file line number Diff line number Diff line change
@@ -208,10 +208,32 @@ def _printsync(f, ns, clock_domains):
r += "end\n\n"
return r

def _printspecials(f, ns, clock_domains):
def _call_special_classmethod(overrides, obj, method, *args, **kwargs):
cl = obj.__class__
if cl in overrides:
cl = overrides[cl]
if hasattr(cl, method):
return getattr(cl, method)(obj, *args, **kwargs)
else:
return None

def _lower_specials(overrides, specials):
f = Fragment()
lowered_specials = set()
for special in sorted(specials, key=lambda x: x.huid):
impl = _call_special_classmethod(overrides, special, "lower")
if impl is not None:
f += impl.get_fragment()
lowered_specials.add(special)
return f, lowered_specials

def _printspecials(overrides, specials, ns, clock_domains):
r = ""
for special in sorted(f.specials, key=lambda x: x.huid):
r += special.emit_verilog(special, ns, clock_domains)
for special in sorted(specials, key=lambda x: x.huid):
pr = _call_special_classmethod(overrides, special, "emit_verilog", ns, clock_domains)
if pr is None:
raise NotImplementedError("Special " + str(special) + " failed to implement emit_verilog")
r += pr
return r

def _printinit(f, ios, ns):
@@ -230,6 +252,7 @@ def _printinit(f, ios, ns):
def convert(f, ios=None, name="top",
clock_domains=None,
return_ns=False,
special_overrides=dict(),
display_run=False):
if ios is None:
ios = set()
@@ -242,6 +265,8 @@ def convert(f, ios=None, name="top",
ios.add(cd.rst)

f = lower_arrays(f)
fs, lowered_specials = _lower_specials(special_overrides, f.specials)
f += fs

ns = build_namespace(list_signals(f) \
| list_special_ios(f, True, True, True) \
@@ -251,7 +276,7 @@ def convert(f, ios=None, name="top",
r += _printheader(f, ios, name, ns)
r += _printcomb(f, ns, display_run)
r += _printsync(f, ns, clock_domains)
r += _printspecials(f, ns, clock_domains)
r += _printspecials(special_overrides, f.specials - lowered_specials, ns, clock_domains)
r += _printinit(f, ios, ns)
r += "endmodule\n"

69 changes: 69 additions & 0 deletions migen/genlib/cdc.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
from migen.fhdl.structure import *
from migen.fhdl.specials import Special
from migen.fhdl.tools import value_bits_sign, list_signals

class MultiRegImpl:
def __init__(self, i, idomain, o, odomain, n):
self.i = i
self.idomain = idomain
self.o = o
self.odomain = odomain

w, signed = value_bits_sign(self.i)
self.regs = [Signal((w, signed)) for i in range(n)]

def get_fragment(self):
src = self.i
o_sync = []
for reg in self.regs:
o_sync.append(reg.eq(src))
src = reg
comb = [
self.o.eq(src)
]
return Fragment(comb, {self.odomain: o_sync})

class MultiReg(Special):
def __init__(self, i, idomain, o, odomain, n=2):
Special.__init__(self)
self.i = i
self.idomain = idomain
self.o = o
self.odomain = odomain
self.n = n

def list_ios(self, ins, outs, inouts):
r = set()
if ins:
r.update(list_signals(self.i))
if outs:
r.update(list_signals(self.o))
return r

@staticmethod
def lower(dr):
return MultiRegImpl(dr.i, dr.idomain, dr.o, dr.odomain, dr.n)

class PulseSynchronizer:
def __init__(self, idomain, odomain):
self.idomain = idomain
self.odomain = odomain
self.i = Signal()
self.o = Signal()

def get_fragment(self):
toggle_i = Signal()
toggle_o = Signal()
toggle_o_r = Signal()
sync_i = [
If(self.i, toggle_i.eq(~toggle_i))
]
sync_o = [
toggle_o_r.eq(toggle_o)
]
comb = [
self.o.eq(toggle_o ^ toggle_o_r)
]
return Fragment(comb,
{self.idomain: sync_i, self.odomain: sync_o},
specials={MultiReg(toggle_i, self.idomain, toggle_o, self.odomain)})