Esempio n. 1
0
    def __init__(self):
        self.sink = Sink(ULPI_DATA_D)
        self.source = Source(ULPI_DATA_D)

        valid = Signal()
        data = Record(ULPI_DATA_D)


        self.comb += [
            If(self.sink.stb,
                self.sink.ack.eq(1),
            )]

        self.sync += [
            If(self.sink.stb,
                valid.eq(1),
                If(valid & ~self.source.ack,
                    data.rxcmd.eq(1),
                    data.d.eq(RXCMD_MAGIC_OVF),
                ).Else(
                    data.eq(self.sink.payload)
                )
            ).Elif(self.source.ack,
                valid.eq(0)
            )]

        self.comb += [
            self.source.stb.eq(valid),
            self.source.payload.eq(data)
            ]
Esempio n. 2
0
File: core.py Progetto: JQIamo/artiq
    def __init__(self, interface, counter, fifo_depth):
        data_width = rtlink.get_data_width(interface)
        fine_ts_width = rtlink.get_fine_ts_width(interface)

        ev_layout = []
        if data_width:
            ev_layout.append(("data", data_width))
        if interface.timestamped:
            ev_layout.append(("timestamp", counter.width + fine_ts_width))
        self.ev = Record(ev_layout)

        self.readable = Signal()
        self.re = Signal()

        self.overflow = Signal()  # pulsed

        # # #

        fifo = ClockDomainsRenamer({"read": "rsys", "write": "rio"})(
            AsyncFIFO(layout_len(ev_layout), fifo_depth))
        self.submodules += fifo
        fifo_in = Record(ev_layout)
        fifo_out = Record(ev_layout)
        self.comb += [
            fifo.din.eq(fifo_in.raw_bits()),
            fifo_out.raw_bits().eq(fifo.dout)
        ]

        # latency compensation
        if interface.delay:
            counter_rtio = Signal.like(counter.value_rtio, reset_less=True)
            self.sync.rtio += counter_rtio.eq(counter.value_rtio -
                                              (interface.delay + 1))
        else:
            counter_rtio = counter.value_rtio

        # FIFO write
        if data_width:
            self.comb += fifo_in.data.eq(interface.data)
        if interface.timestamped:
            if fine_ts_width:
                full_ts = Cat(interface.fine_ts, counter_rtio)
            else:
                full_ts = counter_rtio
            self.comb += fifo_in.timestamp.eq(full_ts)
        self.comb += fifo.we.eq(interface.stb)

        # FIFO read
        self.comb += [
            self.ev.eq(fifo_out),
            self.readable.eq(fifo.readable),
            fifo.re.eq(self.re)
        ]

        overflow_transfer = BlindTransfer()
        self.submodules += overflow_transfer
        self.comb += [
            overflow_transfer.i.eq(fifo.we & ~fifo.writable),
            self.overflow.eq(overflow_transfer.o),
        ]
Esempio n. 3
0
    def __init__(self, nchan=3, depth=8):
        self.valid_i = Signal()
        self.chan_synced = Signal()

        self._r_channels_synced = CSRStatus()

        lst_control = []
        all_control = Signal()
        for i in range(nchan):
            name = "data_in" + str(i)
            data_in = Record(channel_layout, name=name)
            setattr(self, name, data_in)
            name = "data_out" + str(i)
            data_out = Record(channel_layout, name=name)
            setattr(self, name, data_out)

            ###

            syncbuffer = RenameClockDomains(_SyncBuffer(layout_len(channel_layout), depth), "pix")
            self.submodules += syncbuffer
            self.comb += [syncbuffer.din.eq(data_in.raw_bits()), data_out.raw_bits().eq(syncbuffer.dout)]
            is_control = Signal()
            self.comb += [is_control.eq(~data_out.de), syncbuffer.re.eq(~is_control | all_control)]
            lst_control.append(is_control)

        some_control = Signal()
        self.comb += [all_control.eq(optree("&", lst_control)), some_control.eq(optree("|", lst_control))]
        self.sync.pix += If(~self.valid_i, self.chan_synced.eq(0)).Else(
            If(some_control, If(all_control, self.chan_synced.eq(1)).Else(self.chan_synced.eq(0)))
        )
        self.specials += MultiReg(self.chan_synced, self._r_channels_synced.status)
Esempio n. 4
0
    def __init__(self):
        self.sink = Sink(ULPI_DATA_D)
        self.source = Source(ULPI_DATA_D)

        self._ctl = CSRStorageEx(1)
        snapshot = self._ctl.re
        reset = self._ctl.storage[0]
        self._num_ovf = Perfcounter(snapshot, reset)
        self._num_total = Perfcounter(snapshot, reset)

        self.comb += If(self.sink.stb, self._num_total.inc())
        self.comb += If(self.source.stb & ~self.source.ack,
                        self._num_ovf.inc())

        valid = Signal()
        data = Record(ULPI_DATA_D)

        self.comb += [If(
            self.sink.stb,
            self.sink.ack.eq(1),
        )]

        self.sync += [
            If(
                self.sink.stb, valid.eq(1),
                If(
                    valid & ~self.source.ack,
                    data.rxcmd.eq(1),
                    data.d.eq(RXCMD_MAGIC_OVF),
                ).Else(data.eq(self.sink.payload))).Elif(
                    self.source.ack, valid.eq(0))
        ]

        self.comb += [self.source.stb.eq(valid), self.source.payload.eq(data)]
Esempio n. 5
0
File: core.py Progetto: cr1901/artiq
    def __init__(self, interface, counter, fifo_depth):
        data_width = rtlink.get_data_width(interface)
        fine_ts_width = rtlink.get_fine_ts_width(interface)

        ev_layout = []
        if data_width:
            ev_layout.append(("data", data_width))
        if interface.timestamped:
            ev_layout.append(("timestamp", counter.width + fine_ts_width))
        self.ev = Record(ev_layout)

        self.readable = Signal()
        self.re = Signal()
        
        self.overflow = Signal()  # pulsed

        # # #

        fifo = ClockDomainsRenamer({"read": "rsys", "write": "rio"})(
            AsyncFIFO(layout_len(ev_layout), fifo_depth))
        self.submodules += fifo
        fifo_in = Record(ev_layout)
        fifo_out = Record(ev_layout)
        self.comb += [
            fifo.din.eq(fifo_in.raw_bits()),
            fifo_out.raw_bits().eq(fifo.dout)
        ]

        # FIFO write
        if data_width:
            self.comb += fifo_in.data.eq(interface.data)
        if interface.timestamped:
            if fine_ts_width:
                full_ts = Cat(interface.fine_ts, counter.value_rio)
            else:
                full_ts = counter.value_rio
            self.comb += fifo_in.timestamp.eq(full_ts)
        self.comb += fifo.we.eq(interface.stb)

        # FIFO read
        self.comb += [
            self.ev.eq(fifo_out),
            self.readable.eq(fifo.readable),
            fifo.re.eq(self.re)
        ]

        overflow_sync = PulseSynchronizer("rio", "rsys")
        overflow_ack_sync = PulseSynchronizer("rsys", "rio")
        self.submodules += overflow_sync, overflow_ack_sync
        overflow_blind = Signal()
        self.comb += overflow_sync.i.eq(fifo.we & ~fifo.writable & ~overflow_blind)
        self.sync.rio += [
            If(fifo.we & ~fifo.writable, overflow_blind.eq(1)),
            If(overflow_ack_sync.o, overflow_blind.eq(0))
        ]
        self.comb += [
            overflow_ack_sync.i.eq(overflow_sync.o),
            self.overflow.eq(overflow_sync.o)
        ]
Esempio n. 6
0
File: dma.py Progetto: gbraad/misoc
 def __init__(self, port, lasmim_dma_wr, lasmim_dma_rd):
     self.submodules.writer = LiteUSBDMAWriter(lasmim_dma_wr)
     self.submodules.reader = LiteUSBDMAReader(lasmim_dma_rd, port.tag)
     self.submodules.ev = SharedIRQ(self.writer.ev, self.reader.ev)
     self.comb += [
         Record.connect(port.source, self.writer.sink),
         Record.connect(self.reader.source, port.sink),
     ]
Esempio n. 7
0
File: dma.py Progetto: olofk/misoc
 def __init__(self, port, lasmim_dma_wr, lasmim_dma_rd):
     self.submodules.writer = LiteUSBDMAWriter(lasmim_dma_wr)
     self.submodules.reader = LiteUSBDMAReader(lasmim_dma_rd, port.tag)
     self.submodules.ev = SharedIRQ(self.writer.ev, self.reader.ev)
     self.comb += [
         Record.connect(port.source, self.writer.sink),
         Record.connect(self.reader.source, port.sink),
     ]
Esempio n. 8
0
    def __init__(self, interface, counter, fifo_depth):
        data_width = rtlink.get_data_width(interface)
        fine_ts_width = rtlink.get_fine_ts_width(interface)

        ev_layout = []
        if data_width:
            ev_layout.append(("data", data_width))
        if interface.timestamped:
            ev_layout.append(("timestamp", counter.width + fine_ts_width))
        self.ev = Record(ev_layout)

        self.readable = Signal()
        self.re = Signal()

        self.overflow = Signal()  # pulsed

        # # #

        fifo = RenameClockDomains(AsyncFIFO(ev_layout, fifo_depth), {
            "read": "rsys",
            "write": "rio"
        })
        self.submodules += fifo

        # FIFO write
        if data_width:
            self.comb += fifo.din.data.eq(interface.data)
        if interface.timestamped:
            if fine_ts_width:
                full_ts = Cat(interface.fine_ts, counter.value_rio)
            else:
                full_ts = counter.value_rio
            self.comb += fifo.din.timestamp.eq(full_ts)
        self.comb += fifo.we.eq(interface.stb)

        # FIFO read
        self.comb += [
            self.ev.eq(fifo.dout),
            self.readable.eq(fifo.readable),
            fifo.re.eq(self.re)
        ]

        overflow_sync = PulseSynchronizer("rio", "rsys")
        overflow_ack_sync = PulseSynchronizer("rsys", "rio")
        self.submodules += overflow_sync, overflow_ack_sync
        overflow_blind = Signal()
        self.comb += overflow_sync.i.eq(fifo.we & ~fifo.writable
                                        & ~overflow_blind)
        self.sync.rio += [
            If(fifo.we & ~fifo.writable, overflow_blind.eq(1)),
            If(overflow_ack_sync.o, overflow_blind.eq(0))
        ]
        self.comb += [
            overflow_ack_sync.i.eq(overflow_sync.o),
            self.overflow.eq(overflow_sync.o)
        ]
Esempio n. 9
0
    def __init__(self):

        self.busy = Signal()
        self.sink = Sink(CMD_REC)
        self.source = Source([('d',8), ('last',1)])

        sm = FSM(reset_state="IDLE")
        self.submodules += sm

        self.comb += [
            self.source.stb.eq(0),
            self.source.payload.last.eq(0)
            ]


        ssum = Signal(8)

        token_next = Record(CMD_REC)
        token = Record(CMD_REC)
        self.comb += token_next.eq(token)
        self.sync += token.eq(token_next)

        sm.act("IDLE",
                If(self.sink.stb,
                    self.sink.ack.eq(1),
                    token_next.eq(self.sink.payload),
                    NextState('c0')))

        _outs = [
            0x55,
            Cat(token.a[8:14], 0, token.wr),
            token.a[0:8],
            token.d,
            ssum
            ]

        s = _outs[0]
        for i in _outs[1:-1]:
            s = s + i
        self.sync += ssum.eq(s)


        for c, v in enumerate(_outs):
            _last = 1 if c == len(_outs) - 1 else 0
            _next = "IDLE" if _last else "c%d" % (c + 1)
            sm.act("c%d" % c,
                    self.source.stb.eq(1),
                    self.source.payload.d.eq(v),
                    self.source.payload.last.eq(_last),
                    If(self.source.ack,
                        NextState(_next)
                        ))
Esempio n. 10
0
    def __init__(self):
        self.busy=Signal()
        self.sink = Sink([('d',8)])
        self.source = Source(CMD_REC)

        sm = FSM(reset_state="IDLE")
        self.submodules += sm

        # Basic checksum

        token = self.source.payload
        token_next = Record(CMD_REC)

        self.sync += token.eq(token_next)
        self.comb += token_next.eq(token)



        sm.act("IDLE",
                self.sink.ack.eq(1),
                If(self.sink.stb,
                    If(self.sink.payload.d == 0x55,
                        NextState("ADRH")
                    )))

        def parse_state(st, to, *update):
            sm.act(st, 
                self.sink.ack.eq(1),
                If(self.sink.stb,
                    NextState(to),
                    *update
                    ))

        parse_state('ADRH', 'ADRL', 
                token_next.wr.eq(self.sink.payload.d[7]), 
                token_next.a[8:14].eq(self.sink.payload.d[:6]))

        parse_state('ADRL', 'DATA',  token_next.a[0:8].eq(self.sink.payload.d)),
        parse_state('DATA', 'CKSUM', token_next.d.eq(self.sink.payload.d)),

        sm.act("CKSUM",
                self.sink.ack.eq(1),
                If(self.sink.stb,
                        NextState('ISSUE')
                )    
        )

        sm.act("ISSUE",
                self.source.stb.eq(1),
                If(self.source.ack,
                    NextState('IDLE')))
Esempio n. 11
0
    def __init__(self):
        self.busy=Signal()
        self.sink = Sink([('d',8)])
        self.source = Source(CMD_REC)

        sm = FSM(reset_state="IDLE")
        self.submodules += sm

        # Basic checksum

        token = self.source.payload
        token_next = Record(CMD_REC)

        self.sync += token.eq(token_next)
        self.comb += token_next.eq(token)



        sm.act("IDLE",
                self.sink.ack.eq(1),
                If(self.sink.stb,
                    If(self.sink.payload.d == 0x55,
                        NextState("ADRH")
                    )))

        def parse_state(st, to, *update):
            sm.act(st, 
                self.sink.ack.eq(1),
                If(self.sink.stb,
                    NextState(to),
                    *update
                    ))

        parse_state('ADRH', 'ADRL', 
                token_next.wr.eq(self.sink.payload.d[7]), 
                token_next.a[8:14].eq(self.sink.payload.d[:6]))

        parse_state('ADRL', 'DATA',  token_next.a[0:8].eq(self.sink.payload.d)),
        parse_state('DATA', 'CKSUM', token_next.d.eq(self.sink.payload.d)),

        sm.act("CKSUM",
                self.sink.ack.eq(1),
                If(self.sink.stb,
                        NextState('ISSUE')
                )    
        )

        sm.act("ISSUE",
                self.source.stb.eq(1),
                If(self.source.ack,
                    NextState('IDLE')))
