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
    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)})