2012-10-04 12:22:22 -04:00
|
|
|
# Simple Processor Interface
|
|
|
|
|
|
|
|
from migen.fhdl.structure import *
|
2013-02-22 11:56:35 -05:00
|
|
|
from migen.fhdl.specials import Memory
|
2012-10-04 12:22:22 -04:00
|
|
|
from migen.bank.description import *
|
|
|
|
from migen.flow.actor import *
|
|
|
|
|
2012-10-09 15:11:15 -04:00
|
|
|
# layout is a list of tuples, either:
|
2012-11-29 17:36:55 -05:00
|
|
|
# - (name, nbits, [reset value], [alignment bits])
|
2012-10-09 15:11:15 -04:00
|
|
|
# - (name, sublayout)
|
|
|
|
|
|
|
|
def _convert_layout(layout):
|
|
|
|
r = []
|
|
|
|
for element in layout:
|
|
|
|
if isinstance(element[1], list):
|
|
|
|
r.append((element[0], _convert_layout(element[1])))
|
|
|
|
else:
|
|
|
|
r.append((element[0], element[1]))
|
|
|
|
return r
|
|
|
|
|
2013-03-30 12:28:41 -04:00
|
|
|
def _create_csrs_assign(layout, target, atomic, prefix=""):
|
|
|
|
csrs = []
|
2012-10-09 15:11:15 -04:00
|
|
|
assigns = []
|
|
|
|
for element in layout:
|
|
|
|
if isinstance(element[1], list):
|
2013-03-30 12:28:41 -04:00
|
|
|
r_csrs, r_assigns = _create_csrs_assign(element[1],
|
2012-10-09 15:11:15 -04:00
|
|
|
atomic,
|
|
|
|
getattr(target, element[0]),
|
|
|
|
element[0] + "_")
|
2013-03-30 12:28:41 -04:00
|
|
|
csrs += r_csrs
|
2012-10-09 15:11:15 -04:00
|
|
|
assigns += r_assigns
|
|
|
|
else:
|
|
|
|
name = element[0]
|
2012-11-29 17:36:55 -05:00
|
|
|
nbits = element[1]
|
2012-10-09 15:11:15 -04:00
|
|
|
if len(element) > 2:
|
|
|
|
reset = element[2]
|
|
|
|
else:
|
|
|
|
reset = 0
|
|
|
|
if len(element) > 3:
|
|
|
|
alignment = element[3]
|
|
|
|
else:
|
|
|
|
alignment = 0
|
2013-03-30 12:28:41 -04:00
|
|
|
reg = CSRStorage(nbits + alignment, reset=reset, atomic_write=atomic, name=prefix + name)
|
|
|
|
csrs.append(reg)
|
|
|
|
assigns.append(getattr(target, name).eq(reg.storage[alignment:]))
|
|
|
|
return csrs, assigns
|
2012-10-09 15:11:15 -04:00
|
|
|
|
|
|
|
(MODE_EXTERNAL, MODE_SINGLE_SHOT, MODE_CONTINUOUS) = range(3)
|
|
|
|
|
2013-04-10 13:12:42 -04:00
|
|
|
class SingleGenerator(Module):
|
2012-10-09 15:11:15 -04:00
|
|
|
def __init__(self, layout, mode):
|
2013-04-10 13:12:42 -04:00
|
|
|
self.source = Source(_convert_layout(layout))
|
|
|
|
self.busy = Signal()
|
|
|
|
self._csrs, assigns = _create_csrs_assign(layout, self.source.payload,
|
|
|
|
mode != MODE_SINGLE_SHOT)
|
2012-10-09 15:11:15 -04:00
|
|
|
if mode == MODE_EXTERNAL:
|
2013-04-10 13:12:42 -04:00
|
|
|
trigger = self.trigger = Signal()
|
2012-10-09 15:11:15 -04:00
|
|
|
elif mode == MODE_SINGLE_SHOT:
|
2013-03-30 12:28:41 -04:00
|
|
|
shoot = CSR()
|
|
|
|
self._csrs.insert(0, shoot)
|
2013-04-10 13:12:42 -04:00
|
|
|
trigger = shoot.re
|
2012-10-09 15:11:15 -04:00
|
|
|
elif mode == MODE_CONTINUOUS:
|
2013-03-30 12:28:41 -04:00
|
|
|
enable = CSRStorage()
|
|
|
|
self._csrs.insert(0, enable)
|
2013-04-10 13:12:42 -04:00
|
|
|
trigger = enable.storage
|
2012-10-09 15:11:15 -04:00
|
|
|
else:
|
|
|
|
raise ValueError
|
2013-04-10 13:12:42 -04:00
|
|
|
self.comb += self.busy.eq(self.source.stb)
|
|
|
|
stmts = [self.source.stb.eq(trigger)] + assigns
|
|
|
|
self.sync += [If(self.source.ack | ~self.source.stb, *stmts)]
|
2012-10-09 15:11:15 -04:00
|
|
|
|
2013-03-30 12:28:41 -04:00
|
|
|
def get_csrs(self):
|
|
|
|
return self._csrs
|
2012-10-09 15:11:15 -04:00
|
|
|
|
2013-04-10 13:12:42 -04:00
|
|
|
class Collector(Module, AutoCSR):
|
2012-10-04 12:22:22 -04:00
|
|
|
def __init__(self, layout, depth=1024):
|
2013-04-10 13:12:42 -04:00
|
|
|
self.sink = Sink(layout)
|
|
|
|
self.busy = Signal()
|
2012-10-04 12:22:22 -04:00
|
|
|
self._depth = depth
|
|
|
|
self._dw = sum(len(s) for s in self.token("sink").flatten())
|
|
|
|
|
2013-03-30 12:28:41 -04:00
|
|
|
self._r_wa = CSRStorage(bits_for(self._depth-1), write_from_dev=True)
|
|
|
|
self._r_wc = CSRStorage(bits_for(self._depth), write_from_dev=True, atomic_write=True)
|
|
|
|
self._r_ra = CSRStorage(bits_for(self._depth-1))
|
|
|
|
self._r_rd = CSRStatus(self._dw)
|
2013-04-10 13:12:42 -04:00
|
|
|
|
|
|
|
###
|
2012-10-04 12:22:22 -04:00
|
|
|
|
2012-11-26 12:27:59 -05:00
|
|
|
mem = Memory(self._dw, self._depth)
|
2013-04-10 13:12:42 -04:00
|
|
|
self.specials += mem
|
2012-11-26 12:27:59 -05:00
|
|
|
wp = mem.get_port(write_capable=True)
|
|
|
|
rp = mem.get_port()
|
2012-10-04 12:22:22 -04:00
|
|
|
|
2013-04-10 13:12:42 -04:00
|
|
|
self.comb += [
|
|
|
|
self.busy.eq(0),
|
|
|
|
|
2013-03-30 12:28:41 -04:00
|
|
|
If(self._r_wc.r != 0,
|
2012-10-04 12:22:22 -04:00
|
|
|
self.endpoints["sink"].ack.eq(1),
|
|
|
|
If(self.endpoints["sink"].stb,
|
2013-03-30 12:28:41 -04:00
|
|
|
self._r_wa.we.eq(1),
|
|
|
|
self._r_wc.we.eq(1),
|
2012-11-26 12:27:59 -05:00
|
|
|
wp.we.eq(1)
|
2012-10-04 12:22:22 -04:00
|
|
|
)
|
|
|
|
),
|
2013-03-30 12:28:41 -04:00
|
|
|
self._r_wa.dat_w.eq(self._r_wa.storage + 1),
|
|
|
|
self._r_wc.dat_w.eq(self._r_wc.storage - 1),
|
2012-10-04 12:22:22 -04:00
|
|
|
|
2013-03-30 12:28:41 -04:00
|
|
|
wp.adr.eq(self._r_wa.storage),
|
2013-04-01 16:15:23 -04:00
|
|
|
wp.dat_w.eq(self.token("sink").raw_bits()),
|
2012-10-04 12:22:22 -04:00
|
|
|
|
2013-03-30 12:28:41 -04:00
|
|
|
rp.adr.eq(self._r_ra.storage),
|
|
|
|
self._r_rd.status.eq(rp.dat_r)
|
2012-10-04 12:22:22 -04:00
|
|
|
]
|