Esempio n. 12
0
File: dma.py Progetto: JQIamo/artiq
    def __init__(self, stream_slicer):
        self.source = stream.Endpoint(record_layout)
        self.end_marker_found = Signal()
        self.flush = Signal()

        hdrlen = (layout_len(record_layout) - 512)//8
        record_raw = Record(record_layout)
        self.comb += [
            record_raw.raw_bits().eq(stream_slicer.source),
            self.source.channel.eq(record_raw.channel),
            self.source.timestamp.eq(record_raw.timestamp),
            self.source.address.eq(record_raw.address),
            Case(record_raw.length,
                {hdrlen+i: self.source.data.eq(record_raw.data[:i*8])
                 for i in range(1, 512//8+1)}),
        ]

        fsm = FSM(reset_state="FLOWING")
        self.submodules += fsm

        fsm.act("FLOWING",
            If(stream_slicer.source_stb,
                If(record_raw.length == 0,
                    NextState("END_MARKER_FOUND")
                ).Else(
                    self.source.stb.eq(1)
                )
            ),
            If(self.source.ack,
                stream_slicer.source_consume.eq(record_raw.length)
            )
        )
        fsm.act("END_MARKER_FOUND",
            self.end_marker_found.eq(1),
            If(self.flush,
                stream_slicer.flush.eq(1),
                NextState("WAIT_FLUSH")
            )
        )
        fsm.act("WAIT_FLUSH",
            If(stream_slicer.flush_done,
                NextState("SEND_EOP")
            )
        )
        fsm.act("SEND_EOP",
            self.source.eop.eq(1),
            self.source.stb.eq(1),
            If(self.source.ack, NextState("FLOWING"))
        )
Esempio n. 13
0
    def __init__(self, stream_slicer):
        self.source = stream.Endpoint(record_layout)
        self.end_marker_found = Signal()
        self.flush = Signal()

        hdrlen = (layout_len(record_layout) - 512)//8
        record_raw = Record(record_layout)
        self.comb += [
            record_raw.raw_bits().eq(stream_slicer.source),
            self.source.channel.eq(record_raw.channel),
            self.source.timestamp.eq(record_raw.timestamp),
            self.source.address.eq(record_raw.address),
            Case(record_raw.length,
                {hdrlen+i: self.source.data.eq(record_raw.data[:i*8])
                 for i in range(1, 512//8+1)}),
        ]

        fsm = FSM(reset_state="FLOWING")
        self.submodules += fsm

        fsm.act("FLOWING",
            If(stream_slicer.source_stb,
                If(record_raw.length == 0,
                    NextState("END_MARKER_FOUND")
                ).Else(
                    self.source.stb.eq(1)
                )
            ),
            If(self.source.ack,
                stream_slicer.source_consume.eq(record_raw.length)
            )
        )
        fsm.act("END_MARKER_FOUND",
            self.end_marker_found.eq(1),
            If(self.flush,
                stream_slicer.flush.eq(1),
                NextState("WAIT_FLUSH")
            )
        )
        fsm.act("WAIT_FLUSH",
            If(stream_slicer.flush_done,
                NextState("SEND_EOP")
            )
        )
        fsm.act("SEND_EOP",
            self.source.eop.eq(1),
            self.source.stb.eq(1),
            If(self.source.ack, NextState("FLOWING"))
        )
Esempio n. 14
0
class DownscalerCore(Module):
	def __init__(self, base_layout, N, res_bits):
		self.init = Signal()
		self.ready = Signal()
		self.ce = Signal()

		self.hres_in = Signal(res_bits)
		self.vres_in = Signal(res_bits)
		self.i = Record([("w"+str(i), base_layout) for i in range(N)])

		self.hres_out = Signal(res_bits)
		self.vres_out = Signal(res_bits)
		self.o = Record([("w"+str(i), base_layout) for i in range(N)])
		self.stb = Signal()

		###

		packbits = log2_int(N)
		hcounter = Signal(res_bits-packbits)
		self.sync += If(self.init,
				hcounter.eq(self.hres_in[packbits:] - 1)
			).Elif(self.ce,
				If(hcounter == 0,
					hcounter.eq(self.hres_in[packbits:] - 1)
				).Else(
					hcounter.eq(hcounter - 1)
				)
			)
		self.submodules.vselector = InsertReset(InsertCE(Chopper(res_bits)))
		self.comb += [
			self.vselector.reset.eq(self.init),
			self.vselector.ce.eq(self.ce & (hcounter == 0)),
			self.vselector.p.eq(self.vres_out),
			self.vselector.q.eq(self.vres_in)
		]

		self.submodules.hselector = MultiChopper(N, res_bits)
		self.comb += [
			self.hselector.init.eq(self.init),
			self.ready.eq(self.hselector.ready),
			self.hselector.next.eq(self.ce),
			self.hselector.p.eq(self.hres_out),
			self.hselector.q.eq(self.hres_in)
		]

		self.submodules.compacter = InsertReset(InsertCE(Compacter(base_layout, N)))
		self.submodules.packer = InsertReset(InsertCE(Packer(base_layout, N)))
		self.comb += [
			self.compacter.reset.eq(self.init),
			self.packer.reset.eq(self.init),
			self.compacter.ce.eq(self.ce),
			self.packer.ce.eq(self.ce),

			self.compacter.i.eq(self.i),
			self.compacter.sel.eq(self.hselector.chopper & Replicate(self.vselector.chopper, N)),
			self.packer.i.eq(self.compacter.o),
			self.packer.count.eq(self.compacter.count),
			self.o.eq(self.packer.o),
			self.stb.eq(self.packer.stb)
		]
Esempio n. 15
0
    def request(self, name, number=None):
        resource = _lookup(self.available, name, number)
        rt, ri = _resource_type(resource)
        if number is None:
            resource_name = name
        else:
            resource_name = name + str(number)
        if isinstance(rt, int):
            obj = Signal(rt, name_override=resource_name)
        else:
            obj = Record(rt, name=resource_name)
            for name, inverted in ri:
                if inverted:
                    getattr(obj, name).inverted = True

        for element in resource[2:]:
            if isinstance(element, Inverted):
                if isinstance(obj, Signal):
                    obj.inverted = True
            if isinstance(element, PlatformInfo):
                obj.platform_info = element.info
                break

        self.available.remove(resource)
        self.matched.append((resource, obj))
        return obj
Esempio n. 16
0
    def getPort(self):
        r = Record(
            sdramHostIf(flen(self.downstream.d_read),
                        flen(self.downstream.i_addr)))

        self.ports.append(r)
        return r
Esempio n. 17
0
 def __init__(self):
     self.submodules.master = wishbone.Initiator(self.gen_reads())
     self.pads = Record([("cs_n", 1), ("clk", 1), ("dq", 4)])
     self.submodules.slave = SpiFlash(self.pads)
     self.submodules.tap = wishbone.Tap(self.slave.bus)
     self.submodules.intercon = wishbone.InterconnectPointToPoint(
             self.master.bus, self.slave.bus)
     self.cycle = 0
Esempio n. 18
0
	def __init__(self, width_or_layout, depth):
		self.we = Signal()
		self.writable = Signal() # not full
		self.re = Signal()
		self.readable = Signal() # not empty

		if isinstance(width_or_layout, list):
			self.din = Record(width_or_layout)
			self.dout = Record(width_or_layout)
			self.din_bits = self.din.raw_bits()
			self.dout_bits = self.dout.raw_bits()
			self.width = layout_len(width_or_layout)
		else:
			self.din = Signal(width_or_layout)
			self.dout = Signal(width_or_layout)
			self.din_bits = self.din
			self.dout_bits = self.dout
			self.width = width_or_layout
Esempio n. 19
0
    def __init__(self, interface, counter, fifo_depth):
        data_width = rtlink.get_data_width(interface)
        fine_ts_width = rtlink.get_fine_ts_width(interface)

        ev_layout = []
        if data_width:
            ev_layout.append(("data", data_width))
        if interface.timestamped:
            ev_layout.append(("timestamp", counter.width + fine_ts_width))
        self.ev = Record(ev_layout)

        self.readable = Signal()
        self.re = Signal()

        self.overflow = Signal()  # pulsed

        # # #

        fifo = ClockDomainsRenamer({
            "read": "rsys",
            "write": "rio"
        })(AsyncFIFO(layout_len(ev_layout), fifo_depth))
        self.submodules += fifo
        fifo_in = Record(ev_layout)
        fifo_out = Record(ev_layout)
        self.comb += [
            fifo.din.eq(fifo_in.raw_bits()),
            fifo_out.raw_bits().eq(fifo.dout)
        ]

        # FIFO write
        if data_width:
            self.comb += fifo_in.data.eq(interface.data)
        if interface.timestamped:
            if fine_ts_width:
                full_ts = Cat(interface.fine_ts, counter.value_rtio)
            else:
                full_ts = counter.value_rtio
            self.comb += fifo_in.timestamp.eq(full_ts)
        self.comb += fifo.we.eq(interface.stb)

        # FIFO read
        self.comb += [
            self.ev.eq(fifo_out),
            self.readable.eq(fifo.readable),
            fifo.re.eq(self.re)
        ]

        overflow_transfer = _BlindTransfer()
        self.submodules += overflow_transfer
        self.comb += [
            overflow_transfer.i.eq(fifo.we & ~fifo.writable),
            self.overflow.eq(overflow_transfer.o),
        ]
Esempio n. 20
0
    def __init__(self, nimages, pack_factor, latency):
        epixel_layout = pixel_layout(pack_factor)
        sink_layout = [("i"+str(i), epixel_layout) for i in range(nimages)]
        self.sink = Sink(sink_layout)
        self.source = Source(epixel_layout)
        factors = []
        for i in range(nimages):
            name = "f"+str(i)
            csr = CSRStorage(8, name=name)
            setattr(self, name, csr)
            factors.append(csr.storage)
        PipelinedActor.__init__(self, latency)

        ###

        sink_registered = Record(sink_layout)
        self.sync += If(self.pipe_ce, sink_registered.eq(self.sink.payload))

        imgs = [getattr(sink_registered, "i"+str(i)) for i in range(nimages)]
        outval = Record(epixel_layout)
        for e in epixel_layout:
            name = e[0]
            inpixs = [getattr(img, name) for img in imgs]
            outpix = getattr(outval, name)
            for component in ["r", "g", "b"]:
                incomps = [getattr(pix, component) for pix in inpixs]
                outcomp = getattr(outpix, component)
                outcomp_full = Signal(19)
                self.comb += [
                    outcomp_full.eq(sum(incomp*factor for incomp, factor in zip(incomps, factors))),
                    If(outcomp_full[18],
                        outcomp.eq(2**10 - 1)  # saturate on overflow
                    ).Else(
                        outcomp.eq(outcomp_full[8:18])
                    )
                ]

        pipe_stmts = []
        for i in range(latency-1):
            new_outval = Record(epixel_layout)
            pipe_stmts.append(new_outval.eq(outval))
            outval = new_outval
        self.sync += If(self.pipe_ce, pipe_stmts)
        self.comb += self.source.payload.eq(outval)
Esempio n. 21
0
 def __init__(self, **kwargs):
     self.ctrl_pads = Record(self.ctrl_layout)
     self.ctrl_pads.board.reset = 0b1111  # board-inverted
     self.ctrl_pads.frame.reset = 0b111  # pullup on cs_n
     self.ctrl_pads.trigger.reset = 1
     self.submodules.dut = ResetInserter(["sys"])(PdqBase(
         self.ctrl_pads, **kwargs))
     # self.comb += self.dut.reset_sys.eq(self.dut.comm.rg.reset)
     self.outputs = []
     self.aux = []
Esempio n. 22
0
    def __init__(self, phy,
                 tx_fifo_depth=16,
                 rx_fifo_depth=16,
                 phy_cd="sys"):
        self._rxtx = CSR(8)
        self._txfull = CSRStatus()
        self._rxempty = CSRStatus()

        self.submodules.ev = EventManager()
        self.ev.tx = EventSourceProcess()
        self.ev.rx = EventSourceProcess()
        self.ev.finalize()

        # # #

        # TX
        tx_fifo = _get_uart_fifo(tx_fifo_depth, source_cd=phy_cd)
        self.submodules += tx_fifo

        self.comb += [
            tx_fifo.sink.stb.eq(self._rxtx.re),
            tx_fifo.sink.data.eq(self._rxtx.r),
            self._txfull.status.eq(~tx_fifo.sink.ack),
            Record.connect(tx_fifo.source, phy.sink),
            # Generate TX IRQ when tx_fifo becomes non-full
            self.ev.tx.trigger.eq(~tx_fifo.sink.ack)
        ]


        # RX
        rx_fifo = _get_uart_fifo(rx_fifo_depth, sink_cd=phy_cd)
        self.submodules += rx_fifo


        self.comb += [
            Record.connect(phy.source, rx_fifo.sink),
            self._rxempty.status.eq(~rx_fifo.source.stb),
            self._rxtx.w.eq(rx_fifo.source.data),
            rx_fifo.source.ack.eq(self.ev.rx.clear),
            # Generate RX IRQ when tx_fifo becomes non-empty
            self.ev.rx.trigger.eq(~rx_fifo.source.stb)
        ]
Esempio n. 23
0
def test_fast_serial_tx():
    def feed_in(dut, pads, txns):
        for data, port in txns:
            yield dut.sink.payload.data.eq(data)
            yield dut.sink.payload.port.eq(port)
            yield dut.sink.stb.eq(1)
            yield
            while not (yield dut.sink.ack):
                yield
            yield dut.sink.stb.eq(0)

    def test_out(dut, pads, txns):
        for data, port in txns:
            while not (not (yield pads.di) and (yield pads.cts)):
                yield
            rx_data = 0
            for i in range(8):
                yield
                rx_data |= (yield pads.di) << i
            yield
            rx_port = (yield pads.di)
            yield

            assert rx_data == data
            assert rx_port == port

    def drive_cts(dut, pads):
        yield pads.cts.eq(0)
        for i in range(5):
            yield
        yield pads.cts.eq(1)

    txns = [
        (0b01010101, 0),
        (0x00, 1),
    ]

    pads = Record([
        ("di", 1),
        ("clk", 1),
        ("di", 1),
        ("cts", 1),
    ])

    dut = FastSerialTX(pads)

    run_simulation(dut, [
        feed_in(dut, pads, txns),
        test_out(dut, pads, txns),
        drive_cts(dut, pads),
    ],
                   vcd_name="serial_tx.vcd")
Esempio n. 24
0
def create_rbus(fine_ts_bits, pads, output_only_pads):
    rbus = []
    for pad in pads:
        layout = [("o_stb", 1), ("o_value", 2)]
        if fine_ts_bits:
            layout.append(("o_fine_ts", fine_ts_bits))
        if pad not in output_only_pads:
            layout += [("oe", 1), ("i_stb", 1), ("i_value", 1),
                       ("i_pileup", 1)]
            if fine_ts_bits:
                layout.append(("i_fine_ts", fine_ts_bits))
        rbus.append(Record(layout))
    return rbus
	def __init__(self):
		# in pix clock domain
		self.valid_i = Signal()
		self.vsync = Signal()
		self.de = Signal()
		self.r = Signal(8)
		self.g = Signal(8)
		self.b = Signal(8)

		# in sys clock domain
		self.frame = Source(frame_layout)
		self.busy = Signal()

		###

		fifo_stb = Signal()
		fifo_in = Record(frame_layout)
		self.comb += [
			fifo_stb.eq(self.valid_i & self.de),
			fifo_in.r.eq(self.r),
			fifo_in.g.eq(self.g),
			fifo_in.b.eq(self.b),
		]
		vsync_r = Signal()
		self.sync.pix += [
			If(self.vsync & ~vsync_r, fifo_in.parity.eq(~fifo_in.parity)),
			vsync_r.eq(self.vsync)
		]

		fifo = AsyncFIFO(layout_len(frame_layout), 256)
		self.add_submodule(fifo, {"write": "pix", "read": "sys"})
		self.comb += [
			fifo.we.eq(fifo_stb),
			fifo.din.eq(fifo_in.raw_bits()),
			self.frame.stb.eq(fifo.readable),
			self.frame.payload.raw_bits().eq(fifo.dout),
			fifo.re.eq(self.frame.ack),
			self.busy.eq(0)
		]
Esempio n. 26
0
    def __init__(self):
        self.sink = Sink(ULPI_DATA_D)
        self.source = Source(ULPI_DATA_D)

        self._ctl = CSRStorageEx(1)
        snapshot = self._ctl.re
        reset = self._ctl.storage[0]
        self._num_ovf = Perfcounter(snapshot, reset)
        self._num_total = Perfcounter(snapshot, reset)

        self.comb += If(self.sink.stb, self._num_total.inc())
        self.comb += If(self.source.stb &~ self.source.ack, self._num_ovf.inc())

        valid = Signal()
        data = Record(ULPI_DATA_D)


        self.comb += [
            If(self.sink.stb,
                self.sink.ack.eq(1),
            )]

        self.sync += [
            If(self.sink.stb,
                valid.eq(1),
                If(valid & ~self.source.ack,
                    data.rxcmd.eq(1),
                    data.d.eq(RXCMD_MAGIC_OVF),
                ).Else(
                    data.eq(self.sink.payload)
                )
            ).Elif(self.source.ack,
                valid.eq(0)
            )]

        self.comb += [
            self.source.stb.eq(valid),
            self.source.payload.eq(data)
            ]
Esempio n. 27
0
    def __init__(self, phy,
                 tx_fifo_depth=16,
                 rx_fifo_depth=16):
        self._rxtx = CSR(8)
        self._txfull = CSRStatus()
        self._rxempty = CSRStatus()

        self.submodules.ev = EventManager()
        self.ev.tx = EventSourceProcess()
        self.ev.rx = EventSourceProcess()
        self.ev.finalize()

        # # #

        tx_fifo = SyncFIFO([("data", 8)], tx_fifo_depth)
        self.submodules += tx_fifo
        self.comb += [
            tx_fifo.sink.stb.eq(self._rxtx.re),
            tx_fifo.sink.data.eq(self._rxtx.r),
            self._txfull.status.eq(~tx_fifo.sink.ack),
            Record.connect(tx_fifo.source, phy.sink)
        ]

        rx_fifo = SyncFIFO([("data", 8)], rx_fifo_depth)
        self.submodules += rx_fifo
        self.comb += [
            Record.connect(phy.source, rx_fifo.sink),
            self._rxempty.status.eq(~rx_fifo.source.stb),
            self._rxtx.w.eq(rx_fifo.source.data),
            rx_fifo.source.ack.eq(self.ev.rx.clear)
        ]

        self.comb += [
            # Generate TX IRQ when tx_fifo becomes empty
            self.ev.tx.trigger.eq(tx_fifo.source.stb),
            # Generate RX IRQ when rx_fifo becomes non-empty
            self.ev.rx.trigger.eq(~rx_fifo.source.stb),
        ]
Esempio n. 28
0
 def request(self, name, number=None):
     resource = _lookup(self.available, name, number)
     rt = _resource_type(resource)
     if isinstance(rt, int):
         obj = Signal(rt, name_override=resource[0])
     else:
         obj = Record(rt, name=resource[0])
     for element in resource[2:]:
         if isinstance(element, PlatformInfo):
             obj.platform_info = element.info
             break
     self.available.remove(resource)
     self.matched.append((resource, obj))
     return obj
Esempio n. 29
0
    def __init__(self):
        self.valid_i = Signal()
        self.data_in0 = Record(channel_layout)
        self.data_in1 = Record(channel_layout)
        self.data_in2 = Record(channel_layout)

        self.valid_o = Signal()
        self.de = Signal()
        self.hsync = Signal()
        self.vsync = Signal()
        self.r = Signal(8)
        self.g = Signal(8)
        self.b = Signal(8)

        ###

        de = self.data_in0.de
        de_r = Signal()
        c = self.data_in0.c
        c_polarity = Signal(2)
        c_out = Signal(2)

        self.comb += [
            self.de.eq(de_r),
            self.hsync.eq(c_out[0]),
            self.vsync.eq(c_out[1])
        ]

        self.sync.pix += [
            self.valid_o.eq(self.valid_i),
            self.r.eq(self.data_in2.d),
            self.g.eq(self.data_in1.d),
            self.b.eq(self.data_in0.d),
            de_r.eq(de),
            If(de_r & ~de, c_polarity.eq(c),
               c_out.eq(0)).Else(c_out.eq(c ^ c_polarity))
        ]
Esempio n. 30
0
    def __init__(self):

        self.busy = Signal()
        self.sink = Sink(CMD_REC)
        self.source = Source([('d',8), ('last',1)])

        sm = FSM(reset_state="IDLE")
        self.submodules += sm

        self.comb += [
            self.source.stb.eq(0),
            self.source.payload.last.eq(0)
            ]


        ssum = Signal(8)

        token_next = Record(CMD_REC)
        token = Record(CMD_REC)
        self.comb += token_next.eq(token)
        self.sync += token.eq(token_next)

        sm.act("IDLE",
                If(self.sink.stb,
                    self.sink.ack.eq(1),
                    token_next.eq(self.sink.payload),
                    NextState('c0')))

        _outs = [
            0x55,
            Cat(token.a[8:14], 0, token.wr),
            token.a[0:8],
            token.d,
            ssum
            ]

        s = _outs[0]
        for i in _outs[1:-1]:
            s = s + i
        self.sync += ssum.eq(s)


        for c, v in enumerate(_outs):
            _last = 1 if c == len(_outs) - 1 else 0
            _next = "IDLE" if _last else "c%d" % (c + 1)
            sm.act("c%d" % c,
                    self.source.stb.eq(1),
                    self.source.payload.d.eq(v),
                    self.source.payload.last.eq(_last),
                    If(self.source.ack,
                        NextState(_next)
                        ))
Esempio n. 31
0
    def __init__(self, phy, tx_fifo_depth=16, rx_fifo_depth=16):
        self._rxtx = CSR(8)
        self._txfull = CSRStatus()
        self._rxempty = CSRStatus()

        self.submodules.ev = EventManager()
        self.ev.tx = EventSourceProcess()
        self.ev.rx = EventSourceProcess()
        self.ev.finalize()

        # # #

        tx_fifo = SyncFIFO([("data", 8)], tx_fifo_depth)
        self.submodules += tx_fifo
        self.comb += [
            tx_fifo.sink.stb.eq(self._rxtx.re),
            tx_fifo.sink.data.eq(self._rxtx.r),
            self._txfull.status.eq(~tx_fifo.sink.ack),
            Record.connect(tx_fifo.source, phy.sink)
        ]

        rx_fifo = SyncFIFO([("data", 8)], rx_fifo_depth)
        self.submodules += rx_fifo
        self.comb += [
            Record.connect(phy.source, rx_fifo.sink),
            self._rxempty.status.eq(~rx_fifo.source.stb),
            self._rxtx.w.eq(rx_fifo.source.data),
            rx_fifo.source.ack.eq(self.ev.rx.clear)
        ]

        self.comb += [
            # Generate TX IRQ when tx_fifo becomes empty
            self.ev.tx.trigger.eq(tx_fifo.source.stb),
            # Generate RX IRQ when rx_fifo becomes non-empty
            self.ev.rx.trigger.eq(~rx_fifo.source.stb),
        ]
Esempio n. 32
0
    def __init__(self):
        self.sink = Sink(ULPI_DATA_D)
        self.source = Source(ULPI_DATA_D)

        valid = Signal()
        data = Record(ULPI_DATA_D)

        self.comb += [If(
            self.sink.stb,
            self.sink.ack.eq(1),
        )]

        self.sync += [
            If(
                self.sink.stb, valid.eq(1),
                If(
                    valid & ~self.source.ack,
                    data.rxcmd.eq(1),
                    data.d.eq(RXCMD_MAGIC_OVF),
                ).Else(data.eq(self.sink.payload))).Elif(
                    self.source.ack, valid.eq(0))
        ]

        self.comb += [self.source.stb.eq(valid), self.source.payload.eq(data)]
Esempio n. 33
0
    def __init__(self):
        self.valid_i = Signal()
        self.input = Signal(10)
        self.valid_o = Signal()
        self.output = Record(channel_layout)

        ###

        self.sync.pix += self.output.de.eq(1)
        for i, t in enumerate(control_tokens):
            self.sync.pix += If(self.input == t, self.output.de.eq(0),
                                self.output.c.eq(i))
        self.sync.pix += self.output.d[0].eq(self.input[0] ^ self.input[9])
        for i in range(1, 8):
            self.sync.pix += self.output.d[i].eq(self.input[i]
                                                 ^ self.input[i - 1]
                                                 ^ ~self.input[8])
        self.sync.pix += self.valid_o.eq(self.valid_i)
Esempio n. 34
0
 def __init__(self, mem, skip_ft245r=True):
     self.ctrl_pads = Record(self.ctrl_layout)
     self.ctrl_pads.adr.reset = 0b1111
     self.ctrl_pads.trigger.reset = 1
     self.ctrl_pads.frame.reset = 0b000
     self.submodules.dut = ResetInserter(["sys"])(Pdq2Base(self.ctrl_pads))
     self.comb += self.dut.reset_sys.eq(self.dut.comm.ctrl.reset)
     if skip_ft245r:
         reader = SimReader(mem)
     else:
         reader = SimFt245r_rx(mem)
     self.submodules.reader = ResetInserter(["sys"])(reader)
     self.comb += self.reader.reset_sys.eq(self.dut.comm.ctrl.reset)
     self.comb += self.dut.comm.sink.connect(self.reader.source)
     # override high-ack during reset draining the reader
     self.comb += self.reader.source.ack.eq(self.dut.comm.sink.ack
                                            & ~self.dut.comm.ctrl.reset)
     self.outputs = []
Esempio n. 35
0
    def __init__(self, nchan=3, depth=8):
        self.valid_i = Signal()
        self.chan_synced = Signal()

        self._channels_synced = CSRStatus()

        lst_control = []
        all_control = Signal()
        for i in range(nchan):
            name = "data_in" + str(i)
            data_in = Record(channel_layout, name=name)
            setattr(self, name, data_in)
            name = "data_out" + str(i)
            data_out = Record(channel_layout, name=name)
            setattr(self, name, data_out)

            # # #

            syncbuffer = _SyncBuffer(layout_len(channel_layout), depth)
            syncbuffer = ClockDomainsRenamer("pix")(syncbuffer)
            self.submodules += syncbuffer
            self.comb += [
                syncbuffer.din.eq(data_in.raw_bits()),
                data_out.raw_bits().eq(syncbuffer.dout)
            ]
            is_control = Signal()
            self.comb += [
                is_control.eq(~data_out.de),
                syncbuffer.re.eq(~is_control | all_control)
            ]
            lst_control.append(is_control)

        some_control = Signal()
        self.comb += [
            all_control.eq(reduce(and_, lst_control)),
            some_control.eq(reduce(or_, lst_control))
        ]
        self.sync.pix += \
            If(~self.valid_i,
                self.chan_synced.eq(0)
            ).Else(
                If(some_control,
                    If(all_control,
                        self.chan_synced.eq(1)
                    ).Else(
                        self.chan_synced.eq(0)
                    )
                )
            )
        self.specials += MultiReg(self.chan_synced,
                                  self._channels_synced.status)
Esempio n. 36
0
File: core.py Progetto: cr1901/artiq
    def __init__(self, interface, counter, fifo_depth, guard_io_cycles):
        data_width = rtlink.get_data_width(interface)
        address_width = rtlink.get_address_width(interface)
        fine_ts_width = rtlink.get_fine_ts_width(interface)

        ev_layout = []
        if data_width:
            ev_layout.append(("data", data_width))
        if address_width:
            ev_layout.append(("address", address_width))
        ev_layout.append(("timestamp", counter.width + fine_ts_width))
        # ev must be valid 1 cycle before we to account for the latency in
        # generating replace, sequence_error and nop
        self.ev = Record(ev_layout)

        self.writable = Signal()
        self.we = Signal()  # maximum throughput 1/2

        self.underflow = Signal()  # valid 1 cycle after we, pulsed
        self.sequence_error = Signal()
        self.collision_error = Signal()

        # # #

        # FIFO
        fifo = ClockDomainsRenamer({"write": "rsys", "read": "rio"})(
            AsyncFIFO(layout_len(ev_layout), fifo_depth))
        self.submodules += fifo
        fifo_in = Record(ev_layout)
        fifo_out = Record(ev_layout)
        self.comb += [
            fifo.din.eq(fifo_in.raw_bits()),
            fifo_out.raw_bits().eq(fifo.dout)
        ]

        # Buffer
        buf_pending = Signal()
        buf = Record(ev_layout)
        buf_just_written = Signal()

        # Special cases
        replace = Signal()
        sequence_error = Signal()
        collision_error = Signal()
        any_error = Signal()
        nop = Signal()
        self.sync.rsys += [
            # Note: replace does not perform any RTLink address checks,
            # i.e. a write to a different address will be silently replaced
            # as well.
            replace.eq(self.ev.timestamp == buf.timestamp),
            # Detect sequence errors on coarse timestamps only
            # so that they are mutually exclusive with collision errors.
            sequence_error.eq(self.ev.timestamp[fine_ts_width:]
                              < buf.timestamp[fine_ts_width:])
        ]
        if fine_ts_width:
            self.sync.rsys += collision_error.eq(
                (self.ev.timestamp[fine_ts_width:] == buf.timestamp[fine_ts_width:])
                & (self.ev.timestamp[:fine_ts_width] != buf.timestamp[:fine_ts_width]))
        self.comb += any_error.eq(sequence_error | collision_error)
        if interface.suppress_nop:
            # disable NOP at reset: do not suppress a first write with all 0s
            nop_en = Signal(reset=0)
            addresses_equal = [getattr(self.ev, a) == getattr(buf, a)
                               for a in ("data", "address")
                               if hasattr(self.ev, a)]
            if addresses_equal:
                self.sync.rsys += nop.eq(
                    nop_en & reduce(and_, addresses_equal))
            else:
                self.comb.eq(nop.eq(0))
            self.sync.rsys += [
                # buf now contains valid data. enable NOP.
                If(self.we & ~any_error, nop_en.eq(1)),
                # underflows cancel the write. allow it to be retried.
                If(self.underflow, nop_en.eq(0))
            ]
        self.comb += [
            self.sequence_error.eq(self.we & sequence_error),
            self.collision_error.eq(self.we & collision_error)
        ]

        # Buffer read and FIFO write
        self.comb += fifo_in.eq(buf)
        in_guard_time = Signal()
        self.comb += in_guard_time.eq(
            buf.timestamp[fine_ts_width:]
                < counter.value_sys + guard_io_cycles)
        self.sync.rsys += If(in_guard_time, buf_pending.eq(0))
        self.comb += \
            If(buf_pending,
                If(in_guard_time,
                    If(buf_just_written,
                        self.underflow.eq(1)
                    ).Else(
                        fifo.we.eq(1)
                    )
                ),
                If(self.we & ~replace & ~nop & ~any_error,
                   fifo.we.eq(1)
                )
            )

        # Buffer write
        # Must come after read to handle concurrent read+write properly
        self.sync.rsys += [
            buf_just_written.eq(0),
            If(self.we & ~nop & ~any_error,
                buf_just_written.eq(1),
                buf_pending.eq(1),
                buf.eq(self.ev)
            )
        ]
        self.comb += self.writable.eq(fifo.writable)

        # Buffer output of FIFO to improve timing
        dout_stb = Signal()
        dout_ack = Signal()
        dout = Record(ev_layout)
        self.sync.rio += \
            If(fifo.re,
                dout_stb.eq(1),
                dout.eq(fifo_out)
            ).Elif(dout_ack,
                dout_stb.eq(0)
            )
        self.comb += fifo.re.eq(fifo.readable & (~dout_stb | dout_ack))

        # FIFO read through buffer
        # TODO: report error on stb & busy
        self.comb += [
            dout_ack.eq(
                dout.timestamp[fine_ts_width:] == counter.value_rio),
            interface.stb.eq(dout_stb & dout_ack)
        ]
        if data_width:
            self.comb += interface.data.eq(dout.data)
        if address_width:
            self.comb += interface.address.eq(dout.address)
        if fine_ts_width:
            self.comb += interface.fine_ts.eq(dout.timestamp[:fine_ts_width])
Esempio n. 37
0
def UARTPads():
    return Record([("tx", 1), ("rx", 1)])
Esempio n. 38
0
    def __init__(self, tsc, channels, mode, quash_channels=[], interface=None):
        if interface is None:
            interface = cri.Interface()
        self.cri = interface

        # # #

        if mode == "sync":
            fifo_factory = SyncFIFOBuffered
            sync_io = self.sync
            sync_cri = self.sync
        elif mode == "async":
            fifo_factory = lambda *args: ClockDomainsRenamer({"write": "rio", "read": "rsys"})(AsyncFIFO(*args))
            sync_io = self.sync.rio
            sync_cri = self.sync.rsys
        else:
            raise ValueError

        i_statuses, i_datas, i_timestamps = [], [], []
        i_ack = Signal()
        sel = self.cri.chan_sel[:16]
        for n, channel in enumerate(channels):
            iif = channel.interface.i
            if iif is None or n in quash_channels:
                i_datas.append(0)
                i_timestamps.append(0)
                i_statuses.append(0)
                continue

            # FIFO
            layout = get_channel_layout(len(tsc.coarse_ts), iif)
            fifo = fifo_factory(layout_len(layout), channel.ififo_depth)
            self.submodules += fifo
            fifo_in = Record(layout)
            fifo_out = Record(layout)
            self.comb += [
                fifo.din.eq(fifo_in.raw_bits()),
                fifo_out.raw_bits().eq(fifo.dout)
            ]

            # FIFO write
            if iif.delay:
                counter_rtio = Signal.like(tsc.coarse_ts, reset_less=True)
                sync_io += counter_rtio.eq(tsc.coarse_ts - (iif.delay + 1))
            else:
                counter_rtio = tsc.coarse_ts
            if hasattr(fifo_in, "data"):
                self.comb += fifo_in.data.eq(iif.data)
            if hasattr(fifo_in, "timestamp"):
                if hasattr(iif, "fine_ts"):
                    full_ts = Cat(iif.fine_ts, counter_rtio)
                else:
                    full_ts = counter_rtio
                self.comb += fifo_in.timestamp.eq(full_ts)
            self.comb += fifo.we.eq(iif.stb)

            overflow_io = Signal()
            self.comb += overflow_io.eq(fifo.we & ~fifo.writable)
            if mode == "sync":
                overflow_trigger = overflow_io
            elif mode == "async":
                overflow_transfer = BlindTransfer()
                self.submodules += overflow_transfer
                self.comb += overflow_transfer.i.eq(overflow_io)
                overflow_trigger = overflow_transfer.o
            else:
                raise ValueError

            # FIFO read, CRI connection
            if hasattr(fifo_out, "data"):
                i_datas.append(fifo_out.data)
            else:
                i_datas.append(0)
            if hasattr(fifo_out, "timestamp"):
                ts_shift = 64 - len(fifo_out.timestamp)
                i_timestamps.append(fifo_out.timestamp << ts_shift)
            else:
                i_timestamps.append(0)

            selected = Signal()
            self.comb += selected.eq(sel == n)

            overflow = Signal()
            sync_cri += [
                If(selected & i_ack,
                    overflow.eq(0)),
                If(overflow_trigger,
                    overflow.eq(1))
            ]
            self.comb += fifo.re.eq(selected & i_ack & ~overflow)
            i_statuses.append(Cat(fifo.readable & ~overflow, overflow))

        i_status_raw = Signal(2)
        self.comb += i_status_raw.eq(Array(i_statuses)[sel])
        input_timeout = Signal.like(self.cri.i_timeout, reset_less=True)
        input_pending = Signal()
        self.cri.i_data.reset_less = True
        self.cri.i_timestamp.reset_less = True
        sync_cri += [
            i_ack.eq(0),
            If(i_ack,
                self.cri.i_status.eq(Cat(~i_status_raw[0], i_status_raw[1], 0)),
                self.cri.i_data.eq(Array(i_datas)[sel]),
                self.cri.i_timestamp.eq(Array(i_timestamps)[sel]),
            ),
            If((tsc.full_ts_cri >= input_timeout) | (i_status_raw != 0),
                If(input_pending, i_ack.eq(1)),
                input_pending.eq(0)
            ),
            If(self.cri.cmd == cri.commands["read"],
                input_timeout.eq(self.cri.i_timeout),
                input_pending.eq(1),
                self.cri.i_status.eq(0b100)
            )
        ]
Esempio n. 39
0
    def __init__(self, word_width, fifo_depth):
        # in pix clock domain
        self.valid_i = Signal()
        self.vsync = Signal()
        self.de = Signal()
        self.r = Signal(8)
        self.g = Signal(8)
        self.b = Signal(8)

        self.counter = Signal(20)  # Since math.log(1024*768, 2) = 19.58

        word_layout = [("sof", 1), ("pixels", word_width)]
        self.frame = Source(word_layout)
        self.busy = Signal()

        self._overflow = CSR()
        self._start_counter = CSRStorage(1, reset=0)

        self.sync += [
            If((self._start_counter.storage),
               self.counter.eq(self.counter + 1)
            )
        ]

        de_r = Signal()
        self.sync.pix += de_r.eq(self.de) #initially self.sync.pix

        rgb2ycbcr = RGB2YCbCr()
        self.submodules += RenameClockDomains(rgb2ycbcr, "pix") #initially pix
        chroma_downsampler = YCbCr444to422()
        self.submodules += RenameClockDomains(chroma_downsampler, "pix") #initially pix
        self.comb += [
            rgb2ycbcr.sink.stb.eq(self.valid_i),
            rgb2ycbcr.sink.sop.eq(self.de & ~de_r),
            rgb2ycbcr.sink.r.eq(self.r),
            rgb2ycbcr.sink.g.eq(self.g),
            rgb2ycbcr.sink.b.eq(self.b),
            Record.connect(rgb2ycbcr.source, chroma_downsampler.sink),
            chroma_downsampler.source.ack.eq(1)
        ]
        # XXX need clean up
        de = self.de
        vsync = self.vsync
        for i in range(rgb2ycbcr.latency + chroma_downsampler.latency):
            next_de = Signal()
            next_vsync = Signal()
            # Beware below...initially was self.sync.pix
            self.sync.pix += [
                next_de.eq(de),
                next_vsync.eq(vsync)
            ]
            de = next_de
            vsync = next_vsync

        ###################################################################################
        # start of frame detection

        '''new_frame = Signal()
        self.comb += new_frame.eq(self.counter == 0)'''
        vsync_r = Signal()
        new_frame = Signal()
        self.comb += new_frame.eq(vsync & ~vsync_r)
        #self.sync.pix += vsync_r.eq(vsync)
        self.sync.pix += vsync_r.eq(vsync)

        # pack pixels into words
        cur_word = Signal(word_width)
        cur_word_valid = Signal()
        encoded_pixel = Signal(16)
        self.comb += encoded_pixel.eq(Cat(chroma_downsampler.source.y, chroma_downsampler.source.cb_cr)),
        pack_factor = word_width//16
        assert(pack_factor & (pack_factor - 1) == 0)  # only support powers of 2
        pack_counter = Signal(max=pack_factor)
        
        #self.sync.pix += [
        self.sync.pix += [
            cur_word_valid.eq(0),
            If(new_frame,
                cur_word_valid.eq(pack_counter == (pack_factor - 1)),
                pack_counter.eq(0),
            ).Elif(chroma_downsampler.source.stb & de,
                [If(pack_counter == (pack_factor-i-1),
                    cur_word[16*i:16*(i+1)].eq(encoded_pixel)) for i in range(pack_factor)],
                cur_word_valid.eq(pack_counter == (pack_factor - 1)),
                pack_counter.eq(pack_counter + 1)
            )
        ]

        # FIFO
        #Async for another clock domain, sync for our sys clock domain! F**k!! :(
        fifo = RenameClockDomains(AsyncFIFO(word_layout, fifo_depth),
            {"write": "pix", "read": "sys"})
        self.submodules += fifo
        self.comb += [
            fifo.din.pixels.eq(cur_word),
            fifo.we.eq(cur_word_valid)
        ]
        
        self.sync.pix += \
            If(new_frame,
                fifo.din.sof.eq(1)
            ).Elif(cur_word_valid,
                fifo.din.sof.eq(0)
            )

        self.comb += [
            self.frame.stb.eq(fifo.readable),
            self.frame.payload.eq(fifo.dout),
            fifo.re.eq(self.frame.ack),
            self.busy.eq(0)
        ]

        # overflow detection
        pix_overflow = Signal()
        pix_overflow_reset = Signal()

        self.sync.pix += [
            If(fifo.we & ~fifo.writable,
                pix_overflow.eq(1)
            ).Elif(pix_overflow_reset,
                pix_overflow.eq(0)
            )
        ]

        sys_overflow = Signal()
        self.specials += MultiReg(pix_overflow, sys_overflow)
        self.comb += [
            pix_overflow_reset.eq(self._overflow.re),
        ]

        overflow_mask = Signal()
        self.comb += [
            self._overflow.w.eq(sys_overflow & ~overflow_mask),
        ]
        self.sync += \
            If(self._overflow.re,
                overflow_mask.eq(1)
            ).Elif(pix_overflow_reset,
                overflow_mask.eq(0)
            )
Esempio n. 40
0
    def __init__(self, word_width, fifo_depth):
        # in pix clock domain
        self.valid_i = Signal()
        self.vsync = Signal()
        self.de = Signal()
        self.r = Signal(8)
        self.g = Signal(8)
        self.b = Signal(8)

        # in sys clock domain
        word_layout = [("sof", 1), ("pixels", word_width)]
        self.frame = Source(word_layout)
        self.busy = Signal()

        self._overflow = CSR()

        ###

        de_r = Signal()
        self.sync.pix += de_r.eq(self.de)

        rgb2ycbcr = RGB2YCbCr()
        self.submodules += RenameClockDomains(rgb2ycbcr, "pix")
        chroma_downsampler = YCbCr444to422()
        self.submodules += RenameClockDomains(chroma_downsampler, "pix")
        self.comb += [
            rgb2ycbcr.sink.stb.eq(self.valid_i),
            rgb2ycbcr.sink.sop.eq(self.de & ~de_r),
            rgb2ycbcr.sink.r.eq(self.r),
            rgb2ycbcr.sink.g.eq(self.g),
            rgb2ycbcr.sink.b.eq(self.b),
            Record.connect(rgb2ycbcr.source, chroma_downsampler.sink),
            chroma_downsampler.source.ack.eq(1),
        ]
        # XXX need clean up
        de = self.de
        vsync = self.vsync
        for i in range(rgb2ycbcr.latency + chroma_downsampler.latency):
            next_de = Signal()
            next_vsync = Signal()
            self.sync.pix += [next_de.eq(de), next_vsync.eq(vsync)]
            de = next_de
            vsync = next_vsync

        # start of frame detection
        vsync_r = Signal()
        new_frame = Signal()
        self.comb += new_frame.eq(vsync & ~vsync_r)
        self.sync.pix += vsync_r.eq(vsync)

        # pack pixels into words
        cur_word = Signal(word_width)
        cur_word_valid = Signal()
        encoded_pixel = Signal(16)
        self.comb += (encoded_pixel.eq(Cat(chroma_downsampler.source.y, chroma_downsampler.source.cb_cr)),)
        pack_factor = word_width // 16
        assert pack_factor & (pack_factor - 1) == 0  # only support powers of 2
        pack_counter = Signal(max=pack_factor)
        self.sync.pix += [
            cur_word_valid.eq(0),
            If(new_frame, cur_word_valid.eq(pack_counter == (pack_factor - 1)), pack_counter.eq(0)).Elif(
                chroma_downsampler.source.stb & de,
                [
                    If(pack_counter == (pack_factor - i - 1), cur_word[16 * i : 16 * (i + 1)].eq(encoded_pixel))
                    for i in range(pack_factor)
                ],
                cur_word_valid.eq(pack_counter == (pack_factor - 1)),
                pack_counter.eq(pack_counter + 1),
            ),
        ]

        # FIFO
        fifo = RenameClockDomains(AsyncFIFO(word_layout, fifo_depth), {"write": "pix", "read": "sys"})
        self.submodules += fifo
        self.comb += [fifo.din.pixels.eq(cur_word), fifo.we.eq(cur_word_valid)]
        self.sync.pix += If(new_frame, fifo.din.sof.eq(1)).Elif(cur_word_valid, fifo.din.sof.eq(0))

        self.comb += [
            self.frame.stb.eq(fifo.readable),
            self.frame.payload.eq(fifo.dout),
            fifo.re.eq(self.frame.ack),
            self.busy.eq(0),
        ]

        # overflow detection
        pix_overflow = Signal()
        pix_overflow_reset = Signal()
        self.sync.pix += [If(fifo.we & ~fifo.writable, pix_overflow.eq(1)).Elif(pix_overflow_reset, pix_overflow.eq(0))]

        sys_overflow = Signal()
        self.specials += MultiReg(pix_overflow, sys_overflow)
        self.submodules.overflow_reset = PulseSynchronizer("sys", "pix")
        self.submodules.overflow_reset_ack = PulseSynchronizer("pix", "sys")
        self.comb += [pix_overflow_reset.eq(self.overflow_reset.o), self.overflow_reset_ack.i.eq(pix_overflow_reset)]

        overflow_mask = Signal()
        self.comb += [self._overflow.w.eq(sys_overflow & ~overflow_mask), self.overflow_reset.i.eq(self._overflow.re)]
        self.sync += If(self._overflow.re, overflow_mask.eq(1)).Elif(self.overflow_reset_ack.o, overflow_mask.eq(0))
Esempio n. 41
0
    def __init__(self):
        self.sink = Sink(line_layout)

        self.trigger = Signal()
        self.aux = Signal()
        self.silence = Signal()
        self.arm = Signal()
        self.data = Signal(16)

        ###

        line = Record(line_layout)
        dt_dec = Signal(16)
        dt_end = Signal(16)
        dt = Signal(16)
        adv = Signal()
        tic = Signal()
        toc = Signal()
        stb = Signal()
        toc0 = Signal()
        inc = Signal()

        lp = self.sink.payload

        self.comb += [
            adv.eq(self.arm & self.sink.stb
                   & (self.trigger
                      | ~(line.header.wait | lp.header.trigger))),
            tic.eq(dt_dec == dt_end),
            toc.eq(dt == line.dt),
            stb.eq(tic & toc & adv),
            self.sink.ack.eq(stb),
            inc.eq(self.arm & tic & (~toc | (~toc0 & ~adv))),
        ]

        subs = [
            Volt(lp, stb & (lp.header.typ == 0), inc),
            Dds(lp, stb & (lp.header.typ == 1), inc),
        ]

        for i, sub in enumerate(subs):
            self.submodules += sub

        self.sync += [
            toc0.eq(toc),
            self.data.eq(optree("+", [sub.data for sub in subs])),
            self.aux.eq(line.header.aux),
            self.silence.eq(line.header.silence),
            If(
                ~tic,
                dt_dec.eq(dt_dec + 1),
            ).Elif(
                ~toc,
                dt_dec.eq(0),
                dt.eq(dt + 1),
            ).Elif(
                stb,
                line.header.eq(lp.header),
                line.dt.eq(lp.dt - 1),
                dt_end.eq((1 << lp.header.shift) - 1),
                dt_dec.eq(0),
                dt.eq(0),
            )
        ]
Esempio n. 42
0
	def __init__(self):
		super(Loopback, self).__init__()
		self.comb += Record.connect(self.dout, self.din)
Esempio n. 43
0
	def __init__(self, cachesize, lasmim):
		self.wishbone = wishbone.Interface()

		###

		data_width = flen(self.wishbone.dat_r)
		if lasmim.dw > data_width and (lasmim.dw % data_width) != 0:
			raise ValueError("LASMI data width must be a multiple of {dw}".format(dw=data_width))
		if lasmim.dw < data_width and (data_width % lasmim.dw) != 0:
			raise ValueError("WISHBONE data width must be a multiple of {dw}".format(dw=lasmim.dw))

		# Split address:
		# TAG | LINE NUMBER | LINE OFFSET
		offsetbits = log2_int(max(lasmim.dw//data_width, 1))
		addressbits = lasmim.aw + offsetbits
		linebits = log2_int(cachesize) - offsetbits
		tagbits = addressbits - linebits
		wordbits = data_width//lasmim.dw
		adr_offset, adr_line, adr_tag = split(self.wishbone.adr, offsetbits, linebits, tagbits)
		word = Signal(wordbits) if wordbits else None
		
		# Data memory
		data_mem = Memory(lasmim.dw*2**wordbits, 2**linebits)
		data_port = data_mem.get_port(write_capable=True, we_granularity=8)
		self.specials += data_mem, data_port
		
		write_from_lasmi = Signal()
		write_to_lasmi = Signal()
		if adr_offset is None:
			adr_offset_r = None
		else:
			adr_offset_r = Signal(offsetbits)
			self.sync += adr_offset_r.eq(adr_offset)

		self.comb += [
			data_port.adr.eq(adr_line),
			If(write_from_lasmi,
				displacer(lasmim.dat_r, word, data_port.dat_w),
				displacer(Replicate(1, lasmim.dw//8), word, data_port.we)
			).Else(
				data_port.dat_w.eq(Replicate(self.wishbone.dat_w, max(lasmim.dw//data_width, 1))),
				If(self.wishbone.cyc & self.wishbone.stb & self.wishbone.we & self.wishbone.ack,
					displacer(self.wishbone.sel, adr_offset, data_port.we, 2**offsetbits, reverse=True)
				)
			),
			If(write_to_lasmi, 
				chooser(data_port.dat_r, word, lasmim.dat_w),
				lasmim.dat_we.eq(2**(lasmim.dw//8)-1)
			),
			chooser(data_port.dat_r, adr_offset_r, self.wishbone.dat_r, reverse=True)
		]

		
		# Tag memory
		tag_layout = [("tag", tagbits), ("dirty", 1)]
		tag_mem = Memory(layout_len(tag_layout), 2**linebits)
		tag_port = tag_mem.get_port(write_capable=True)
		self.specials += tag_mem, tag_port
		tag_do = Record(tag_layout)
		tag_di = Record(tag_layout)
		self.comb += [
			tag_do.raw_bits().eq(tag_port.dat_r),
			tag_port.dat_w.eq(tag_di.raw_bits())
		]
			
		self.comb += [
			tag_port.adr.eq(adr_line),
			tag_di.tag.eq(adr_tag)
		]
		if word is not None:
			self.comb += lasmim.adr.eq(Cat(word, adr_line, tag_do.tag))
		else:
			self.comb += lasmim.adr.eq(Cat(adr_line, tag_do.tag))		
			
		# Lasmim word computation, word_clr and word_inc will be simplified
		# at synthesis when wordbits=0
		word_clr = Signal()
		word_inc = Signal()
		if word is not None:
			self.sync += \
				If(word_clr,
					word.eq(0),
				).Elif(word_inc,
					word.eq(word+1)
				)

		def word_is_last(word):
			if word is not None:
				return word == 2**wordbits-1
			else:
				return 1

		# Control FSM
		assert(lasmim.write_latency >= 1 and lasmim.read_latency >= 1)
		fsm = FSM(reset_state="IDLE")
		self.submodules += fsm
		
		fsm.delayed_enter("EVICT_DATAD", "EVICT_DATA", lasmim.write_latency-1)
		fsm.delayed_enter("REFILL_DATAD", "REFILL_DATA", lasmim.read_latency-1)

		fsm.act("IDLE",
			If(self.wishbone.cyc & self.wishbone.stb, NextState("TEST_HIT"))
		)
		fsm.act("TEST_HIT",
			word_clr.eq(1),
			If(tag_do.tag == adr_tag,
				self.wishbone.ack.eq(1),
				If(self.wishbone.we,
					tag_di.dirty.eq(1),
					tag_port.we.eq(1)
				),
				NextState("IDLE")
			).Else(
				If(tag_do.dirty,
					NextState("EVICT_REQUEST")
				).Else(
					NextState("REFILL_WRTAG")
				)
			)
		)
		
		fsm.act("EVICT_REQUEST",
			lasmim.stb.eq(1),
			lasmim.we.eq(1),
			If(lasmim.req_ack, NextState("EVICT_WAIT_DATA_ACK"))
		)
		fsm.act("EVICT_WAIT_DATA_ACK",
			If(lasmim.dat_ack, NextState("EVICT_DATAD"))
		)
		fsm.act("EVICT_DATA",
			write_to_lasmi.eq(1),
			word_inc.eq(1),
			If(word_is_last(word),
				NextState("REFILL_WRTAG"),
			).Else(
				NextState("EVICT_REQUEST")
			)
		)
		
		fsm.act("REFILL_WRTAG",
			# Write the tag first to set the LASMI address
			tag_port.we.eq(1),
			word_clr.eq(1),
			NextState("REFILL_REQUEST")
		)
		fsm.act("REFILL_REQUEST",
			lasmim.stb.eq(1),
			If(lasmim.req_ack, NextState("REFILL_WAIT_DATA_ACK"))
		)
		fsm.act("REFILL_WAIT_DATA_ACK",
			If(lasmim.dat_ack, NextState("REFILL_DATAD"))
		)
		fsm.act("REFILL_DATA",
			write_from_lasmi.eq(1),
			word_inc.eq(1),
			If(word_is_last(word),
				NextState("TEST_HIT"),
			).Else(
				NextState("REFILL_REQUEST")
			)
		)
Esempio n. 44
0
	def get_fragment(self):
		comb = []
		sync = []
		
		aaw = self.asmiport.hub.aw
		adw = self.asmiport.hub.dw
		
		# Split address:
		# TAG | LINE NUMBER | LINE OFFSET
		offsetbits = log2_int(adw//32)
		addressbits = aaw + offsetbits
		linebits = log2_int(self.cachesize) - offsetbits
		tagbits = addressbits - linebits
		adr_offset, adr_line, adr_tag = split(self.wishbone.adr, offsetbits, linebits, tagbits)
		
		# Data memory
		data_mem = Memory(adw, 2**linebits)
		data_port = data_mem.get_port(write_capable=True, we_granularity=8)
		
		write_from_asmi = Signal()
		write_to_asmi = Signal()
		adr_offset_r = Signal(offsetbits)
		comb += [
			data_port.adr.eq(adr_line),
			If(write_from_asmi,
				data_port.dat_w.eq(self.asmiport.dat_r),
				data_port.we.eq(Replicate(1, adw//8))
			).Else(
				data_port.dat_w.eq(Replicate(self.wishbone.dat_w, adw//32)),
				If(self.wishbone.cyc & self.wishbone.stb & self.wishbone.we & self.wishbone.ack,
					displacer(self.wishbone.sel, adr_offset, data_port.we, 2**offsetbits, reverse=True)
				)
			),
			If(write_to_asmi, self.asmiport.dat_w.eq(data_port.dat_r)),
			self.asmiport.dat_wm.eq(0),
			chooser(data_port.dat_r, adr_offset_r, self.wishbone.dat_r, reverse=True)
		]
		sync += [
			adr_offset_r.eq(adr_offset)
		]
		
		# Tag memory
		tag_layout = [("tag", tagbits), ("dirty", 1)]
		tag_mem = Memory(layout_len(tag_layout), 2**linebits)
		tag_port = tag_mem.get_port(write_capable=True)
		tag_do = Record(tag_layout)
		tag_di = Record(tag_layout)
		comb += [
			tag_do.raw_bits().eq(tag_port.dat_r),
			tag_port.dat_w.eq(tag_di.raw_bits())
		]
			
		comb += [
			tag_port.adr.eq(adr_line),
			tag_di.tag.eq(adr_tag),
			self.asmiport.adr.eq(Cat(adr_line, tag_do.tag))
		]
		
		# Control FSM
		write_to_asmi_pre = Signal()
		sync.append(write_to_asmi.eq(write_to_asmi_pre))
		
		fsm = FSM("IDLE", "TEST_HIT",
			"EVICT_ISSUE", "EVICT_WAIT",
			"REFILL_WRTAG", "REFILL_ISSUE", "REFILL_WAIT", "REFILL_COMPLETE")
		
		fsm.act(fsm.IDLE,
			If(self.wishbone.cyc & self.wishbone.stb, fsm.next_state(fsm.TEST_HIT))
		)
		fsm.act(fsm.TEST_HIT,
			If(tag_do.tag == adr_tag,
				self.wishbone.ack.eq(1),
				If(self.wishbone.we,
					tag_di.dirty.eq(1),
					tag_port.we.eq(1)
				),
				fsm.next_state(fsm.IDLE)
			).Else(
				If(tag_do.dirty,
					fsm.next_state(fsm.EVICT_ISSUE)
				).Else(
					fsm.next_state(fsm.REFILL_WRTAG)
				)
			)
		)
		
		fsm.act(fsm.EVICT_ISSUE,
			self.asmiport.stb.eq(1),
			self.asmiport.we.eq(1),
			If(self.asmiport.ack, fsm.next_state(fsm.EVICT_WAIT))
		)
		fsm.act(fsm.EVICT_WAIT,
			# Data is actually sampled by the memory controller in the next state.
			# But since the data memory has one cycle latency, it gets the data
			# at the address given during this cycle.
			If(self.asmiport.get_call_expression(),
				write_to_asmi_pre.eq(1),
				fsm.next_state(fsm.REFILL_WRTAG)
			)
		)
		
		fsm.act(fsm.REFILL_WRTAG,
			# Write the tag first to set the ASMI address
			tag_port.we.eq(1),
			fsm.next_state(fsm.REFILL_ISSUE)
		)
		fsm.act(fsm.REFILL_ISSUE,
			self.asmiport.stb.eq(1),
			If(self.asmiport.ack, fsm.next_state(fsm.REFILL_WAIT))
		)
		fsm.act(fsm.REFILL_WAIT,
			If(self.asmiport.get_call_expression(), fsm.next_state(fsm.REFILL_COMPLETE))
		)
		fsm.act(fsm.REFILL_COMPLETE,
			write_from_asmi.eq(1),
			fsm.next_state(fsm.TEST_HIT)
		)
		
		return Fragment(comb, sync, specials={data_mem, tag_mem}) \
			+ fsm.get_fragment()
Esempio n. 45
0
        self.submodules.tap = wishbone.Tap(self.slave.bus)
        self.submodules.intercon = wishbone.InterconnectPointToPoint(
                self.master.bus, self.slave.bus)
        self.cycle = 0

    def gen_reads(self):
        for a in range(10):
            t = TRead(a)
            yield t
            print("read {} in {} cycles(s)".format(t.data, t.latency))

    def do_simulation(self, selfp):
        if selfp.pads.cs_n:
            self.cycle = 0
        else:
            self.cycle += 1
            if not selfp.slave.dq.oe:
                selfp.slave.dq.i = self.cycle & 0xf
    do_simulation.passive = True

if __name__ == "__main__":
    from migen.sim.generic import run_simulation
    from migen.fhdl import verilog

    pads = Record([("cs_n", 1), ("clk", 1), ("dq", 4)])
    s = SpiFlash(pads)
    print(verilog.convert(s, ios={pads.clk, pads.cs_n, pads.dq, s.bus.adr,
        s.bus.dat_r, s.bus.cyc, s.bus.ack, s.bus.stb}))

    run_simulation(SpiFlashTB(), vcd_name="spiflash.vcd")
Esempio n. 46
0
    def __init__(self, interface, counter, fifo_depth, guard_io_cycles):
        data_width = rtlink.get_data_width(interface)
        address_width = rtlink.get_address_width(interface)
        fine_ts_width = rtlink.get_fine_ts_width(interface)

        ev_layout = []
        if data_width:
            ev_layout.append(("data", data_width))
        if address_width:
            ev_layout.append(("address", address_width))
        ev_layout.append(("timestamp", counter.width + fine_ts_width))
        # ev must be valid 1 cycle before we to account for the latency in
        # generating replace, sequence_error and collision
        self.ev = Record(ev_layout)

        self.writable = Signal()
        self.we = Signal()  # maximum throughput 1/2

        self.underflow = Signal()  # valid 1 cycle after we, pulsed
        self.sequence_error = Signal()
        self.collision = Signal()
        self.busy = Signal()  # pulsed

        # # #

        # FIFO
        fifo = ClockDomainsRenamer({"write": "rsys", "read": "rio"})(
            AsyncFIFO(layout_len(ev_layout), fifo_depth))
        self.submodules += fifo
        fifo_in = Record(ev_layout)
        fifo_out = Record(ev_layout)
        self.comb += [
            fifo.din.eq(fifo_in.raw_bits()),
            fifo_out.raw_bits().eq(fifo.dout)
        ]

        # Buffer
        buf_pending = Signal()
        buf = Record(ev_layout)
        buf_just_written = Signal()

        # Special cases
        replace = Signal()
        sequence_error = Signal()
        collision = Signal()
        any_error = Signal()
        if interface.enable_replace:
            # Note: replace may be asserted at the same time as collision
            # when addresses are different. In that case, it is a collision.
            self.sync.rsys += replace.eq(self.ev.timestamp == buf.timestamp)
            # Detect sequence errors on coarse timestamps only
            # so that they are mutually exclusive with collision errors.
        self.sync.rsys += sequence_error.eq(self.ev.timestamp[fine_ts_width:] <
                                            buf.timestamp[fine_ts_width:])
        if interface.enable_replace:
            if address_width:
                different_addresses = self.ev.address != buf.address
            else:
                different_addresses = 0
            if fine_ts_width:
                self.sync.rsys += collision.eq(
                    (self.ev.timestamp[fine_ts_width:] == buf.timestamp[fine_ts_width:])
                    & ((self.ev.timestamp[:fine_ts_width] != buf.timestamp[:fine_ts_width])
                       |different_addresses))
        else:
            self.sync.rsys += collision.eq(
                self.ev.timestamp[fine_ts_width:] == buf.timestamp[fine_ts_width:])
        self.comb += [
            any_error.eq(sequence_error | collision),
            self.sequence_error.eq(self.we & sequence_error),
            self.collision.eq(self.we & collision)
        ]

        # Buffer read and FIFO write
        self.comb += fifo_in.eq(buf)
        in_guard_time = Signal()
        self.comb += in_guard_time.eq(
            buf.timestamp[fine_ts_width:]
                < counter.value_sys + guard_io_cycles)
        self.sync.rsys += If(in_guard_time, buf_pending.eq(0))
        self.comb += \
            If(buf_pending,
                If(in_guard_time,
                    If(buf_just_written,
                        self.underflow.eq(1)
                    ).Else(
                        fifo.we.eq(1)
                    )
                ),
                If(self.we & ~replace & ~any_error,
                   fifo.we.eq(1)
                )
            )

        # Buffer write
        # Must come after read to handle concurrent read+write properly
        self.sync.rsys += [
            buf_just_written.eq(0),
            If(self.we & ~any_error,
                buf_just_written.eq(1),
                buf_pending.eq(1),
                buf.eq(self.ev)
            )
        ]
        self.comb += self.writable.eq(fifo.writable)

        # Buffer output of FIFO to improve timing
        dout_stb = Signal()
        dout_ack = Signal()
        dout = Record(ev_layout)
        self.sync.rio += \
            If(fifo.re,
                dout_stb.eq(1),
                dout.eq(fifo_out)
            ).Elif(dout_ack,
                dout_stb.eq(0)
            )
        self.comb += fifo.re.eq(fifo.readable & (~dout_stb | dout_ack))

        # FIFO read through buffer
        self.comb += [
            dout_ack.eq(
                dout.timestamp[fine_ts_width:] == counter.value_rtio),
            interface.stb.eq(dout_stb & dout_ack)
        ]

        busy_transfer = _BlindTransfer()
        self.submodules += busy_transfer
        self.comb += [
            busy_transfer.i.eq(interface.stb & interface.busy),
            self.busy.eq(busy_transfer.o),
        ]

        if data_width:
            self.comb += interface.data.eq(dout.data)
        if address_width:
            self.comb += interface.address.eq(dout.address)
        if fine_ts_width:
            self.comb += interface.fine_ts.eq(dout.timestamp[:fine_ts_width])
Esempio n. 47
0
    def __init__(self, tsc, cri, enable):
        self.source = stream.Endpoint([("data", message_len)])

        self.overflow = CSRStatus()
        self.overflow_reset = CSR()

        # # #

        read_wait_event = cri.i_status[2]
        read_wait_event_r = Signal()
        read_done = Signal()
        read_overflow = Signal()
        self.sync += read_wait_event_r.eq(read_wait_event)
        self.comb += \
            If(read_wait_event_r & ~read_wait_event,
                If(~cri.i_status[0], read_done.eq(1)),
                If(cri.i_status[1], read_overflow.eq(1))
            )

        input_output_stb = Signal()
        input_output = Record(input_output_layout)
        self.comb += [
            input_output.channel.eq(cri.chan_sel),
            input_output.address_padding.eq(cri.o_address),
            input_output.rtio_counter.eq(tsc.full_ts_cri),
            If(cri.cmd == cri_commands["write"],
                input_output.message_type.eq(MessageType.output.value),
                input_output.timestamp.eq(cri.o_timestamp),
                input_output.data.eq(cri.o_data)
            ).Else(
                input_output.message_type.eq(MessageType.input.value),
                input_output.timestamp.eq(cri.i_timestamp),
                input_output.data.eq(cri.i_data)
            ),
            input_output_stb.eq((cri.cmd == cri_commands["write"]) | read_done)
        ]

        exception_stb = Signal()
        exception = Record(exception_layout)
        self.comb += [
            exception.message_type.eq(MessageType.exception.value),
            exception.channel.eq(cri.chan_sel),
            exception.rtio_counter.eq(tsc.full_ts_cri),
        ]
        just_written = Signal()
        self.sync += just_written.eq(cri.cmd == cri_commands["write"])
        self.comb += [
            If(just_written & cri.o_status[1],
                exception_stb.eq(1),
                exception.exception_type.eq(ExceptionType.o_underflow.value)
            ),
            If(read_overflow,
                exception_stb.eq(1),
                exception.exception_type.eq(ExceptionType.i_overflow.value)
            )
        ]

        stopped = Record(stopped_layout)
        self.comb += [
            stopped.message_type.eq(MessageType.stopped.value),
            stopped.rtio_counter.eq(tsc.full_ts_cri),
        ]

        enable_r = Signal()
        stopping = Signal()
        self.sync += [
            enable_r.eq(enable),
            If(~enable & enable_r, stopping.eq(1)),

            If(~stopping,
                If(exception_stb,
                    self.source.data.eq(exception.raw_bits())
                ).Else(
                    self.source.data.eq(input_output.raw_bits())
                ),
                self.source.eop.eq(0),
                self.source.stb.eq(enable &
                                  (input_output_stb | exception_stb)),

                If(self.overflow_reset.re, self.overflow.status.eq(0)),
                If(self.source.stb & ~self.source.ack,
                    self.overflow.status.eq(1)
                )
            ).Else(
                self.source.data.eq(stopped.raw_bits()),
                self.source.eop.eq(1),
                self.source.stb.eq(1),
                If(self.source.ack, stopping.eq(0))
            )
        ]
Esempio n. 48
0
    def __init__(self, tsc, cri, enable):
        self.source = stream.Endpoint([("data", message_len)])

        self.overflow = CSRStatus()
        self.overflow_reset = CSR()

        # # #

        read_wait_event = cri.i_status[2]
        read_wait_event_r = Signal()
        read_done = Signal()
        read_overflow = Signal()
        self.sync += read_wait_event_r.eq(read_wait_event)
        self.comb += \
            If(read_wait_event_r & ~read_wait_event,
                If(~cri.i_status[0], read_done.eq(1)),
                If(cri.i_status[1], read_overflow.eq(1))
            )

        input_output_stb = Signal()
        input_output = Record(input_output_layout)
        self.comb += [
            input_output.channel.eq(cri.chan_sel),
            input_output.address_padding.eq(cri.o_address),
            input_output.rtio_counter.eq(tsc.full_ts_cri),
            If(cri.cmd == cri_commands["write"],
               input_output.message_type.eq(MessageType.output.value),
               input_output.timestamp.eq(cri.o_timestamp),
               input_output.data.eq(cri.o_data)).Else(
                   input_output.message_type.eq(MessageType.input.value),
                   input_output.timestamp.eq(cri.i_timestamp),
                   input_output.data.eq(cri.i_data)),
            input_output_stb.eq((cri.cmd == cri_commands["write"]) | read_done)
        ]

        exception_stb = Signal()
        exception = Record(exception_layout)
        self.comb += [
            exception.message_type.eq(MessageType.exception.value),
            exception.channel.eq(cri.chan_sel),
            exception.rtio_counter.eq(tsc.full_ts_cri),
        ]
        just_written = Signal()
        self.sync += just_written.eq(cri.cmd == cri_commands["write"])
        self.comb += [
            If(just_written & cri.o_status[1], exception_stb.eq(1),
               exception.exception_type.eq(ExceptionType.o_underflow.value)),
            If(read_overflow, exception_stb.eq(1),
               exception.exception_type.eq(ExceptionType.i_overflow.value))
        ]

        stopped = Record(stopped_layout)
        self.comb += [
            stopped.message_type.eq(MessageType.stopped.value),
            stopped.rtio_counter.eq(tsc.full_ts_cri),
        ]

        enable_r = Signal()
        stopping = Signal()
        self.sync += [
            enable_r.eq(enable),
            If(~enable & enable_r, stopping.eq(1)),
            If(
                ~stopping,
                If(exception_stb,
                   self.source.data.eq(exception.raw_bits())).Else(
                       self.source.data.eq(input_output.raw_bits())),
                self.source.eop.eq(0),
                self.source.stb.eq(enable
                                   & (input_output_stb | exception_stb)),
                If(self.overflow_reset.re, self.overflow.status.eq(0)),
                If(self.source.stb & ~self.source.ack,
                   self.overflow.status.eq(1))).Else(
                       self.source.data.eq(stopped.raw_bits()),
                       self.source.eop.eq(1), self.source.stb.eq(1),
                       If(self.source.ack, stopping.eq(0)))
        ]
Esempio n. 49
0
    def __init__(self, interface, counter, fifo_depth, guard_io_cycles):
        data_width = rtlink.get_data_width(interface)
        address_width = rtlink.get_address_width(interface)
        fine_ts_width = rtlink.get_fine_ts_width(interface)

        ev_layout = []
        if data_width:
            ev_layout.append(("data", data_width))
        if address_width:
            ev_layout.append(("address", address_width))
        ev_layout.append(("timestamp", counter.width + fine_ts_width))
        # ev must be valid 1 cycle before we to account for the latency in
        # generating replace, sequence_error and collision
        self.ev = Record(ev_layout)

        self.writable = Signal()
        self.we = Signal()  # maximum throughput 1/2

        self.underflow = Signal()  # valid 1 cycle after we, pulsed
        self.sequence_error = Signal()
        self.collision = Signal()
        self.busy = Signal()  # pulsed

        # # #

        # FIFO
        fifo = ClockDomainsRenamer({
            "write": "rsys",
            "read": "rio"
        })(AsyncFIFO(layout_len(ev_layout), fifo_depth))
        self.submodules += fifo
        fifo_in = Record(ev_layout)
        fifo_out = Record(ev_layout)
        self.comb += [
            fifo.din.eq(fifo_in.raw_bits()),
            fifo_out.raw_bits().eq(fifo.dout)
        ]

        # Buffer
        buf_pending = Signal()
        buf = Record(ev_layout)
        buf_just_written = Signal()

        # Special cases
        replace = Signal()
        sequence_error = Signal()
        collision = Signal()
        any_error = Signal()
        if interface.enable_replace:
            # Note: replace may be asserted at the same time as collision
            # when addresses are different. In that case, it is a collision.
            self.sync.rsys += replace.eq(self.ev.timestamp == buf.timestamp)
            # Detect sequence errors on coarse timestamps only
            # so that they are mutually exclusive with collision errors.
        self.sync.rsys += sequence_error.eq(
            self.ev.timestamp[fine_ts_width:] < buf.timestamp[fine_ts_width:])
        if interface.enable_replace:
            if address_width:
                different_addresses = self.ev.address != buf.address
            else:
                different_addresses = 0
            if fine_ts_width:
                self.sync.rsys += collision.eq(
                    (self.ev.timestamp[fine_ts_width:] ==
                     buf.timestamp[fine_ts_width:])
                    & ((self.ev.timestamp[:fine_ts_width] !=
                        buf.timestamp[:fine_ts_width])
                       | different_addresses))
        else:
            self.sync.rsys += collision.eq(self.ev.timestamp[fine_ts_width:] ==
                                           buf.timestamp[fine_ts_width:])
        self.comb += [
            any_error.eq(sequence_error | collision),
            self.sequence_error.eq(self.we & sequence_error),
            self.collision.eq(self.we & collision)
        ]

        # Buffer read and FIFO write
        self.comb += fifo_in.eq(buf)
        in_guard_time = Signal()
        self.comb += in_guard_time.eq(
            buf.timestamp[fine_ts_width:] < counter.value_sys +
            guard_io_cycles)
        self.sync.rsys += If(in_guard_time, buf_pending.eq(0))
        self.comb += \
            If(buf_pending,
                If(in_guard_time,
                    If(buf_just_written,
                        self.underflow.eq(1)
                    ).Else(
                        fifo.we.eq(1)
                    )
                ),
                If(self.we & ~replace & ~any_error,
                   fifo.we.eq(1)
                )
            )

        # Buffer write
        # Must come after read to handle concurrent read+write properly
        self.sync.rsys += [
            buf_just_written.eq(0),
            If(self.we & ~any_error, buf_just_written.eq(1), buf_pending.eq(1),
               buf.eq(self.ev))
        ]
        self.comb += self.writable.eq(fifo.writable)

        # Buffer output of FIFO to improve timing
        dout_stb = Signal()
        dout_ack = Signal()
        dout = Record(ev_layout)
        self.sync.rio += \
            If(fifo.re,
                dout_stb.eq(1),
                dout.eq(fifo_out)
            ).Elif(dout_ack,
                dout_stb.eq(0)
            )
        self.comb += fifo.re.eq(fifo.readable & (~dout_stb | dout_ack))

        # latency compensation
        if interface.delay:
            counter_rtio = Signal.like(counter.value_rtio)
            self.sync.rtio += counter_rtio.eq(counter.value_rtio -
                                              interface.delay + 1)
        else:
            counter_rtio = counter.value_rtio

        # FIFO read through buffer
        self.comb += [
            dout_ack.eq(dout.timestamp[fine_ts_width:] == counter_rtio),
            interface.stb.eq(dout_stb & dout_ack)
        ]

        busy_transfer = BlindTransfer()
        self.submodules += busy_transfer
        self.comb += [
            busy_transfer.i.eq(interface.stb & interface.busy),
            self.busy.eq(busy_transfer.o),
        ]

        if data_width:
            self.comb += interface.data.eq(dout.data)
        if address_width:
            self.comb += interface.address.eq(dout.address)
        if fine_ts_width:
            self.comb += interface.fine_ts.eq(dout.timestamp[:fine_ts_width])
Esempio n. 50
0
    def __init__(self, cachesize, lasmim):
        self.wishbone = wishbone.Interface()

        ###

        data_width = flen(self.wishbone.dat_r)
        if lasmim.dw > data_width and (lasmim.dw % data_width) != 0:
            raise ValueError(
                "LASMI data width must be a multiple of {dw}".format(
                    dw=data_width))
        if lasmim.dw < data_width and (data_width % lasmim.dw) != 0:
            raise ValueError(
                "WISHBONE data width must be a multiple of {dw}".format(
                    dw=lasmim.dw))

        # Split address:
        # TAG | LINE NUMBER | LINE OFFSET
        offsetbits = log2_int(max(lasmim.dw // data_width, 1))
        addressbits = lasmim.aw + offsetbits
        linebits = log2_int(cachesize) - offsetbits
        tagbits = addressbits - linebits
        wordbits = log2_int(max(data_width // lasmim.dw, 1))
        adr_offset, adr_line, adr_tag = split(self.wishbone.adr, offsetbits,
                                              linebits, tagbits)
        word = Signal(wordbits) if wordbits else None

        # Data memory
        data_mem = Memory(lasmim.dw * 2**wordbits, 2**linebits)
        data_port = data_mem.get_port(write_capable=True, we_granularity=8)
        self.specials += data_mem, data_port

        write_from_lasmi = Signal()
        write_to_lasmi = Signal()
        if adr_offset is None:
            adr_offset_r = None
        else:
            adr_offset_r = Signal(offsetbits)
            self.sync += adr_offset_r.eq(adr_offset)

        self.comb += [
            data_port.adr.eq(adr_line),
            If(write_from_lasmi, displacer(lasmim.dat_r, word,
                                           data_port.dat_w),
               displacer(Replicate(1, lasmim.dw // 8), word,
                         data_port.we)).Else(
                             data_port.dat_w.eq(
                                 Replicate(self.wishbone.dat_w,
                                           max(lasmim.dw // data_width, 1))),
                             If(
                                 self.wishbone.cyc & self.wishbone.stb
                                 & self.wishbone.we & self.wishbone.ack,
                                 displacer(self.wishbone.sel,
                                           adr_offset,
                                           data_port.we,
                                           2**offsetbits,
                                           reverse=True))),
            If(write_to_lasmi, chooser(data_port.dat_r, word, lasmim.dat_w),
               lasmim.dat_we.eq(2**(lasmim.dw // 8) - 1)),
            chooser(data_port.dat_r,
                    adr_offset_r,
                    self.wishbone.dat_r,
                    reverse=True)
        ]

        # Tag memory
        tag_layout = [("tag", tagbits), ("dirty", 1)]
        tag_mem = Memory(layout_len(tag_layout), 2**linebits)
        tag_port = tag_mem.get_port(write_capable=True)
        self.specials += tag_mem, tag_port
        tag_do = Record(tag_layout)
        tag_di = Record(tag_layout)
        self.comb += [
            tag_do.raw_bits().eq(tag_port.dat_r),
            tag_port.dat_w.eq(tag_di.raw_bits())
        ]

        self.comb += [tag_port.adr.eq(adr_line), tag_di.tag.eq(adr_tag)]
        if word is not None:
            self.comb += lasmim.adr.eq(Cat(word, adr_line, tag_do.tag))
        else:
            self.comb += lasmim.adr.eq(Cat(adr_line, tag_do.tag))

        # Lasmim word computation, word_clr and word_inc will be simplified
        # at synthesis when wordbits=0
        word_clr = Signal()
        word_inc = Signal()
        if word is not None:
            self.sync += \
             If(word_clr,
              word.eq(0),
             ).Elif(word_inc,
              word.eq(word+1)
             )

        def word_is_last(word):
            if word is not None:
                return word == 2**wordbits - 1
            else:
                return 1

        # Control FSM
        assert (lasmim.write_latency >= 1 and lasmim.read_latency >= 1)
        fsm = FSM(reset_state="IDLE")
        self.submodules += fsm

        fsm.delayed_enter("EVICT_DATAD", "EVICT_DATA",
                          lasmim.write_latency - 1)
        fsm.delayed_enter("REFILL_DATAD", "REFILL_DATA",
                          lasmim.read_latency - 1)

        fsm.act(
            "IDLE",
            If(self.wishbone.cyc & self.wishbone.stb, NextState("TEST_HIT")))
        fsm.act(
            "TEST_HIT", word_clr.eq(1),
            If(tag_do.tag == adr_tag, self.wishbone.ack.eq(1),
               If(self.wishbone.we, tag_di.dirty.eq(1), tag_port.we.eq(1)),
               NextState("IDLE")).Else(
                   If(tag_do.dirty, NextState("EVICT_REQUEST")).Else(
                       NextState("REFILL_WRTAG"))))

        fsm.act("EVICT_REQUEST", lasmim.stb.eq(1), lasmim.we.eq(1),
                If(lasmim.req_ack, NextState("EVICT_WAIT_DATA_ACK")))
        fsm.act("EVICT_WAIT_DATA_ACK",
                If(lasmim.dat_ack, NextState("EVICT_DATAD")))
        fsm.act(
            "EVICT_DATA", write_to_lasmi.eq(1), word_inc.eq(1),
            If(
                word_is_last(word),
                NextState("REFILL_WRTAG"),
            ).Else(NextState("EVICT_REQUEST")))

        fsm.act(
            "REFILL_WRTAG",
            # Write the tag first to set the LASMI address
            tag_port.we.eq(1),
            word_clr.eq(1),
            NextState("REFILL_REQUEST"))
        fsm.act("REFILL_REQUEST", lasmim.stb.eq(1),
                If(lasmim.req_ack, NextState("REFILL_WAIT_DATA_ACK")))
        fsm.act("REFILL_WAIT_DATA_ACK",
                If(lasmim.dat_ack, NextState("REFILL_DATAD")))
        fsm.act(
            "REFILL_DATA", write_from_lasmi.eq(1), word_inc.eq(1),
            If(
                word_is_last(word),
                NextState("TEST_HIT"),
            ).Else(NextState("REFILL_REQUEST")))
Esempio n. 51
0
    def __init__(self, pack_factor):
        hbits_dyn = _hbits - log2_int(pack_factor)
        timing_layout = [
            ("hres", hbits_dyn),
            ("hsync_start", hbits_dyn),
            ("hsync_end", hbits_dyn),
            ("hscan", hbits_dyn),
            ("vres", _vbits),
            ("vsync_start", _vbits),
            ("vsync_end", _vbits),
            ("vscan", _vbits)]
        self.timing = Sink(timing_layout)
        self.pixels = Sink(pixel_layout(pack_factor))
        self.phy = Source(phy_layout(pack_factor))
        self.busy = Signal()

        ###

        hactive = Signal()
        vactive = Signal()
        active = Signal()

        hcounter = Signal(hbits_dyn)
        vcounter = Signal(_vbits)

        skip = bpc - bpc_phy
        self.comb += [
            active.eq(hactive & vactive),
            If(active,
                [getattr(getattr(self.phy.payload, p), c).eq(getattr(getattr(self.pixels.payload, p), c)[skip:])
                    for p in ["p"+str(i) for i in range(pack_factor)] for c in ["y", "cb_cr"]],
                self.phy.de.eq(1)
            ),
            self.pixels.ack.eq(self.phy.ack & active)
        ]

        load_timing = Signal()
        tr = Record(timing_layout)
        self.sync += If(load_timing, tr.eq(self.timing.payload))

        generate_en = Signal()
        generate_frame_done = Signal()
        self.sync += [
            generate_frame_done.eq(0),
            If(generate_en,
                hcounter.eq(hcounter + 1),

                If(hcounter == 0, hactive.eq(1)),
                If(hcounter == tr.hres, hactive.eq(0)),
                If(hcounter == tr.hsync_start, self.phy.hsync.eq(1)),
                If(hcounter == tr.hsync_end, self.phy.hsync.eq(0)),
                If(hcounter == tr.hscan,
                    hcounter.eq(0),
                    If(vcounter == tr.vscan,
                        vcounter.eq(0),
                        generate_frame_done.eq(1)
                    ).Else(
                        vcounter.eq(vcounter + 1)
                    )
                ),

                If(vcounter == 0, vactive.eq(1)),
                If(vcounter == tr.vres, vactive.eq(0)),
                If(vcounter == tr.vsync_start, self.phy.vsync.eq(1)),
                If(vcounter == tr.vsync_end, self.phy.vsync.eq(0))
            )
        ]

        self.submodules.fsm = FSM()
        self.fsm.act("GET_TIMING",
            self.timing.ack.eq(1),
            load_timing.eq(1),
            If(self.timing.stb, NextState("GENERATE"))
        )
        self.fsm.act("GENERATE",
            self.busy.eq(1),
            If(~active | self.pixels.stb,
                self.phy.stb.eq(1),
                If(self.phy.ack, generate_en.eq(1))
            ),
            If(generate_frame_done,    NextState("GET_TIMING"))
        )
Esempio n. 52
0
    def __init__(self, kcsrs, rtio_counter, enable):
        self.source = stream.Endpoint([("data", message_len)])

        self.overflow = CSRStatus()
        self.overflow_reset = CSR()

        # # #

        input_output_stb = Signal()
        input_output = Record(input_output_layout)
        o_data = kcsrs.o_data.storage
        o_address = kcsrs.o_address.storage
        i_data = kcsrs.i_data.status
        self.comb += [
            input_output.channel.eq(kcsrs.chan_sel.storage),
            input_output.address_padding.eq(o_address),
            input_output.rtio_counter.eq(rtio_counter),
            If(kcsrs.o_we.re,
               input_output.message_type.eq(MessageType.output.value),
               input_output.timestamp.eq(kcsrs.o_timestamp.storage),
               input_output.data.eq(o_data)).Else(
                   input_output.message_type.eq(MessageType.input.value),
                   input_output.timestamp.eq(kcsrs.i_timestamp.status),
                   input_output.data.eq(i_data)),
            input_output_stb.eq(kcsrs.o_we.re | kcsrs.i_re.re)
        ]

        exception_stb = Signal()
        exception = Record(exception_layout)
        self.comb += [
            exception.message_type.eq(MessageType.exception.value),
            exception.channel.eq(kcsrs.chan_sel.storage),
            exception.rtio_counter.eq(rtio_counter),
        ]
        for ename in ("o_underflow_reset", "o_sequence_error_reset",
                      "o_collision_reset", "i_overflow_reset"):
            self.comb += \
                If(getattr(kcsrs, ename).re,
                    exception_stb.eq(1),
                    exception.exception_type.eq(
                        getattr(ExceptionType, ename).value)
                )

        stopped = Record(stopped_layout)
        self.comb += [
            stopped.message_type.eq(MessageType.stopped.value),
            stopped.rtio_counter.eq(rtio_counter),
        ]

        enable_r = Signal()
        stopping = Signal()
        self.sync += [
            enable_r.eq(enable),
            If(~enable & enable_r, stopping.eq(1)),
            If(
                ~stopping,
                If(exception_stb,
                   self.source.data.eq(exception.raw_bits())).Else(
                       self.source.data.eq(input_output.raw_bits())),
                self.source.eop.eq(0),
                self.source.stb.eq(enable
                                   & (input_output_stb | exception_stb)),
                If(self.overflow_reset.re, self.overflow.status.eq(0)),
                If(self.source.stb & ~self.source.ack,
                   self.overflow.status.eq(1))).Else(
                       self.source.data.eq(stopped.raw_bits()),
                       self.source.eop.eq(1), self.source.stb.eq(1),
                       If(self.source.ack, stopping.eq(0)))
        ]
Esempio n. 53
0
	def __init__(self, cachesize, lasmim):
		self.wishbone = wishbone.Interface()

		###

		if lasmim.dw <= 32:
			raise ValueError("LASMI data width must be strictly larger than 32")
		if (lasmim.dw % 32) != 0:
			raise ValueError("LASMI data width must be a multiple of 32")

		# Split address:
		# TAG | LINE NUMBER | LINE OFFSET
		offsetbits = log2_int(lasmim.dw//32)
		addressbits = lasmim.aw + offsetbits
		linebits = log2_int(cachesize) - offsetbits
		tagbits = addressbits - linebits
		adr_offset, adr_line, adr_tag = split(self.wishbone.adr, offsetbits, linebits, tagbits)
		
		# Data memory
		data_mem = Memory(lasmim.dw, 2**linebits)
		data_port = data_mem.get_port(write_capable=True, we_granularity=8)
		self.specials += data_mem, data_port
		
		write_from_lasmi = Signal()
		write_to_lasmi = Signal()
		adr_offset_r = Signal(offsetbits)
		self.comb += [
			data_port.adr.eq(adr_line),
			If(write_from_lasmi,
				data_port.dat_w.eq(lasmim.dat_r),
				data_port.we.eq(Replicate(1, lasmim.dw//8))
			).Else(
				data_port.dat_w.eq(Replicate(self.wishbone.dat_w, lasmim.dw//32)),
				If(self.wishbone.cyc & self.wishbone.stb & self.wishbone.we & self.wishbone.ack,
					displacer(self.wishbone.sel, adr_offset, data_port.we, 2**offsetbits, reverse=True)
				)
			),
			If(write_to_lasmi, 
				lasmim.dat_w.eq(data_port.dat_r),
				lasmim.dat_we.eq(2**(lasmim.dw//8)-1)
			),
			chooser(data_port.dat_r, adr_offset_r, self.wishbone.dat_r, reverse=True)
		]
		self.sync += adr_offset_r.eq(adr_offset)
		
		# Tag memory
		tag_layout = [("tag", tagbits), ("dirty", 1)]
		tag_mem = Memory(layout_len(tag_layout), 2**linebits)
		tag_port = tag_mem.get_port(write_capable=True)
		self.specials += tag_mem, tag_port
		tag_do = Record(tag_layout)
		tag_di = Record(tag_layout)
		self.comb += [
			tag_do.raw_bits().eq(tag_port.dat_r),
			tag_port.dat_w.eq(tag_di.raw_bits())
		]
			
		self.comb += [
			tag_port.adr.eq(adr_line),
			tag_di.tag.eq(adr_tag),
			lasmim.adr.eq(Cat(adr_line, tag_do.tag))
		]
		
		# Control FSM
		assert(lasmim.write_latency >= 1 and lasmim.read_latency >= 1)
		fsm = FSM("IDLE", "TEST_HIT",
			"EVICT_REQUEST", "EVICT_WAIT_DATA_ACK", "EVICT_DATA",
			"REFILL_WRTAG", "REFILL_REQUEST", "REFILL_WAIT_DATA_ACK", "REFILL_DATA",
			delayed_enters=[
				("EVICT_DATAD", "EVICT_DATA", lasmim.write_latency-1),
				("REFILL_DATAD", "REFILL_DATA", lasmim.read_latency-1)
			])
		self.submodules += fsm
		
		fsm.act(fsm.IDLE,
			If(self.wishbone.cyc & self.wishbone.stb, fsm.next_state(fsm.TEST_HIT))
		)
		fsm.act(fsm.TEST_HIT,
			If(tag_do.tag == adr_tag,
				self.wishbone.ack.eq(1),
				If(self.wishbone.we,
					tag_di.dirty.eq(1),
					tag_port.we.eq(1)
				),
				fsm.next_state(fsm.IDLE)
			).Else(
				If(tag_do.dirty,
					fsm.next_state(fsm.EVICT_REQUEST)
				).Else(
					fsm.next_state(fsm.REFILL_WRTAG)
				)
			)
		)
		
		fsm.act(fsm.EVICT_REQUEST,
			lasmim.stb.eq(1),
			lasmim.we.eq(1),
			If(lasmim.req_ack, fsm.next_state(fsm.EVICT_WAIT_DATA_ACK))
		)
		fsm.act(fsm.EVICT_WAIT_DATA_ACK,
			If(lasmim.dat_ack, fsm.next_state(fsm.EVICT_DATAD))
		)
		fsm.act(fsm.EVICT_DATA,
			write_to_lasmi.eq(1),
			fsm.next_state(fsm.REFILL_WRTAG)
		)
		
		fsm.act(fsm.REFILL_WRTAG,
			# Write the tag first to set the LASMI address
			tag_port.we.eq(1),
			fsm.next_state(fsm.REFILL_REQUEST)
		)
		fsm.act(fsm.REFILL_REQUEST,
			lasmim.stb.eq(1),
			If(lasmim.req_ack, fsm.next_state(fsm.REFILL_WAIT_DATA_ACK))
		)
		fsm.act(fsm.REFILL_WAIT_DATA_ACK,
			If(lasmim.dat_ack, fsm.next_state(fsm.REFILL_DATAD))
		)
		fsm.act(fsm.REFILL_DATA,
			write_from_lasmi.eq(1),
			fsm.next_state(fsm.TEST_HIT)
		)
Esempio n. 54
0
    def __init__(self, sdram, clk_out, clk_sample, databits, rowbits, colbits,
                 bankbits, burst, tRESET, tCL, tRP, tRFC, tRCD, tREFI, tWR):

        addrbits = rowbits + colbits + bankbits
        assert sdram.dq.nbits == databits
        colabits = colbits if colbits <= 10 else colbits + 1
        max_col = Replicate(1, colbits)
        assert sdram.a.nbits >= colabits
        assert sdram.a.nbits >= rowbits
        assert sdram.ba.nbits == bankbits
        dqmbits = max(databits // 8, 1)
        assert sdram.dqm.nbits == dqmbits
        assert burst <= 1 << colbits

        self.hostif = Record(sdramHostIf(databits, addrbits))

        # DQ handling, tristate, and sampling
        dq = TSTriple(databits)
        self.specials += dq.get_tristate(sdram.dq)
        dq_r = Signal(databits)
        self.clock_domains.cd_sample = ClockDomain(reset_less=True)
        self.comb += self.cd_sample.clk.eq(clk_sample)
        self.sync.sample += dq_r.eq(dq.i)

        # Signals used for driving SDRAM control signals
        # These registered and derived from the current FSM state.
        # However, the reset state actually determines the default value for
        # states where they are not explicitly assigned. For example, cmd is
        # INHIBIT at reset (because the FSM is in RESET state at reset and that
        # sets cmd to INHIBIT), but it's NOP for every other state where it
        # isn't assigned.
        cmd = Signal(4, reset=NOP)
        dqm = Signal()
        ba = Signal(bankbits)
        a = Signal(max(colabits, rowbits))
        cke = Signal()

        sdram.cs_n.reset = 1
        self.sync += [
            sdram.dqm.eq(Replicate(dqm, dqmbits)),
            sdram.cs_n.eq(cmd[3]),
            sdram.ras_n.eq(cmd[2]),
            sdram.cas_n.eq(cmd[1]),
            sdram.we_n.eq(cmd[0]),
            sdram.ba.eq(ba),
            sdram.a.eq(a),
            sdram.cke.eq(cke),
        ]
        self.comb += [
            sdram.clk.eq(clk_out),
        ]

        # Counter to time reset cycle of the SDRAM
        # We enable CKE on the first cycle after system reset, then wait tRESET
        reset_ctr = Signal(max=tRESET + 1)
        self.sync += [cke.eq(1), reset_ctr.eq(reset_ctr + 1)]

        # Counter to time refresh intervals
        # Note that this can go higher than tREFI, since we might be in the
        # middle of a burst, but long-term refresh cycles will be issued often
        # enough to meet refresh timing.
        refresh_interval = tREFI - 2  # A bit of leeway for safety
        refresh_ctr = Signal(max=(refresh_interval + 2 * burst + 128))
        self.sync += If(
            cmd == AUTO_REFRESH,
            If(refresh_ctr > refresh_interval,
               refresh_ctr.eq(refresh_ctr - refresh_interval)).Else(
                   refresh_ctr.eq(0))).Else(refresh_ctr.eq(refresh_ctr + 1))

        tMRD = 3  # JEDEC spec, Micron only needs 2

        # Mode: Full page burst mode, burst write
        mode = 0b0000000111 | (tCL << 4)

        # last_col indicates that the read/write is about to wrap, and so should end
        last_col = Signal()
        i_col_cnt = Signal(colbits)
        self.comb += last_col.eq(i_col_cnt == max_col)

        def delay_clocks(v, d):
            for i in range(d):
                n = Signal()
                self.sync += n.eq(v)
                v = n
            return v

        # Read cycle state signals
        read_cycle = Signal()

        # Reads come back tCL + 1 clocks later. The extra two cycles
        # are due to the registration of FIFO outputs and inputs
        dq_r_sample = Signal(databits)
        self.sync += dq_r_sample.eq(dq_r)

        returning_read = delay_clocks(read_cycle, tCL + 2)
        can_continue_read = Signal()
        kill_read = Signal()
        self.comb += [
            can_continue_read.eq(~self.hostif.d_term & ~last_col & ~kill_read),
            self.hostif.d_read.eq(dq_r_sample),
        ]
        self.sync += [
            # If the output FIFO becomes full, kill the current read
            If(returning_read & self.hostif.d_term,
               kill_read.eq(1)).Elif(~returning_read, kill_read.eq(0)),
        ]

        # Write state signals
        write_cycle = Signal()
        can_continue_write = Signal()

        self.sync += [
            dq.o.eq(self.hostif.d_write),
            dq.oe.eq(write_cycle),
        ]

        self.comb += [
            can_continue_write.eq(~self.hostif.d_term & ~last_col),
            dqm.eq(self.hostif.d_term & write_cycle),
        ]

        # Shared signals
        cmd_needs_reissue = Signal()
        cmd_reissue = Signal()

        self.sync += [
            If(write_cycle | read_cycle, i_col_cnt.eq(i_col_cnt + 1)),
            If(
                ~self.hostif.d_term & last_col & write_cycle
                | read_cycle & last_col & ~kill_read
                & ~(returning_read & self.hostif.d_term),
                cmd_needs_reissue.eq(1)).Elif(cmd_reissue,
                                              cmd_needs_reissue.eq(0))
        ]

        # Hostif streaming interface signal generation
        self.comb += [
            self.hostif.d_stb.eq(write_cycle | returning_read & ~kill_read),
        ]

        # Address generation
        def split(addr):
            col = addr[:colbits]
            if colbits > 10:
                col = Cat(col[:10], 0, col[10:])
            return col, addr[colbits:colbits + rowbits], addr[colbits +
                                                              rowbits:]

        # Issued cmd ptr
        latch_cmd = Signal()
        iwr = Signal(1)
        iptr = Signal(addrbits)
        i_col, i_row, i_bank = split(iptr)

        self.sync += If(latch_cmd, iptr.eq(self.hostif.i_addr),
                        iwr.eq(self.hostif.i_wr),
                        i_col_cnt.eq(split(self.hostif.i_addr)[0])).Elif(
                            cmd_reissue, iptr[:colbits].eq(0),
                            iptr[colbits:].eq(iptr[colbits:] + 1),
                            i_col_cnt.eq(0))

        # Finite state machine driving the controller
        fsm = self.submodules.fsm = FSM(reset_state="RESET")

        # Initialization sequence
        fsm.act("RESET", cmd.eq(INHIBIT),
                If(reset_ctr == tRESET, NextState("INIT_IDLE")))
        fsm.delayed_enter("INIT_IDLE", "INIT_PRECHARGE", 5)
        fsm.act("INIT_PRECHARGE", cmd.eq(PRECHARGE), a[10].eq(1))
        fsm.delayed_enter("INIT_PRECHARGE", "INIT_REFRESH1", tRP)
        fsm.act("INIT_REFRESH1", cmd.eq(AUTO_REFRESH))
        fsm.delayed_enter("INIT_REFRESH1", "INIT_REFRESH2", tRFC)
        fsm.act("INIT_REFRESH2", cmd.eq(AUTO_REFRESH))
        fsm.delayed_enter("INIT_REFRESH2", "INIT_MODE", tRFC)
        fsm.act("INIT_MODE", cmd.eq(LOAD_MODE), a.eq(mode))
        fsm.delayed_enter("INIT_MODE", "IDLE", tMRD)

        # Main loop
        fsm.act(
            "IDLE",
            If(refresh_ctr >= refresh_interval, NextState("REFRESH")).Elif(
                cmd_needs_reissue, cmd_reissue.eq(1),
                If(iwr, NextState("WRITE_ACTIVE")).Else(
                    NextState("READ_ACTIVE"))).Elif(
                        self.hostif.i_wr & self.hostif.i_stb,
                        self.hostif.i_ack.eq(1), latch_cmd.eq(1),
                        NextState("WRITE_ACTIVE")).Elif(
                            ~self.hostif.i_wr & self.hostif.i_stb,
                            self.hostif.i_ack.eq(1), latch_cmd.eq(1),
                            NextState("READ_ACTIVE")))
        # REFRESH
        fsm.act("REFRESH", cmd.eq(AUTO_REFRESH))
        fsm.delayed_enter("REFRESH", "IDLE", tRFC)

        # WRITE
        fsm.act("WRITE_ACTIVE", cmd.eq(ACTIVE), ba.eq(i_bank), a.eq(i_row))
        fsm.delayed_enter("WRITE_ACTIVE", "WRITE", tRCD)
        fsm.act(
            "WRITE", cmd.eq(WRITE), ba.eq(i_bank), a.eq(i_col),
            write_cycle.eq(1),
            If(can_continue_write, NextState("WRITING")).Else(
                If(dqm,
                   NextState("PRECHARGE")).Else(NextState("PRECHARGE_TWR"))))
        fsm.act(
            "WRITING", write_cycle.eq(1),
            If(
                ~can_continue_write,
                If(dqm,
                   NextState("PRECHARGE")).Else(NextState("PRECHARGE_TWR"))))

        # READ
        fsm.act("READ_ACTIVE", cmd.eq(ACTIVE), ba.eq(i_bank), a.eq(i_row))
        fsm.delayed_enter("READ_ACTIVE", "READ", tRCD)
        fsm.act(
            "READ", cmd.eq(READ), ba.eq(i_bank), a.eq(i_col), read_cycle.eq(1),
            If(can_continue_read,
               NextState("READING")).Else(NextState("PRECHARGE")))
        fsm.act("READING", read_cycle.eq(1),
                If(~can_continue_read, NextState("PRECHARGE")))

        if (tWR - 1) > 0:
            fsm.act("PRECHARGE_TWR", cmd.eq(BURST_TERM))

        fsm.delayed_enter("PRECHARGE_TWR", "PRECHARGE", tWR - 1),
        fsm.act("PRECHARGE", cmd.eq(PRECHARGE), a[10].eq(1)),
        fsm.delayed_enter("PRECHARGE", "IDLE", tRP)
Esempio n. 55
0
    def __init__(self, rtio_core):
        self.source = stream.Endpoint([("data", 256)])

        self.overflow = CSRStatus()
        self.overflow_reset = CSR()

        # # #

        kcsrs = rtio_core.kcsrs

        input_output_stb = Signal()
        input_output = Record(input_output_layout)
        if hasattr(kcsrs, "o_data"):
            o_data = kcsrs.o_data.storage
        else:
            o_data = 0
        if hasattr(kcsrs, "o_address"):
            o_address = kcsrs.o_address.storage
        else:
            o_address = 0
        if hasattr(kcsrs, "i_data"):
            i_data = kcsrs.i_data.status
        else:
            i_data = 0
        self.comb += [
            input_output.channel.eq(kcsrs.chan_sel.storage),
            input_output.address_padding.eq(o_address),
            input_output.rtio_counter.eq(
                rtio_core.counter.value_sys << rtio_core.fine_ts_width),
            If(kcsrs.o_we.re,
                input_output.message_type.eq(MessageType.output.value),
                input_output.timestamp.eq(kcsrs.o_timestamp.storage),
                input_output.data.eq(o_data)
            ).Else(
                input_output.message_type.eq(MessageType.input.value),
                input_output.timestamp.eq(kcsrs.i_timestamp.status),
                input_output.data.eq(i_data)
            ),
            input_output_stb.eq(kcsrs.o_we.re | kcsrs.i_re.re)
        ]

        exception_stb = Signal()
        exception = Record(exception_layout)
        self.comb += [
            exception.message_type.eq(MessageType.exception.value),
            exception.channel.eq(kcsrs.chan_sel.storage),
            exception.rtio_counter.eq(
                rtio_core.counter.value_sys << rtio_core.fine_ts_width),
        ]
        for ename in ("o_underflow_reset", "o_sequence_error_reset",
                      "o_collision_error_reset", "i_overflow_reset"):
            self.comb += \
                If(getattr(kcsrs, ename).re,
                    exception_stb.eq(1),
                    exception.exception_type.eq(
                        getattr(ExceptionType, ename).value)
                )
        for rname in "reset", "reset_phy":
            r_d = Signal(reset=1)
            r = getattr(kcsrs, rname).storage
            self.sync += r_d.eq(r)
            self.comb += [
                If(r & ~r_d,
                    exception_stb.eq(1),
                    exception.exception_type.eq(
                        getattr(ExceptionType, rname+"_rising").value)
                ),
                If(~r & r_d,
                    exception_stb.eq(1),
                    exception.exception_type.eq(
                        getattr(ExceptionType, rname+"_falling").value)
                )
            ]

        self.sync += [
            If(exception_stb,
                self.source.data.eq(exception.raw_bits())
            ).Else(
                self.source.data.eq(input_output.raw_bits())
            ),
            self.source.stb.eq(input_output_stb | exception_stb)
        ]

        self.sync += [
            If(self.overflow_reset.re, self.overflow.status.eq(0)),
            If(self.source.stb & ~self.source.ack,
                self.overflow.status.eq(1)
            )
        ]
Esempio n. 56
0
    def __init__(self,
                 channels,
                 glbl_fine_ts_width,
                 mode,
                 quash_channels=[],
                 interface=None):
        if interface is None:
            interface = cri.Interface()
        self.cri = interface
        self.coarse_timestamp = Signal(64 - glbl_fine_ts_width)

        # # #

        if mode == "sync":
            fifo_factory = SyncFIFOBuffered
            sync_io = self.sync
            sync_cri = self.sync
        elif mode == "async":
            fifo_factory = lambda *args: ClockDomainsRenamer({
                "write": "rio",
                "read": "rsys"
            })(AsyncFIFO(*args))
            sync_io = self.sync.rio
            sync_cri = self.sync.rsys
        else:
            raise ValueError

        i_statuses, i_datas, i_timestamps = [], [], []
        i_ack = Signal()
        sel = self.cri.chan_sel[:16]
        for n, channel in enumerate(channels):
            iif = channel.interface.i
            if iif is None or n in quash_channels:
                i_datas.append(0)
                i_timestamps.append(0)
                i_statuses.append(0)
                continue

            # FIFO
            layout = get_channel_layout(len(self.coarse_timestamp), iif)
            fifo = fifo_factory(layout_len(layout), channel.ififo_depth)
            self.submodules += fifo
            fifo_in = Record(layout)
            fifo_out = Record(layout)
            self.comb += [
                fifo.din.eq(fifo_in.raw_bits()),
                fifo_out.raw_bits().eq(fifo.dout)
            ]

            # FIFO write
            if iif.delay:
                counter_rtio = Signal.like(self.coarse_timestamp,
                                           reset_less=True)
                sync_io += counter_rtio.eq(self.coarse_timestamp -
                                           (iif.delay + 1))
            else:
                counter_rtio = self.coarse_timestamp
            if hasattr(fifo_in, "data"):
                self.comb += fifo_in.data.eq(iif.data)
            if hasattr(fifo_in, "timestamp"):
                if hasattr(iif, "fine_ts"):
                    full_ts = Cat(iif.fine_ts, counter_rtio)
                else:
                    full_ts = counter_rtio
                self.comb += fifo_in.timestamp.eq(full_ts)
            self.comb += fifo.we.eq(iif.stb)

            overflow_io = Signal()
            self.comb += overflow_io.eq(fifo.we & ~fifo.writable)
            if mode == "sync":
                overflow_trigger = overflow_io
            elif mode == "async":
                overflow_transfer = BlindTransfer()
                self.submodules += overflow_transfer
                self.comb += overflow_transfer.i.eq(overflow_io)
                overflow_trigger = overflow_transfer.o
            else:
                raise ValueError

            # FIFO read, CRI connection
            if hasattr(fifo_out, "data"):
                i_datas.append(fifo_out.data)
            else:
                i_datas.append(0)
            if hasattr(fifo_out, "timestamp"):
                ts_shift = 64 - len(fifo_out.timestamp)
                i_timestamps.append(fifo_out.timestamp << ts_shift)
            else:
                i_timestamps.append(0)

            selected = Signal()
            self.comb += selected.eq(sel == n)

            overflow = Signal()
            sync_cri += [
                If(selected & i_ack, overflow.eq(0)),
                If(overflow_trigger, overflow.eq(1))
            ]
            self.comb += fifo.re.eq(selected & i_ack & ~overflow)
            i_statuses.append(Cat(fifo.readable & ~overflow, overflow))

        i_status_raw = Signal(2)
        self.comb += i_status_raw.eq(Array(i_statuses)[sel])
        input_timeout = Signal.like(self.cri.timestamp, reset_less=True)
        input_pending = Signal()
        self.cri.i_data.reset_less = True
        self.cri.i_timestamp.reset_less = True
        sync_cri += [
            i_ack.eq(0),
            If(
                i_ack,
                self.cri.i_status.eq(Cat(~i_status_raw[0], i_status_raw[1],
                                         0)),
                self.cri.i_data.eq(Array(i_datas)[sel]),
                self.cri.i_timestamp.eq(Array(i_timestamps)[sel]),
            ),
            If((self.cri.counter >= input_timeout) | (i_status_raw != 0),
               If(input_pending, i_ack.eq(1)), input_pending.eq(0)),
            If(self.cri.cmd == cri.commands["read"],
               input_timeout.eq(self.cri.timestamp), input_pending.eq(1),
               self.cri.i_status.eq(0b100))
        ]
Esempio n. 57
0
	def __init__(self, cachesize, lasmim, wbm=None):
		if wbm is None:
			wbm = wishbone.Interface()
		self.wishbone = wbm

		###

		data_width = flen(self.wishbone.dat_r)
		if lasmim.dw < data_width:
			raise ValueError("LASMI data width must be >= {dw}".format(dw=data_width))
		if (lasmim.dw % data_width) != 0:
			raise ValueError("LASMI data width must be a multiple of {dw}".format(dw=data_width))

		# Split address:
		# TAG | LINE NUMBER | LINE OFFSET
		offsetbits = log2_int(lasmim.dw//data_width)
		addressbits = lasmim.aw + offsetbits
		linebits = log2_int(cachesize) - offsetbits
		tagbits = addressbits - linebits
		adr_offset, adr_line, adr_tag = split(self.wishbone.adr, offsetbits, linebits, tagbits)
		
		# Data memory
		data_mem = Memory(lasmim.dw, 2**linebits)
		data_port = data_mem.get_port(write_capable=True, we_granularity=8)
		self.specials += data_mem, data_port
		
		write_from_lasmi = Signal()
		write_to_lasmi = Signal()
		if adr_offset is None:
			adr_offset_r = None
		else:
			adr_offset_r = Signal(offsetbits)
			self.sync += adr_offset_r.eq(adr_offset)

		self.comb += [
			data_port.adr.eq(adr_line),
			If(write_from_lasmi,
				data_port.dat_w.eq(lasmim.dat_r),
				data_port.we.eq(Replicate(1, lasmim.dw//8))
			).Else(
				data_port.dat_w.eq(Replicate(self.wishbone.dat_w, lasmim.dw//data_width)),
				If(self.wishbone.cyc & self.wishbone.stb & self.wishbone.we & self.wishbone.ack,
					displacer(self.wishbone.sel, adr_offset, data_port.we, 2**offsetbits, reverse=True)
				)
			),
			If(write_to_lasmi, 
				lasmim.dat_w.eq(data_port.dat_r),
				lasmim.dat_we.eq(2**(lasmim.dw//8)-1)
			),
			chooser(data_port.dat_r, adr_offset_r, self.wishbone.dat_r, reverse=True)
		]

		
		# Tag memory
		tag_layout = [("tag", tagbits), ("dirty", 1)]
		tag_mem = Memory(layout_len(tag_layout), 2**linebits)
		tag_port = tag_mem.get_port(write_capable=True)
		self.specials += tag_mem, tag_port
		tag_do = Record(tag_layout)
		tag_di = Record(tag_layout)
		self.comb += [
			tag_do.raw_bits().eq(tag_port.dat_r),
			tag_port.dat_w.eq(tag_di.raw_bits())
		]
			
		self.comb += [
			tag_port.adr.eq(adr_line),
			tag_di.tag.eq(adr_tag),
			lasmim.adr.eq(Cat(adr_line, tag_do.tag))
		]
		
		# Control FSM
		assert(lasmim.write_latency >= 1 and lasmim.read_latency >= 1)
		fsm = FSM()
		self.submodules += fsm
		
		fsm.delayed_enter("EVICT_DATAD", "EVICT_DATA", lasmim.write_latency-1)
		fsm.delayed_enter("REFILL_DATAD", "REFILL_DATA", lasmim.read_latency-1)

		fsm.act("IDLE",
			If(self.wishbone.cyc & self.wishbone.stb, NextState("TEST_HIT"))
		)
		fsm.act("TEST_HIT",
			If(tag_do.tag == adr_tag,
				self.wishbone.ack.eq(1),
				If(self.wishbone.we,
					tag_di.dirty.eq(1),
					tag_port.we.eq(1)
				),
				NextState("IDLE")
			).Else(
				If(tag_do.dirty,
					NextState("EVICT_REQUEST")
				).Else(
					NextState("REFILL_WRTAG")
				)
			)
		)
		
		fsm.act("EVICT_REQUEST",
			lasmim.stb.eq(1),
			lasmim.we.eq(1),
			If(lasmim.req_ack, NextState("EVICT_WAIT_DATA_ACK"))
		)
		fsm.act("EVICT_WAIT_DATA_ACK",
			If(lasmim.dat_ack, NextState("EVICT_DATAD"))
		)
		fsm.act("EVICT_DATA",
			write_to_lasmi.eq(1),
			NextState("REFILL_WRTAG")
		)
		
		fsm.act("REFILL_WRTAG",
			# Write the tag first to set the LASMI address
			tag_port.we.eq(1),
			NextState("REFILL_REQUEST")
		)
		fsm.act("REFILL_REQUEST",
			lasmim.stb.eq(1),
			If(lasmim.req_ack, NextState("REFILL_WAIT_DATA_ACK"))
		)
		fsm.act("REFILL_WAIT_DATA_ACK",
			If(lasmim.dat_ack, NextState("REFILL_DATAD"))
		)
		fsm.act("REFILL_DATA",
			write_from_lasmi.eq(1),
			NextState("TEST_HIT")
		)