From: Sebastien Bourdeauducq Date: Tue, 9 Oct 2012 19:11:15 +0000 (+0200) Subject: actorlib/spi: SingleGenerator X-Git-Tag: 24jan2021_ls180~2099^2~826 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=d329d40fe9b85cc19c40091d57d52a3f19a64611;p=litex.git actorlib/spi: SingleGenerator --- diff --git a/migen/actorlib/spi.py b/migen/actorlib/spi.py index e5565a5d..f5906e06 100644 --- a/migen/actorlib/spi.py +++ b/migen/actorlib/spi.py @@ -4,6 +4,81 @@ from migen.fhdl.structure import * from migen.bank.description import * from migen.flow.actor import * +# layout is a list of tuples, either: +# - (name, bv, [reset value], [alignment bits]) +# - (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 + +def _create_registers_assign(layout, target, atomic, prefix=""): + registers = [] + assigns = [] + for element in layout: + if isinstance(element[1], list): + r_registers, r_assigns = _create_registers_assign(element[1], + atomic, + getattr(target, element[0]), + element[0] + "_") + registers += r_registers + assigns += r_assigns + else: + name = element[0] + bv = element[1] + if len(element) > 2: + reset = element[2] + else: + reset = 0 + if len(element) > 3: + alignment = element[3] + else: + alignment = 0 + reg = RegisterField(prefix + name, bv.width + alignment, + reset=reset, atomic_write=atomic) + registers.append(reg) + assigns.append(getattr(target, name).eq(reg.field.r[alignment:])) + return registers, assigns + +(MODE_EXTERNAL, MODE_SINGLE_SHOT, MODE_CONTINUOUS) = range(3) + +class SingleGenerator(Actor): + def __init__(self, layout, mode): + self._mode = mode + super().__init__(("source", Source, _convert_layout(layout))) + self._registers, self._assigns = _create_registers_assign(layout, + self.token("source"), self._mode != MODE_SINGLE_SHOT) + if mode == MODE_EXTERNAL: + self.trigger = Signal() + elif mode == MODE_SINGLE_SHOT: + shoot = RegisterRaw("shoot") + self._registers.insert(0, shoot) + self.trigger = shoot.re + elif mode == MODE_CONTINUOUS: + enable = RegisterField("enable") + self._registers.insert(0, enable) + self.trigger = enable.field.r + else: + raise ValueError + + def get_registers(self): + return self._registers + + def get_fragment(self): + stb = self.endpoints["source"].stb + ack = self.endpoints["source"].ack + comb = [ + self.busy.eq(stb) + ] + stmts = [stb.eq(self.trigger)] + self._assigns + sync = [If(ack | ~stb, *stmts)] + return Fragment(comb, sync) + class Collector(Actor): def __init__(self, layout, depth=1024): super().__init__(("sink", Sink, layout))