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: f599fe4ade7e
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: 67c3119249da
Choose a head ref
  • 4 commits
  • 4 files changed
  • 1 contributor

Commits on Apr 24, 2013

  1. genlib: add Gray counter

    Sebastien Bourdeauducq committed Apr 24, 2013
    Copy the full SHA
    0f9df2d View commit details

Commits on Apr 25, 2013

  1. graycounter: expose binary output

    Sebastien Bourdeauducq committed Apr 25, 2013
    Copy the full SHA
    6c08cd6 View commit details
  2. fhdl/specials/memory: do not write address register for async reads

    Sebastien Bourdeauducq committed Apr 25, 2013
    Copy the full SHA
    fee228a View commit details
  3. genlib/fifo: add asynchronous FIFO

    Sebastien Bourdeauducq committed Apr 25, 2013
    Copy the full SHA
    67c3119 View commit details
Showing with 98 additions and 6 deletions.
  1. +19 −0 examples/basic/graycounter.py
  2. +5 −5 migen/fhdl/specials.py
  3. +24 −0 migen/genlib/cdc.py
  4. +50 −1 migen/genlib/fifo.py
19 changes: 19 additions & 0 deletions examples/basic/graycounter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
from random import Random

from migen.fhdl.module import Module
from migen.genlib.cdc import GrayCounter
from migen.sim.generic import Simulator

class TB(Module):
def __init__(self, width=3):
self.width = width
self.submodules.gc = GrayCounter(self.width)
self.prng = Random(7345)

def do_simulation(self, s):
print("{0:0{1}b} CE={2} bin={3}".format(s.rd(self.gc.q),
self.width, s.rd(self.gc.ce), s.rd(self.gc.q_binary)))
s.wr(self.gc.ce, self.prng.getrandbits(1))

sim = Simulator(TB())
sim.run(35)
10 changes: 5 additions & 5 deletions migen/fhdl/specials.py
Original file line number Diff line number Diff line change
@@ -258,11 +258,11 @@ def emit_verilog(memory, ns):
elif port.mode == NO_CHANGE:
rd = "\tif (!" + gn(port.we) + ")\n" \
+ "\t\t" + bassign
if port.re is None:
r += rd
else:
r += "\tif (" + gn(port.re) + ")\n"
r += "\t" + rd.replace("\n\t", "\n\t\t")
if port.re is None:
r += rd
else:
r += "\tif (" + gn(port.re) + ")\n"
r += "\t" + rd.replace("\n\t", "\n\t\t")
r += "end\n\n"

for port in memory.ports:
24 changes: 24 additions & 0 deletions migen/genlib/cdc.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from migen.fhdl.structure import *
from migen.fhdl.module import Module
from migen.fhdl.specials import Special
from migen.fhdl.tools import list_signals

@@ -71,3 +72,26 @@ def get_fragment(self):
return Fragment(comb,
{self.idomain: sync_i, self.odomain: sync_o},
specials={MultiReg(toggle_i, toggle_o, self.odomain)})

class GrayCounter(Module):
def __init__(self, width):
self.ce = Signal()
self.q = Signal(width)
self.q_next = Signal(width)
self.q_binary = Signal(width)
self.q_next_binary = Signal(width)

###

self.comb += [
If(self.ce,
self.q_next_binary.eq(self.q_binary + 1)
).Else(
self.q_next_binary.eq(self.q_binary)
),
self.q_next.eq(self.q_next_binary ^ self.q_next_binary[1:])
]
self.sync += [
self.q_binary.eq(self.q_next_binary),
self.q.eq(self.q_next)
]
51 changes: 50 additions & 1 deletion migen/genlib/fifo.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from migen.fhdl.structure import *
from migen.fhdl.specials import Memory
from migen.fhdl.module import Module
from migen.genlib.cdc import MultiReg, GrayCounter

def _inc(signal, modulo):
if modulo == 2**len(signal):
@@ -12,7 +13,7 @@ def _inc(signal, modulo):
signal.eq(signal + 1)
)

class SyncFIFO(Module):
class _FIFOInterface:
def __init__(self, width, depth):
self.din = Signal(width)
self.we = Signal()
@@ -21,6 +22,10 @@ def __init__(self, width, depth):
self.re = Signal()
self.readable = Signal() # not empty

class SyncFIFO(Module, _FIFOInterface):
def __init__(self, width, depth):
_FIFOInterface.__init__(self, width, depth)

###

do_write = Signal()
@@ -62,3 +67,47 @@ def __init__(self, width, depth):
self.writable.eq(level != depth),
self.readable.eq(level != 0)
]

class AsyncFIFO(Module, _FIFOInterface):
def __init__(self, width, depth):
_FIFOInterface.__init__(self, width, depth)

###

depth_bits = log2_int(depth, True)

produce = GrayCounter(depth_bits+1)
self.add_submodule(produce, "write")
consume = GrayCounter(depth_bits+1)
self.add_submodule(consume, "read")
self.comb += [
produce.ce.eq(self.writable & self.we),
consume.ce.eq(self.readable & self.re)
]

# TODO: disable retiming on produce.q and consume.q

produce_rdomain = Signal(depth_bits+1)
self.specials += MultiReg(produce.q, produce_rdomain, "read")
consume_wdomain = Signal(depth_bits+1)
self.specials += MultiReg(consume.q, consume_wdomain, "write")
self.comb += [
self.writable.eq((produce.q[-1] == consume_wdomain[-1])
| (produce.q[-2] == consume_wdomain[-2])
| (produce.q[:-2] != consume_wdomain[:-2])),
self.readable.eq(consume.q != produce_rdomain)
]

storage = Memory(width, depth)
self.specials += storage
wrport = storage.get_port(write_capable=True, clock_domain="write")
self.comb += [
wrport.adr.eq(produce.q_binary[:-1]),
wrport.dat_w.eq(self.din),
wrport.we.eq(produce.ce)
]
rdport = storage.get_port(clock_domain="read")
self.comb += [
rdport.adr.eq(consume.q_binary[:-1]),
self.dout.eq(rdport.dat_r)
]