wishbone : add DownConverter
authorFlorent Kermarrec <florent@enjoy-digital.fr>
Mon, 26 Aug 2013 12:22:54 +0000 (14:22 +0200)
committerSebastien Bourdeauducq <sebastien@milkymist.org>
Mon, 26 Aug 2013 18:28:09 +0000 (20:28 +0200)
migen/bus/wishbone.py

index d7cd4001d0eb67edd0194f31ef159990324c3275..bcc271bb3342c8ed75aa69fc0b137b90d7026c11 100644 (file)
@@ -1,7 +1,8 @@
 from migen.fhdl.std import *
 from migen.genlib import roundrobin
 from migen.genlib.record import *
-from migen.genlib.misc import optree
+from migen.genlib.misc import optree, chooser
+from migen.genlib.fsm import FSM, NextState
 from migen.bus.transactions import *
 from migen.sim.generic import Proxy
 
@@ -111,6 +112,95 @@ class Crossbar(Module):
                for column, bus in zip(zip(*access), busses):
                        self.submodules += Arbiter(column, bus)
 
+class DownConverter(Module):
+       # DownConverter splits Wishbone accesses of N bits in M accesses of L bits where:
+       # N is the original data-width
+       # L is the target data-width
+       # M = N/L
+       def __init__(self, dw_i, dw_o):
+
+               self.wishbone_i = Interface(dw_i)
+               self.wishbone_o = Interface(dw_o)
+               self.ratio = dw_i//dw_o
+
+               ###
+               
+               rst = Signal()
+
+               # generate internal write and read ack
+               write_ack = Signal()
+               read_ack = Signal()
+               ack = Signal()
+               self.comb += [
+                       ack.eq(self.wishbone_o.cyc & self.wishbone_o.stb & self.wishbone_o.ack),
+                       write_ack.eq(ack & self.wishbone_o.we),
+                       read_ack.eq(ack & ~self.wishbone_o.we)
+               ]
+               
+               # accesses counter logic
+               cnt = Signal(max=self.ratio)
+               self.sync += If(rst, cnt.eq(0)).Elif(ack, cnt.eq(cnt + 1))
+               
+               # read data path
+               dat_r = Signal(dw_i)
+               self.sync += If(ack, dat_r.eq(Cat(self.wishbone_o.dat_r, dat_r[:dw_i-dw_o])))
+               
+               # write data path
+               dat_w = Signal(dw_i)
+               self.comb += dat_w.eq(self.wishbone_i.dat_w)
+               
+               # errors generation
+               err = Signal()
+               self.sync += If(ack, err.eq(self.wishbone_o.err))
+               
+               # direct connection of wishbone_i --> wishbone_o signals
+               for name, size, direction in self.wishbone_i.layout:
+                       if direction == DIR_M_TO_S and name not in ["adr", "dat_w"]:
+                               self.comb += getattr(self.wishbone_o, name).eq(getattr(self.wishbone_i, name))
+               
+               # adaptation of adr & dat signals
+               self.comb += [
+                       self.wishbone_o.adr[0:flen(cnt)].eq(cnt),
+                       self.wishbone_o.adr[flen(cnt):].eq(self.wishbone_i.adr)
+               ]
+               
+               self.comb += chooser(dat_w, cnt, self.wishbone_o.dat_w, reverse=True)
+               
+               # fsm
+               fsm = FSM(reset_state="IDLE")
+               self.submodules += fsm
+               
+               fsm.act("IDLE",
+                       If(write_ack,
+                               NextState("WRITE_ADAPT")
+                       ),
+                       If(read_ack,
+                               NextState("READ_ADAPT")
+                       )
+               )
+               
+               fsm.act("WRITE_ADAPT",
+                       If(write_ack & (cnt == self.ratio-1),
+                               NextState("IDLE"),
+                               rst.eq(1),
+                               self.wishbone_i.err.eq(err | self.wishbone_o.err),
+                               self.wishbone_i.ack.eq(1),
+                       )
+               )
+               
+               master_i_dat_r = Signal(dw_i)
+               self.comb += master_i_dat_r.eq(Cat(self.wishbone_o.dat_r, dat_r[:dw_i-dw_o]))
+
+               fsm.act("READ_ADAPT",
+                       If(read_ack & (cnt == self.ratio-1),
+                               NextState("IDLE"),
+                               rst.eq(1),
+                               self.wishbone_i.err.eq(err | self.wishbone_o.err),
+                               self.wishbone_i.ack.eq(1),
+                               self.wishbone_i.dat_r.eq(master_i_dat_r)
+                       )
+               )
+
 class Tap(Module):
        def __init__(self, bus, handler=print):
                self.bus = bus