from litex.soc.interconnect import csr
from litex.build.generic_platform import *
-# TODO: rewrite without FlipFlop
-
_layout = [
("adr", "adr_width", DIR_M_TO_S),
cached_data.eq(master.dat_r)
)
-
-@ResetInserter()
-@CEInserter()
-class FlipFlop(Module):
- def __init__(self, *args, **kwargs):
- self.d = Signal(*args, **kwargs)
- self.q = Signal(*args, **kwargs)
- self.sync += self.q.eq(self.d)
-
-
-class UpConverter(Module):
- """UpConverter
-
- This module up-converts wishbone accesses and bursts from a master interface
- to a wider slave interface. This allows efficient use wishbone bursts.
-
- Writes:
- Wishbone writes are cached before being written to the slave. Access to
- the slave is done at the end of a burst or when address reach end of burst
- addressing.
-
- Reads:
- Cache is refilled only at the beginning of each burst, the subsequent
- reads of a burst use the cached data.
-
- """
- def __init__(self, master, slave):
- dw_from = len(master.dat_r)
- dw_to = len(slave.dat_w)
- ratio = dw_to//dw_from
- ratiobits = log2_int(ratio)
-
- # # #
-
- write = Signal()
- evict = Signal()
- refill = Signal()
- read = Signal()
-
- address = FlipFlop(30)
- self.submodules += address
- self.comb += address.d.eq(master.adr)
-
- counter = Signal(max=ratio)
- counter_ce = Signal()
- counter_reset = Signal()
- self.sync += \
- If(counter_reset,
- counter.eq(0)
- ).Elif(counter_ce,
- counter.eq(counter + 1)
- )
- counter_offset = Signal(max=ratio)
- counter_done = Signal()
- self.comb += [
- counter_offset.eq(address.q),
- counter_done.eq((counter + counter_offset) == ratio-1)
- ]
-
- cached_data = Signal(dw_to)
- cached_sel = Signal(dw_to//8)
-
- end_of_burst = Signal()
- self.comb += end_of_burst.eq(~master.cyc |
- (master.stb & master.cyc & master.ack & ((master.cti == 7) | counter_done)))
-
-
- need_refill = FlipFlop(reset=1)
- self.submodules += need_refill
- self.comb += [
- need_refill.reset.eq(end_of_burst),
- need_refill.d.eq(0)
- ]
-
- # Main FSM
- self.submodules.fsm = fsm = FSM()
- fsm.act("IDLE",
- counter_reset.eq(1),
- If(master.stb & master.cyc,
- address.ce.eq(1),
- If(master.we,
- NextState("WRITE")
- ).Else(
- If(need_refill.q,
- NextState("REFILL")
- ).Else(
- NextState("READ")
- )
- )
- )
- )
- fsm.act("WRITE",
- If(master.stb & master.cyc,
- write.eq(1),
- counter_ce.eq(1),
- master.ack.eq(1),
- If(counter_done,
- NextState("EVICT")
- )
- ).Elif(~master.cyc,
- NextState("EVICT")
- )
- )
- fsm.act("EVICT",
- evict.eq(1),
- slave.stb.eq(1),
- slave.we.eq(1),
- slave.cyc.eq(1),
- slave.dat_w.eq(cached_data),
- slave.sel.eq(cached_sel),
- If(slave.ack,
- NextState("IDLE")
- )
- )
- fsm.act("REFILL",
- refill.eq(1),
- slave.stb.eq(1),
- slave.cyc.eq(1),
- If(slave.ack,
- need_refill.ce.eq(1),
- NextState("READ")
- )
- )
- fsm.act("READ",
- read.eq(1),
- If(master.stb & master.cyc,
- master.ack.eq(1)
- ),
- NextState("IDLE")
- )
-
- # Address
- self.comb += [
- slave.cti.eq(7), # we are not able to generate bursts since up-converting
- slave.adr.eq(address.q[ratiobits:])
- ]
-
- # Datapath
- cached_datas = [FlipFlop(dw_from) for i in range(ratio)]
- cached_sels = [FlipFlop(dw_from//8) for i in range(ratio)]
- self.submodules += cached_datas, cached_sels
-
- cases = {}
- for i in range(ratio):
- write_sel = Signal()
- cases[i] = write_sel.eq(1)
- self.comb += [
- cached_sels[i].reset.eq(counter_reset),
- If(write,
- cached_datas[i].d.eq(master.dat_w),
- ).Else(
- cached_datas[i].d.eq(slave.dat_r[dw_from*i:dw_from*(i+1)])
- ),
- cached_sels[i].d.eq(master.sel),
- If((write & write_sel) | refill,
- cached_datas[i].ce.eq(1),
- cached_sels[i].ce.eq(1)
- )
- ]
- self.comb += Case(counter + counter_offset, cases)
-
- cases = {}
- for i in range(ratio):
- cases[i] = master.dat_r.eq(cached_datas[i].q)
- self.comb += Case(address.q[:ratiobits], cases)
-
- self.comb += [
- cached_data.eq(Cat([cached_data.q for cached_data in cached_datas])),
- cached_sel.eq(Cat([cached_sel.q for cached_sel in cached_sels]))
- ]
-
-
class Converter(Module):
"""Converter
downconverter = DownConverter(master, slave)
self.submodules += downconverter
elif dw_from < dw_to:
- upconverter = UpConverter(master, slave)
- self.submodules += upconverter
+ raise NotImplementedError
else:
self.comb += master.connect(slave)