From: Florent Kermarrec Date: Mon, 26 Aug 2013 12:22:54 +0000 (+0200) Subject: wishbone : add DownConverter X-Git-Tag: 24jan2021_ls180~2099^2~471 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=628fa8ce9e8f3b375930e26dc2530eb767c535df;p=litex.git wishbone : add DownConverter --- diff --git a/migen/bus/wishbone.py b/migen/bus/wishbone.py index d7cd4001..bcc271bb 100644 --- a/migen/bus/wishbone.py +++ b/migen/bus/wishbone.py @@ -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