Пример #1
0
    def __init__(self, crc_class, layout):
        self.sink = sink = stream.Endpoint(layout)
        self.source = source = stream.Endpoint(layout)
        self.busy = Signal()

        # # #

        dw = len(sink.data)
        crc = crc_class(dw)
        fsm = FSM(reset_state="IDLE")
        self.submodules += crc, fsm

        fsm.act("IDLE",
            crc.reset.eq(1),
            sink.ready.eq(1),
            If(sink.valid,
                sink.ready.eq(0),
                NextState("COPY"),
            )
        )
        fsm.act("COPY",
            crc.ce.eq(sink.valid & source.ready),
            crc.data.eq(sink.data),
            sink.connect(source),
            source.last.eq(0),
            If(sink.valid & sink.last & source.ready,
                NextState("INSERT"),
            )
        )
        ratio = crc.width//dw
        if ratio > 1:
            cnt = Signal(max=ratio, reset=ratio-1)
            cnt_done = Signal()
            fsm.act("INSERT",
                source.valid.eq(1),
                chooser(crc.value, cnt, source.data, reverse=True),
                If(cnt_done,
                    source.last.eq(1),
                    If(source.ready, NextState("IDLE"))
                )
            )
            self.comb += cnt_done.eq(cnt == 0)
            self.sync += \
                If(fsm.ongoing("IDLE"),
                    cnt.eq(cnt.reset)
                ).Elif(fsm.ongoing("INSERT") & ~cnt_done,
                    cnt.eq(cnt - source.ready)
                )
        else:
            fsm.act("INSERT",
                source.valid.eq(1),
                source.last.eq(1),
                source.data.eq(crc.value),
                If(source.ready, NextState("IDLE"))
            )
        self.comb += self.busy.eq(~fsm.ongoing("IDLE"))
Пример #2
0
Файл: crc.py Проект: olofk/misoc
    def __init__(self, crc_class, layout):
        self.sink = sink = Sink(layout)
        self.source = source = Source(layout)
        self.busy = Signal()

        # # #

        dw = flen(sink.data)
        crc = crc_class(dw)
        fsm = FSM(reset_state="IDLE")
        self.submodules += crc, fsm

        fsm.act("IDLE",
            crc.reset.eq(1),
            sink.ack.eq(1),
            If(sink.stb & sink.sop,
                sink.ack.eq(0),
                NextState("COPY"),
            )
        )
        fsm.act("COPY",
            crc.ce.eq(sink.stb & source.ack),
            crc.data.eq(sink.data),
            Record.connect(sink, source),
            source.eop.eq(0),
            If(sink.stb & sink.eop & source.ack,
                NextState("INSERT"),
            )
        )
        ratio = crc.width//dw
        if ratio > 1:
            cnt = Signal(max=ratio, reset=ratio-1)
            cnt_done = Signal()
            fsm.act("INSERT",
                source.stb.eq(1),
                chooser(crc.value, cnt, source.data, reverse=True),
                If(cnt_done,
                    source.eop.eq(1),
                    If(source.ack, NextState("IDLE"))
                )
            )
            self.comb += cnt_done.eq(cnt == 0)
            self.sync += \
                If(fsm.ongoing("IDLE"),
                    cnt.eq(cnt.reset)
                ).Elif(fsm.ongoing("INSERT") & ~cnt_done,
                    cnt.eq(cnt - source.ack)
                )
        else:
            fsm.act("INSERT",
                source.stb.eq(1),
                source.eop.eq(1),
                source.data.eq(crc.value),
                If(source.ack, NextState("IDLE"))
            )
        self.comb += self.busy.eq(~fsm.ongoing("IDLE"))
Пример #3
0
    def __init__(self, phy, mem, syncWord=0x42):
        self.o_done = Signal()
        self.o_tx = Signal()
        self.i_trig = Signal()

        ###

        self.specials.p = p = mem.get_port(write_capable=False)
        dataByte = Signal(8)
        wordIndMax = mem.depth - 1
        byteIndMax = ceil(mem.width / 8) - 1
        print("MemoryDumper: byteIndMax={} wordIndMax={}".format(
            byteIndMax, wordIndMax))
        byteInd = Signal(max=byteIndMax + 1)
        byteInd_ce = Signal()  # Pulse to increment byte / addr pointer
        is_last_byte = Signal()  # Latches high when last byte was sent

        self.sync += [
            # Logic for incrementing data pointers: byteInd / p.adr
            If(
                byteInd_ce,
                If(
                    byteInd >= byteIndMax, byteInd.eq(0),
                    If(p.adr >= wordIndMax, is_last_byte.eq(1),
                       p.adr.eq(0)).Else(p.adr.eq(p.adr + 1), )).Else(
                           byteInd.eq(byteInd + 1))),
            self.o_done.eq(0),
            byteInd_ce.eq(0)
        ]

        self.submodules.fsm = fsm = FSM()
        fsm.act("IDLE", If(self.i_trig, NextState("SYNC")))
        fsm.act("SYNC", phy.sink.valid.eq(1), phy.sink.data.eq(syncWord),
                NextState("WAIT"))
        fsm.act("SEND", phy.sink.valid.eq(1), phy.sink.data.eq(dataByte),
                NextValue(byteInd_ce, 1), NextState("WAIT"))
        fsm.act(
            "WAIT",
            If(
                phy.sink.ready,
                If(is_last_byte, NextState("IDLE"), NextValue(self.o_done, 1),
                   NextValue(is_last_byte, 0)).Else(NextState("SEND"))))
        self.comb += [
            chooser(  # Selects one byte of the dat_r word
                p.dat_r,
                byteInd,
                dataByte,
                n=ceil(mem.width / 8),
                reverse=True)
        ]
Пример #4
0
    def __init__(self, dw):
        self.sink = stream.Endpoint(eth_phy_layout(dw))
        self.source = stream.Endpoint(eth_phy_layout(dw))

        # # #

        preamble = Signal(64, reset=eth_preamble)
        cnt_max = (64//dw)-1
        cnt = Signal(max=cnt_max+1)
        clr_cnt = Signal()
        inc_cnt = Signal()

        self.sync += \
            If(clr_cnt,
                cnt.eq(0)
            ).Elif(inc_cnt,
                cnt.eq(cnt+1)
            )

        fsm = FSM(reset_state="IDLE")
        self.submodules += fsm
        fsm.act("IDLE",
            self.sink.ack.eq(1),
            clr_cnt.eq(1),
            If(self.sink.stb,
                self.sink.ack.eq(0),
                NextState("INSERT"),
            )
        )
        fsm.act("INSERT",
            self.source.stb.eq(1),
            chooser(preamble, cnt, self.source.data),
            If(cnt == cnt_max,
                If(self.source.ack, NextState("COPY"))
            ).Else(
                inc_cnt.eq(self.source.ack)
            )
        )

        self.comb += [
            self.source.data.eq(self.sink.data),
            self.source.last_be.eq(self.sink.last_be)
        ]
        fsm.act("COPY",
            self.sink.connect(self.source, omit=set(["data", "last_be"])),

            If(self.sink.stb & self.sink.eop & self.source.ack,
                NextState("IDLE"),
            )
        )
Пример #5
0
	def __init__(self, d_w):
		self.sink = Sink(eth_description(d_w))
		self.source = Source(eth_description(d_w))

		###

		preamble = Signal(64, reset=eth_preamble)
		cnt_max = (64//d_w)-1
		cnt = Signal(max=cnt_max+1)
		clr_cnt = Signal()
		inc_cnt = Signal()

		self.sync += \
			If(clr_cnt,
				cnt.eq(0)
			).Elif(inc_cnt,
				cnt.eq(cnt+1)
			)

		fsm = FSM(reset_state="IDLE")
		self.submodules += fsm
		fsm.act("IDLE",
			self.sink.ack.eq(1),
			clr_cnt.eq(1),
			If(self.sink.stb & self.sink.sop,
				self.sink.ack.eq(0),
				NextState("INSERT"),
			)
		)
		fsm.act("INSERT",
			self.source.stb.eq(1),
			self.source.sop.eq(cnt==0),
			chooser(preamble, cnt, self.source.d),
			If(cnt == cnt_max,
				If(self.source.ack, NextState("COPY"))
			).Else(
				inc_cnt.eq(self.source.ack)
			)
		)
		fsm.act("COPY",
			Record.connect(self.sink, self.source),
			self.source.sop.eq(0),

			If(self.sink.stb & self.sink.eop & self.source.ack,
				NextState("IDLE"),
			)
		)
Пример #6
0
	def get_fragment(self):
		port = self.mem.get_port(write_capable=not self.read_only,
			we_granularity=data_width if not self.read_only and self.word_bits else 0)
		
		sel = Signal()
		sel_r = Signal()
		sync = [sel_r.eq(sel)]
		comb = [sel.eq(self.bus.adr[9:] == self.address)]

		if self.word_bits:
			word_index = Signal(self.word_bits)
			word_expanded = Signal(self.csrw_per_memw*data_width)
			sync.append(word_index.eq(self.bus.adr[:self.word_bits]))
			comb += [
				word_expanded.eq(port.dat_r),
				If(sel_r,
					chooser(word_expanded, word_index, self.bus.dat_r, n=self.csrw_per_memw, reverse=True)
				)
			]
			if not self.read_only:
				comb += [
					If(sel & self.bus.we, port.we.eq((1 << self.word_bits) >> self.bus.adr[:self.word_bits])),
					port.dat_w.eq(Replicate(self.bus.dat_w, self.csrw_per_memw))
				]
		else:
			comb += [
				If(sel_r,
					self.bus.dat_r.eq(port.dat_r)
				)
			]
			if not self.read_only:
				comb += [
					port.we.eq(sel & self.bus.we),
					port.dat_w.eq(self.bus.dat_w)
				]
		
		if self._page is None:
			comb.append(port.adr.eq(self.bus.adr[self.word_bits:len(port.adr)]))
		else:
			pv = self._page.field.r
			comb.append(port.adr.eq(Cat(self.bus.adr[self.word_bits:len(port.adr)-len(pv)], pv)))
		
		return Fragment(comb, sync, specials={self.mem})
Пример #7
0
	def __init__(self, pads, default=_default_edid):
		self.specials.mem = Memory(8, 128, init=default)

		###

		scl_raw = Signal()
		sda_i = Signal()
		sda_drv = Signal()
		_sda_drv_reg = Signal()
		_sda_i_async = Signal()
		self.sync += _sda_drv_reg.eq(sda_drv)
		self.specials += [
			MultiReg(pads.scl, scl_raw),
			Tristate(pads.sda, 0, _sda_drv_reg, _sda_i_async),
			MultiReg(_sda_i_async, sda_i)
		]

		scl_i = Signal()
		samp_count = Signal(6)
		samp_carry = Signal()
		self.sync += [
			Cat(samp_count, samp_carry).eq(samp_count + 1),
			If(samp_carry, scl_i.eq(scl_raw))
		]

		scl_r = Signal()
		sda_r = Signal()
		scl_rising = Signal()
		sda_rising = Signal()
		sda_falling = Signal()
		self.sync += [
			scl_r.eq(scl_i),
			sda_r.eq(sda_i)
		]
		self.comb += [
			scl_rising.eq(scl_i & ~scl_r),
			sda_rising.eq(sda_i & ~sda_r),
			sda_falling.eq(~sda_i & sda_r)
		]

		start = Signal()
		self.comb += start.eq(scl_i & sda_falling)

		din = Signal(8)
		counter = Signal(max=9)
		self.sync += [
			If(start, counter.eq(0)),
			If(scl_rising,
				If(counter == 8,
					counter.eq(0)
				).Else(
					counter.eq(counter + 1),
					din.eq(Cat(sda_i, din[:7]))
				)
			)
		]

		is_read = Signal()
		update_is_read = Signal()
		self.sync += If(update_is_read, is_read.eq(din[0]))

		offset_counter = Signal(max=128)
		oc_load = Signal()
		oc_inc = Signal()
		self.sync += [
			If(oc_load,
				offset_counter.eq(din)
			).Elif(oc_inc,
				offset_counter.eq(offset_counter + 1)
			)
		]
		rdport = self.mem.get_port()
		self.comb += rdport.adr.eq(offset_counter)
		data_bit = Signal()

		zero_drv = Signal()
		data_drv = Signal()
		self.comb += If(zero_drv, sda_drv.eq(1)).Elif(data_drv, sda_drv.eq(~data_bit))

		data_drv_en = Signal()
		data_drv_stop = Signal()
		self.sync += If(data_drv_en, data_drv.eq(1)).Elif(data_drv_stop, data_drv.eq(0))
		self.sync += If(data_drv_en, chooser(rdport.dat_r, counter, data_bit, 8, reverse=True))

		states = ["WAIT_START",
			"RCV_ADDRESS", "ACK_ADDRESS0", "ACK_ADDRESS1", "ACK_ADDRESS2",
			"RCV_OFFSET", "ACK_OFFSET0", "ACK_OFFSET1", "ACK_OFFSET2",
			"READ", "ACK_READ"]
		fsm = FSM(*states)
		self.submodules += fsm
	
		fsm.act(fsm.RCV_ADDRESS,
			If(counter == 8,
				If(din[1:] == 0x50,
					update_is_read.eq(1),
					fsm.next_state(fsm.ACK_ADDRESS0)
				).Else(
					fsm.next_state(fsm.WAIT_START)
				)
			)
		)
		fsm.act(fsm.ACK_ADDRESS0,
			If(~scl_i, fsm.next_state(fsm.ACK_ADDRESS1))
		)
		fsm.act(fsm.ACK_ADDRESS1,
			zero_drv.eq(1),
			If(scl_i, fsm.next_state(fsm.ACK_ADDRESS2))
		)
		fsm.act(fsm.ACK_ADDRESS2,
			zero_drv.eq(1),
			If(~scl_i,
				If(is_read,
					fsm.next_state(fsm.READ)
				).Else(
					fsm.next_state(fsm.RCV_OFFSET)
				)
			)
		)

		fsm.act(fsm.RCV_OFFSET,
			If(counter == 8,
				oc_load.eq(1),
				fsm.next_state(fsm.ACK_OFFSET0)
			)
		)
		fsm.act(fsm.ACK_OFFSET0,
			If(~scl_i, fsm.next_state(fsm.ACK_OFFSET1))
		)
		fsm.act(fsm.ACK_OFFSET1,
			zero_drv.eq(1),
			If(scl_i, fsm.next_state(fsm.ACK_OFFSET2))
		)
		fsm.act(fsm.ACK_OFFSET2,
			zero_drv.eq(1),
			If(~scl_i, fsm.next_state(fsm.RCV_ADDRESS))
		)

		fsm.act(fsm.READ,
			If(~scl_i,
				If(counter == 8,
					data_drv_stop.eq(1),
					fsm.next_state(fsm.ACK_READ)
				).Else(
					data_drv_en.eq(1)
				)
			)
		)
		fsm.act(fsm.ACK_READ,
			If(scl_rising,
				oc_inc.eq(1),
				If(sda_i,
					fsm.next_state(fsm.WAIT_START)
				).Else(
					fsm.next_state(fsm.READ)
				)
			)
		)

		for state in states:
			fsm.act(getattr(fsm, state), If(start, fsm.next_state(fsm.RCV_ADDRESS)))
Пример #8
0
    def __init__(self, pads):

        STATUS_FULL = 1
        STATUS_EMPTY = 2

        self.shift_reg = shift_reg = CSRStorage(8, write_from_dev=True)
        self.status = status = CSRStorage(2, reset=STATUS_EMPTY, write_from_dev=True)
        self.slave_addr = slave_addr = CSRStorage(7)
        self.pads = pads

        ###

        scl_raw = Signal()
        sda_i = Signal()
        sda_raw = Signal()
        sda_drv = Signal()
        scl_drv = Signal()
        _sda_drv_reg = Signal()
        self._sda_i_async = _sda_i_async = Signal()
        self._scl_i_async = _scl_i_async = Signal()
        _scl_drv_reg = Signal()
        self.sync += _sda_drv_reg.eq(sda_drv)
        self.sync += _scl_drv_reg.eq(scl_drv)
        self.specials += [
            Tristate(pads.sda, 0, _sda_drv_reg, _sda_i_async),
            Tristate(pads.scl, 0, _scl_drv_reg, _scl_i_async),
            MultiReg(_scl_i_async, scl_raw),
            MultiReg(_sda_i_async, sda_raw),
        ]

        # for debug
        self.scl = scl_raw
        self.sda_i = sda_i
        self.sda_o = Signal()
        self.comb += self.sda_o.eq(~_sda_drv_reg)
        self.sda_oe = _sda_drv_reg

        shift_reg_full = Signal()
        shift_reg_empty = Signal()
        scl_i = Signal()
        samp_count = Signal(3)
        samp_carry = Signal()
        self.sync += [
            Cat(samp_count, samp_carry).eq(samp_count + 1),
            If(samp_carry,
                scl_i.eq(scl_raw),
                sda_i.eq(sda_raw)
            )
        ]

        scl_r = Signal()
        sda_r = Signal()
        scl_rising = Signal()
        scl_falling = Signal()
        sda_rising = Signal()
        sda_falling = Signal()
        self.sync += [
            scl_r.eq(scl_i),
            sda_r.eq(sda_i)
        ]
        self.comb += [
            shift_reg_full.eq(status.storage[0]),
            shift_reg_empty.eq(status.storage[1]),
            scl_rising.eq(scl_i & ~scl_r),
            scl_falling.eq(~scl_i & scl_r),
            sda_rising.eq(sda_i & ~sda_r),
            sda_falling.eq(~sda_i & sda_r)
        ]

        start = Signal()
        self.comb += start.eq(scl_i & sda_falling)

        din = Signal(8)
        counter = Signal(max=9)
        counter_reset = Signal()
        self.sync += [
            If(start | counter_reset, counter.eq(0)),
            If(scl_rising,
                If(counter == 8,
                    counter.eq(0)
                ).Else(
                    counter.eq(counter + 1),
                    din.eq(Cat(sda_i, din[:7]))
                )
            )
        ]

        self.din = din
        self.counter = counter

        is_read = Signal()
        update_is_read = Signal()
        self.sync += If(update_is_read, is_read.eq(din[0]))
        data_bit = Signal()

        zero_drv = Signal()
        data_drv = Signal()
        pause_drv = Signal()
        self.comb += scl_drv.eq(pause_drv)
        self.comb += If(zero_drv, sda_drv.eq(1)).Elif(data_drv,
                                                      sda_drv.eq(~data_bit))

        data_drv_en = Signal()
        data_drv_stop = Signal()
        self.sync += If(data_drv_en, data_drv.eq(1)).Elif(data_drv_stop,
                                                          data_drv.eq(0))
        self.sync += If(data_drv_en, chooser(shift_reg.storage,
                                             counter, data_bit, 8,
                                             reverse=True))
        self.submodules.fsm = fsm = FSM()

        fsm.act("WAIT_START",
            data_drv_stop.eq(1),
	    )
        fsm.act("RCV_ADDRESS",
            data_drv_stop.eq(1),
            If(counter == 8,
                If(din[1:] == slave_addr.storage,
                    update_is_read.eq(1),
                    NextState("ACK_ADDRESS0"),
                ).Else(
                    NextState("WAIT_START"),
                )
            )
        )
        fsm.act("ACK_ADDRESS0",
            counter_reset.eq(1),
            If(~scl_i, NextState("ACK_ADDRESS1")),
        )
        fsm.act("ACK_ADDRESS1",
            counter_reset.eq(1),
            zero_drv.eq(1),
            If(scl_i, NextState("ACK_ADDRESS2")),
        )
        fsm.act("ACK_ADDRESS2",
            counter_reset.eq(1),
            zero_drv.eq(1),
            If(~scl_i,
                    NextState("PAUSE")
            )
        )
        fsm.act("PAUSE",
            counter_reset.eq(1),
            pause_drv.eq(1),
            If(~shift_reg_empty & is_read,
               counter_reset.eq(1),
               NextState("DO_READ"),
            ).Elif(~shift_reg_full & ~is_read,
               NextState("DO_WRITE"),
            )
        )
        fsm.act("DO_READ",
            If(~scl_i,
                If(counter == 8,
                   data_drv_stop.eq(1),
                   status.we.eq(1),
                   status.dat_w.eq(STATUS_EMPTY),
                   NextState("ACK_READ0"),
                ).Else(
                    data_drv_en.eq(1),
                )
            )
        )
        fsm.act("ACK_READ0",
            counter_reset.eq(1),
            If(scl_rising,
               If(sda_i,
                  NextState("WAIT_START"),
               ).Else(
                  NextState("ACK_READ1"),
               )
            )
        )
        fsm.act("ACK_READ1",
            counter_reset.eq(1),
            If(scl_falling,
               NextState("PAUSE"),
            )
        )
        fsm.act("DO_WRITE",
            If(counter == 8,
                shift_reg.dat_w.eq(din),
                shift_reg.we.eq(1),
                NextState("ACK_WRITE0"),
            )
        )
        fsm.act("ACK_WRITE0",
            counter_reset.eq(1),
            If(~scl_i, NextState("ACK_WRITE1")),
        )
        fsm.act("ACK_WRITE1",
            counter_reset.eq(1),
            zero_drv.eq(1),
            If(scl_i, NextState("ACK_WRITE2")),
        )
        fsm.act("ACK_WRITE2",
            counter_reset.eq(1),
            zero_drv.eq(1),
            If(~scl_i,
                NextState("PAUSE"),
                status.we.eq(1),
                status.dat_w.eq(STATUS_FULL),
            )
        )

        for state in fsm.actions.keys():
            fsm.act(state, If(start, NextState("RCV_ADDRESS")))

        for state in fsm.actions.keys():
            fsm.act(state, If(self.slave_addr.re, NextState("WAIT_START")))
Пример #9
0
    def __init__(self, phy, clk_freq):
        self.wishbone = wishbone.Interface()

        # # #

        byte_counter = Counter(3)
        word_counter = Counter(8)
        self.submodules += byte_counter, word_counter

        cmd = Signal(8)
        cmd_ce = Signal()

        length = Signal(8)
        length_ce = Signal()

        address = Signal(32)
        address_ce = Signal()

        data = Signal(32)
        rx_data_ce = Signal()
        tx_data_ce = Signal()

        self.sync += [
            If(cmd_ce, cmd.eq(phy.source.data)),
            If(length_ce, length.eq(phy.source.data)),
            If(address_ce, address.eq(Cat(phy.source.data, address[0:24]))),
            If(rx_data_ce, data.eq(Cat(phy.source.data, data[0:24]))).Elif(tx_data_ce, data.eq(self.wishbone.dat_r)),
        ]

        fsm = InsertReset(FSM(reset_state="IDLE"))
        timer = WaitTimer(clk_freq // 10)
        self.submodules += fsm, timer
        self.comb += [fsm.reset.eq(timer.done), phy.source.ack.eq(1)]
        fsm.act(
            "IDLE",
            If(
                phy.source.stb,
                cmd_ce.eq(1),
                If(
                    (phy.source.data == self.cmds["write"]) | (phy.source.data == self.cmds["read"]),
                    NextState("RECEIVE_LENGTH"),
                ),
                byte_counter.reset.eq(1),
                word_counter.reset.eq(1),
            ),
        )
        fsm.act("RECEIVE_LENGTH", If(phy.source.stb, length_ce.eq(1), NextState("RECEIVE_ADDRESS")))
        fsm.act(
            "RECEIVE_ADDRESS",
            If(
                phy.source.stb,
                address_ce.eq(1),
                byte_counter.ce.eq(1),
                If(
                    byte_counter.value == 3,
                    If(cmd == self.cmds["write"], NextState("RECEIVE_DATA")).Elif(
                        cmd == self.cmds["read"], NextState("READ_DATA")
                    ),
                    byte_counter.reset.eq(1),
                ),
            ),
        )
        fsm.act(
            "RECEIVE_DATA",
            If(
                phy.source.stb,
                rx_data_ce.eq(1),
                byte_counter.ce.eq(1),
                If(byte_counter.value == 3, NextState("WRITE_DATA"), byte_counter.reset.eq(1)),
            ),
        )
        self.comb += [
            self.wishbone.adr.eq(address + word_counter.value),
            self.wishbone.dat_w.eq(data),
            self.wishbone.sel.eq(2 ** flen(self.wishbone.sel) - 1),
        ]
        fsm.act(
            "WRITE_DATA",
            self.wishbone.stb.eq(1),
            self.wishbone.we.eq(1),
            self.wishbone.cyc.eq(1),
            If(
                self.wishbone.ack,
                word_counter.ce.eq(1),
                If(word_counter.value == (length - 1), NextState("IDLE")).Else(NextState("RECEIVE_DATA")),
            ),
        )
        fsm.act(
            "READ_DATA",
            self.wishbone.stb.eq(1),
            self.wishbone.we.eq(0),
            self.wishbone.cyc.eq(1),
            If(self.wishbone.ack, tx_data_ce.eq(1), NextState("SEND_DATA")),
        )
        self.comb += chooser(data, byte_counter.value, phy.sink.data, n=4, reverse=True)
        fsm.act(
            "SEND_DATA",
            phy.sink.stb.eq(1),
            If(
                phy.sink.ack,
                byte_counter.ce.eq(1),
                If(
                    byte_counter.value == 3,
                    word_counter.ce.eq(1),
                    If(word_counter.value == (length - 1), NextState("IDLE")).Else(
                        NextState("READ_DATA"), byte_counter.reset.eq(1)
                    ),
                ),
            ),
        )

        self.comb += timer.wait.eq(~fsm.ongoing("IDLE"))

        if phy.sink.description.packetized:
            self.comb += [
                phy.sink.sop.eq((byte_counter.value == 0) & (word_counter.value == 0)),
                phy.sink.eop.eq((byte_counter.value == 3) & (word_counter.value == (length - 1))),
            ]
            if hasattr(phy.sink, "length"):
                self.comb += phy.sink.length.eq(4 * length)
Пример #10
0
	def __init__(self, dw_i, dw_o):
		self.wishbone_i = Interface(dw_i)
		self.wishbone_o = Interface(dw_o)
		self.ratio = dw_i//dw_o

		###
		
		rst = Signal()

		# generate internal write and read ack
		write_ack = Signal()
		read_ack = Signal()
		ack = Signal()
		self.comb += [
			ack.eq(self.wishbone_o.cyc & self.wishbone_o.stb & self.wishbone_o.ack),
			write_ack.eq(ack & self.wishbone_o.we),
			read_ack.eq(ack & ~self.wishbone_o.we)
		]
		
		# accesses counter logic
		cnt = Signal(max=self.ratio)
		self.sync += If(rst, cnt.eq(0)).Elif(ack, cnt.eq(cnt + 1))
		
		# read data path
		dat_r = Signal(dw_i)
		self.sync += If(ack, dat_r.eq(Cat(self.wishbone_o.dat_r, dat_r[:dw_i-dw_o])))
		
		# write data path
		dat_w = Signal(dw_i)
		self.comb += dat_w.eq(self.wishbone_i.dat_w)
		
		# errors generation
		err = Signal()
		self.sync += If(ack, err.eq(self.wishbone_o.err))
		
		# direct connection of wishbone_i --> wishbone_o signals
		for name, size, direction in self.wishbone_i.layout:
			if direction == DIR_M_TO_S and name not in ["adr", "dat_w"]:
				self.comb += getattr(self.wishbone_o, name).eq(getattr(self.wishbone_i, name))
		
		# adaptation of adr & dat signals
		self.comb += [
			self.wishbone_o.adr[0:flen(cnt)].eq(cnt),
			self.wishbone_o.adr[flen(cnt):].eq(self.wishbone_i.adr)
		]
		
		self.comb += chooser(dat_w, cnt, self.wishbone_o.dat_w, reverse=True)
		
		# fsm
		fsm = FSM(reset_state="IDLE")
		self.submodules += fsm
		
		fsm.act("IDLE",
			If(write_ack, NextState("WRITE_ADAPT")),
			If(read_ack, NextState("READ_ADAPT"))
		)
		
		fsm.act("WRITE_ADAPT",
			If(write_ack & (cnt == self.ratio-1),
				NextState("IDLE"),
				rst.eq(1),
				self.wishbone_i.err.eq(err | self.wishbone_o.err),
				self.wishbone_i.ack.eq(1),
			)
		)
		
		master_i_dat_r = Signal(dw_i)
		self.comb += master_i_dat_r.eq(Cat(self.wishbone_o.dat_r, dat_r[:dw_i-dw_o]))

		fsm.act("READ_ADAPT",
			If(read_ack & (cnt == self.ratio-1),
				NextState("IDLE"),
				rst.eq(1),
				self.wishbone_i.err.eq(err | self.wishbone_o.err),
				self.wishbone_i.ack.eq(1),
				self.wishbone_i.dat_r.eq(master_i_dat_r)
			)
		)
Пример #11
0
	def __init__(self, d_w):
		self.sink = Sink(eth_description(d_w))
		self.source = Source(eth_description(d_w))

		###

		preamble = Signal(64, reset=eth_preamble)
		cnt_max = (64//d_w) - 1
		cnt = Signal(max=cnt_max+1)
		clr_cnt = Signal()
		inc_cnt = Signal()

		self.sync += \
			If(clr_cnt,
				cnt.eq(0)
			).Elif(inc_cnt,
				cnt.eq(cnt+1)
			)

		discard = Signal()
		clr_discard = Signal()
		set_discard = Signal()

		self.sync += \
			If(clr_discard,
				discard.eq(0)
			).Elif(set_discard,
				discard.eq(1)
			)

		sop = Signal()
		clr_sop = Signal()
		set_sop = Signal()
		self.sync += \
			If(clr_sop,
				sop.eq(0)
			).Elif(set_sop,
				sop.eq(1)
			)

		ref = Signal(d_w)
		match = Signal()
		self.comb += [
			chooser(preamble, cnt, ref),
			match.eq(self.sink.d == ref)
		]

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

		fsm.act("IDLE",
			self.sink.ack.eq(1),
			clr_cnt.eq(1),
			clr_discard.eq(1),
			If(self.sink.stb & self.sink.sop,
				clr_cnt.eq(0),
				inc_cnt.eq(1),
				clr_discard.eq(0),
				set_discard.eq(~match),
				NextState("CHECK"),
			)
		)
		fsm.act("CHECK",
			self.sink.ack.eq(1),
			If(self.sink.stb,
				set_discard.eq(~match),
				If(cnt == cnt_max,
					If(discard | (~match),
						NextState("IDLE")
					).Else(
						set_sop.eq(1),
						NextState("COPY")
					)
				).Else(
					inc_cnt.eq(1)
				)
			)
		)
		fsm.act("COPY",
			Record.connect(self.sink, self.source),
			self.source.sop.eq(sop),
			clr_sop.eq(self.source.stb & self.source.ack),

			If(self.source.stb & self.source.eop & self.source.ack,
				NextState("IDLE"),
			)
		)
Пример #12
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()
Пример #13
0
    def __init__(self, pads, default=_default_edid):
        self._hpd_notif = CSRStatus()
        self._hpd_en = CSRStorage()
        self.specials.mem = Memory(8, 128, init=default)

        ###

        # HPD
        if hasattr(pads, "hpd_notif"):
            self.specials += MultiReg(pads.hpd_notif, self._hpd_notif.status)
        else:
            self.comb += self._hpd_notif.status.eq(1)
        if hasattr(pads, "hpd_en"):
            self.comb += pads.hpd_en.eq(self._hpd_en.storage)

        # EDID
        scl_raw = Signal()
        sda_i = Signal()
        sda_raw = Signal()
        sda_drv = Signal()
        _sda_drv_reg = Signal()
        _sda_i_async = Signal()
        self.sync += _sda_drv_reg.eq(sda_drv)
        self.specials += [
            MultiReg(pads.scl, scl_raw),
            Tristate(pads.sda, 0, _sda_drv_reg, _sda_i_async),
            MultiReg(_sda_i_async, sda_raw)
        ]

        # for debug
        self.scl = scl_raw
        self.sda_i = sda_i
        self.sda_o = Signal()
        self.comb += self.sda_o.eq(~_sda_drv_reg)
        self.sda_oe = _sda_drv_reg

        scl_i = Signal()
        samp_count = Signal(6)
        samp_carry = Signal()
        self.sync += [
            Cat(samp_count, samp_carry).eq(samp_count + 1),
            If(samp_carry,
                scl_i.eq(scl_raw),
                sda_i.eq(sda_raw)
            )
        ]

        scl_r = Signal()
        sda_r = Signal()
        scl_rising = Signal()
        sda_rising = Signal()
        sda_falling = Signal()
        self.sync += [
            scl_r.eq(scl_i),
            sda_r.eq(sda_i)
        ]
        self.comb += [
            scl_rising.eq(scl_i & ~scl_r),
            sda_rising.eq(sda_i & ~sda_r),
            sda_falling.eq(~sda_i & sda_r)
        ]

        start = Signal()
        self.comb += start.eq(scl_i & sda_falling)

        din = Signal(8)
        counter = Signal(max=9)
        self.sync += [
            If(start, counter.eq(0)),
            If(scl_rising,
                If(counter == 8,
                    counter.eq(0)
                ).Else(
                    counter.eq(counter + 1),
                    din.eq(Cat(sda_i, din[:7]))
                )
            )
        ]

        self.din = din
        self.counter = counter

        is_read = Signal()
        update_is_read = Signal()
        self.sync += If(update_is_read, is_read.eq(din[0]))

        offset_counter = Signal(max=128)
        oc_load = Signal()
        oc_inc = Signal()
        self.sync += [
            If(oc_load,
                offset_counter.eq(din)
            ).Elif(oc_inc,
                offset_counter.eq(offset_counter + 1)
            )
        ]
        rdport = self.mem.get_port()
        self.specials += rdport
        self.comb += rdport.adr.eq(offset_counter)
        data_bit = Signal()

        zero_drv = Signal()
        data_drv = Signal()
        self.comb += If(zero_drv, sda_drv.eq(1)).Elif(data_drv, sda_drv.eq(~data_bit))

        data_drv_en = Signal()
        data_drv_stop = Signal()
        self.sync += If(data_drv_en, data_drv.eq(1)).Elif(data_drv_stop, data_drv.eq(0))
        self.sync += If(data_drv_en, chooser(rdport.dat_r, counter, data_bit, 8, reverse=True))

        self.submodules.fsm = fsm = FSM()

        fsm.act("WAIT_START")
        fsm.act("RCV_ADDRESS",
            If(counter == 8,
                If(din[1:] == 0x50,
                    update_is_read.eq(1),
                    NextState("ACK_ADDRESS0")
                ).Else(
                    NextState("WAIT_START")
                )
            )
        )
        fsm.act("ACK_ADDRESS0",
            If(~scl_i, NextState("ACK_ADDRESS1"))
        )
        fsm.act("ACK_ADDRESS1",
            zero_drv.eq(1),
            If(scl_i, NextState("ACK_ADDRESS2"))
        )
        fsm.act("ACK_ADDRESS2",
            zero_drv.eq(1),
            If(~scl_i,
                If(is_read,
                    NextState("READ")
                ).Else(
                    NextState("RCV_OFFSET")
                )
            )
        )

        fsm.act("RCV_OFFSET",
            If(counter == 8,
                oc_load.eq(1),
                NextState("ACK_OFFSET0")
            )
        )
        fsm.act("ACK_OFFSET0",
            If(~scl_i, NextState("ACK_OFFSET1"))
        )
        fsm.act("ACK_OFFSET1",
            zero_drv.eq(1),
            If(scl_i, NextState("ACK_OFFSET2"))
        )
        fsm.act("ACK_OFFSET2",
            zero_drv.eq(1),
            If(~scl_i, NextState("RCV_ADDRESS"))
        )

        fsm.act("READ",
            If(~scl_i,
                If(counter == 8,
                    data_drv_stop.eq(1),
                    NextState("ACK_READ")
                ).Else(
                    data_drv_en.eq(1)
                )
            )
        )
        fsm.act("ACK_READ",
            If(scl_rising,
                oc_inc.eq(1),
                If(sda_i,
                    NextState("WAIT_START")
                ).Else(
                    NextState("READ")
                )
            )
        )

        for state in fsm.actions.keys():
            fsm.act(state, If(start, NextState("RCV_ADDRESS")))
            fsm.act(state, If(~self._hpd_en.storage, NextState("WAIT_START")))
Пример #14
0
    def __init__(self, pads, default=_default_edid):
        self._hpd_notif = CSRStatus()
        self._hpd_en = CSRStorage()
        mem_size = len(default)
        assert mem_size % 128 == 0
        self.specials.mem = Memory(8, mem_size, init=default)

        # # #

        # HPD
        if hasattr(pads, "hpd_notif"):
            if hasattr(getattr(pads, "hpd_notif"), "inverted"):
                hpd_notif_n = Signal()
                self.comb += hpd_notif_n.eq(~pads.hpd_notif)
                self.specials += MultiReg(hpd_notif_n, self._hpd_notif.status)
            else:
                self.specials += MultiReg(pads.hpd_notif,
                                          self._hpd_notif.status)
        else:
            self.comb += self._hpd_notif.status.eq(1)
        if hasattr(pads, "hpd_en"):
            self.comb += pads.hpd_en.eq(self._hpd_en.storage)

        # EDID
        scl_raw = Signal()
        sda_i = Signal()
        sda_raw = Signal()
        sda_drv = Signal()
        _sda_drv_reg = Signal()
        _sda_i_async = Signal()
        self.sync += _sda_drv_reg.eq(sda_drv)

        pad_scl = getattr(pads, "scl")
        if hasattr(pad_scl, "inverted"):
            self.specials += MultiReg(~pads.scl, scl_raw)
        else:
            self.specials += MultiReg(pads.scl, scl_raw)

        if hasattr(pads, "sda_pu") and hasattr(pads, "sda_pd"):
            pad_sda = getattr(pads, "sda")
            if hasattr(pad_sda, "inverted"):
                self.specials += MultiReg(~pads.sda, sda_raw)
            else:
                self.specials += MultiReg(pads.sda, sda_raw)

            self.comb += [
                pads.sda_pu.eq(0),
                pads.sda_pd.eq(_sda_drv_reg),
            ]
        else:
            self.specials += [
                Tristate(pads.sda, 0, _sda_drv_reg, _sda_i_async),
                MultiReg(_sda_i_async, sda_raw),
            ]

        # for debug
        self.scl = scl_raw
        self.sda_i = sda_i
        self.sda_o = Signal()
        self.comb += self.sda_o.eq(~_sda_drv_reg)
        self.sda_oe = _sda_drv_reg

        scl_i = Signal()
        samp_count = Signal(6)
        samp_carry = Signal()
        self.sync += [
            Cat(samp_count, samp_carry).eq(samp_count + 1),
            If(samp_carry, scl_i.eq(scl_raw), sda_i.eq(sda_raw))
        ]

        scl_r = Signal()
        sda_r = Signal()
        scl_rising = Signal()
        sda_rising = Signal()
        sda_falling = Signal()
        self.sync += [scl_r.eq(scl_i), sda_r.eq(sda_i)]
        self.comb += [
            scl_rising.eq(scl_i & ~scl_r),
            sda_rising.eq(sda_i & ~sda_r),
            sda_falling.eq(~sda_i & sda_r)
        ]

        start = Signal()
        self.comb += start.eq(scl_i & sda_falling)

        din = Signal(8)
        counter = Signal(max=9)
        self.sync += [
            If(start, counter.eq(0)),
            If(
                scl_rising,
                If(counter == 8,
                   counter.eq(0)).Else(counter.eq(counter + 1),
                                       din.eq(Cat(sda_i, din[:7]))))
        ]

        self.din = din
        self.counter = counter

        is_read = Signal()
        update_is_read = Signal()
        self.sync += If(update_is_read, is_read.eq(din[0]))

        offset_counter = Signal(max=mem_size)
        oc_load = Signal()
        oc_inc = Signal()
        self.sync += \
            If(oc_load,
                offset_counter.eq(din)
            ).Elif(oc_inc,
                offset_counter.eq(offset_counter + 1)
            )

        rdport = self.mem.get_port()
        self.specials += rdport
        self.comb += rdport.adr.eq(offset_counter)
        data_bit = Signal()

        zero_drv = Signal()
        data_drv = Signal()
        self.comb += \
            If(zero_drv,
                sda_drv.eq(1)
            ).Elif(data_drv,
                sda_drv.eq(~data_bit)
            )

        data_drv_en = Signal()
        data_drv_stop = Signal()
        self.sync += \
            If(data_drv_en,
                data_drv.eq(1)
            ).Elif(data_drv_stop,
                data_drv.eq(0)
            )
        self.sync += \
            If(data_drv_en,
                chooser(rdport.dat_r, counter, data_bit, 8, reverse=True)
            )

        self.submodules.fsm = fsm = FSM()

        fsm.act("WAIT_START")
        fsm.act(
            "RCV_ADDRESS",
            If(
                counter == 8,
                If(din[1:] == 0x50, update_is_read.eq(1),
                   NextState("ACK_ADDRESS0")).Else(NextState("WAIT_START"))))
        fsm.act("ACK_ADDRESS0", If(~scl_i, NextState("ACK_ADDRESS1")))
        fsm.act("ACK_ADDRESS1", zero_drv.eq(1),
                If(scl_i, NextState("ACK_ADDRESS2")))
        fsm.act(
            "ACK_ADDRESS2", zero_drv.eq(1),
            If(~scl_i,
               If(is_read, NextState("READ")).Else(NextState("RCV_OFFSET"))))

        fsm.act("RCV_OFFSET",
                If(counter == 8, oc_load.eq(1), NextState("ACK_OFFSET0")))
        fsm.act("ACK_OFFSET0", If(~scl_i, NextState("ACK_OFFSET1")))
        fsm.act("ACK_OFFSET1", zero_drv.eq(1),
                If(scl_i, NextState("ACK_OFFSET2")))
        fsm.act("ACK_OFFSET2", zero_drv.eq(1),
                If(~scl_i, NextState("RCV_ADDRESS")))

        fsm.act(
            "READ",
            If(
                ~scl_i,
                If(counter == 8, data_drv_stop.eq(1),
                   NextState("ACK_READ")).Else(data_drv_en.eq(1))))
        fsm.act(
            "ACK_READ",
            If(scl_rising, oc_inc.eq(1),
               If(sda_i, NextState("WAIT_START")).Else(NextState("READ"))))

        for state in fsm.actions.keys():
            fsm.act(state, If(start, NextState("RCV_ADDRESS")))
            if hasattr(pads, "hpd_en"):
                fsm.act(state,
                        If(~self._hpd_en.storage, NextState("WAIT_START")))
Пример #15
0
Файл: csr.py Проект: vic0/migen
	def __init__(self, mem_or_size, address, read_only=None, init=None, bus=None):
		if isinstance(mem_or_size, Memory):
			mem = mem_or_size
		else:
			mem = Memory(data_width, mem_or_size//(data_width//8), init=init)
		csrw_per_memw = (mem.width + data_width - 1)//data_width
		word_bits = log2_int(csrw_per_memw)
		page_bits = log2_int((mem.depth*csrw_per_memw + 511)//512, False)
		if page_bits:
			self._page = CSRStorage(page_bits, name=mem.name_override + "_page")
		else:
			self._page = None
		if read_only is None:
			if hasattr(mem, "bus_read_only"):
				read_only = mem.bus_read_only
			else:
				read_only = False
		if bus is None:
			bus = Interface()
		self.bus = bus
	
		###

		port = mem.get_port(write_capable=not read_only)
		self.specials += mem, port
		
		sel = Signal()
		sel_r = Signal()
		self.sync += sel_r.eq(sel)
		self.comb += sel.eq(self.bus.adr[9:] == address)

		if word_bits:
			word_index = Signal(word_bits)
			word_expanded = Signal(csrw_per_memw*data_width)
			self.sync += word_index.eq(self.bus.adr[:word_bits])
			self.comb += [
				word_expanded.eq(port.dat_r),
				If(sel_r,
					chooser(word_expanded, word_index, self.bus.dat_r, n=csrw_per_memw, reverse=True)
				)
			]
			if not read_only:
				wregs = []
				for i in range(csrw_per_memw-1):
					wreg = Signal(data_width)
					self.sync += If(sel & self.bus.we & (self.bus.adr[:word_bits] == i), wreg.eq(self.bus.dat_w))
					wregs.append(wreg)
				memword_chunks = [self.bus.dat_w] + list(reversed(wregs))
				self.comb += [
					port.we.eq(sel & self.bus.we & (self.bus.adr[:word_bits] == csrw_per_memw - 1)),
					port.dat_w.eq(Cat(*memword_chunks))
				]
		else:
			self.comb += If(sel_r, self.bus.dat_r.eq(port.dat_r))
			if not read_only:
				self.comb += [
					port.we.eq(sel & self.bus.we),
					port.dat_w.eq(self.bus.dat_w)
				]
		
		if self._page is None:
			self.comb += port.adr.eq(self.bus.adr[word_bits:word_bits+flen(port.adr)])
		else:
			pv = self._page.storage
			self.comb += port.adr.eq(Cat(self.bus.adr[word_bits:word_bits+flen(port.adr)-flen(pv)], pv))
Пример #16
0
	def __init__(self, mem_or_size, address, read_only=None, bus=None):
		if isinstance(mem_or_size, Memory):
			mem = mem_or_size
		else:
			mem = Memory(data_width, mem_or_size//(data_width//8))
		if mem.width > data_width:
			csrw_per_memw = (mem.width + data_width - 1)//data_width
			word_bits = bits_for(csrw_per_memw-1)
		else:
			csrw_per_memw = 1
			word_bits = 0
		page_bits = _compute_page_bits(mem.depth + word_bits)
		if page_bits:
			self._page = CSRStorage(page_bits, name=mem.name_override + "_page")
		else:
			self._page = None
		if read_only is None:
			if hasattr(mem, "bus_read_only"):
				read_only = mem.bus_read_only
			else:
				read_only = False
		if bus is None:
			bus = Interface()
		self.bus = bus
	
		###

		self.specials += mem
		port = mem.get_port(write_capable=not read_only,
			we_granularity=data_width if not read_only and word_bits else 0)
		
		sel = Signal()
		sel_r = Signal()
		self.sync += sel_r.eq(sel)
		self.comb += sel.eq(self.bus.adr[9:] == address)

		if word_bits:
			word_index = Signal(word_bits)
			word_expanded = Signal(csrw_per_memw*data_width)
			self.sync += word_index.eq(self.bus.adr[:word_bits])
			self.comb += [
				word_expanded.eq(port.dat_r),
				If(sel_r,
					chooser(word_expanded, word_index, self.bus.dat_r, n=csrw_per_memw, reverse=True)
				)
			]
			if not read_only:
				self.comb += [
					If(sel & self.bus.we, port.we.eq((1 << word_bits) >> self.bus.adr[:self.word_bits])),
					port.dat_w.eq(Replicate(self.bus.dat_w, csrw_per_memw))
				]
		else:
			self.comb += If(sel_r, self.bus.dat_r.eq(port.dat_r))
			if not read_only:
				self.comb += [
					port.we.eq(sel & self.bus.we),
					port.dat_w.eq(self.bus.dat_w)
				]
		
		if self._page is None:
			self.comb += port.adr.eq(self.bus.adr[word_bits:len(port.adr)])
		else:
			pv = self._page.storage
			self.comb += port.adr.eq(Cat(self.bus.adr[word_bits:len(port.adr)-len(pv)], pv))
Пример #17
0
    def __init__(self):
        self.sink = sink = Sink(EndpointDescription([("data", 128)], packetized=True))
        self.source = source = Source(EndpointDescription([("data", 16)], packetized=True))

        # # #

        # mem
        mem = Memory(128, 16)
        write_port = mem.get_port(write_capable=True)
        read_port = mem.get_port(async_read=True)
        self.specials += mem, write_port, read_port

        write_sel = Signal()
        write_swap = Signal()
        read_sel = Signal(reset=1)
        read_swap = Signal()
        self.sync += [
            If(write_swap,
                write_sel.eq(~write_sel)
            ),
            If(read_swap,
                read_sel.eq(~read_sel)
            )
        ]


        # write path
        v_write_clr = Signal()
        v_write_inc = Signal()
        v_write = Signal(3)
        self.sync += \
            If(v_write_clr,
                v_write.eq(0)
            ).Elif(v_write_inc,
                v_write.eq(v_write + 1)
            )

        self.comb += [
            write_port.adr.eq(v_write),
            write_port.adr[-1].eq(write_sel),
            write_port.dat_w.eq(sink.data),
            write_port.we.eq(sink.stb & sink.ack)
        ]

        self.submodules.write_fsm = write_fsm = FSM(reset_state="IDLE")
        write_fsm.act("IDLE",
            v_write_clr.eq(1),
            If(write_sel != read_sel,
                NextState("WRITE")
            )
        )
        write_fsm.act("WRITE",
            sink.ack.eq(1),
            If(sink.stb,
                If(v_write == 7,
                    write_swap.eq(1),
                    NextState("IDLE")
                ).Else(
                    v_write_inc.eq(1)
                )
            )
        )

        # read path
        h_read_clr = Signal()
        h_read_inc = Signal()
        h_read = Signal(3)
        self.sync += \
            If(h_read_clr,
                h_read.eq(0)
            ).Elif(h_read_inc,
                h_read.eq(h_read + 1)
            )

        v_read_clr = Signal()
        v_read_inc = Signal()
        v_read = Signal(3)
        self.sync += \
            If(v_read_clr,
                v_read.eq(0)
            ).Elif(v_read_inc,
                v_read.eq(v_read + 1)
            )

        self.comb += [
            read_port.adr.eq(v_read),
            read_port.adr[-1].eq(read_sel),
            chooser(read_port.dat_r, h_read, source.data, reverse=True)
        ]

        self.submodules.read_fsm = read_fsm = FSM(reset_state="IDLE")
        read_fsm.act("IDLE",
            h_read_clr.eq(1),
            v_read_clr.eq(1),
            If(read_sel == write_sel,
                read_swap.eq(1),
                NextState("READ")
            )
        )
        read_fsm.act("READ",
            source.stb.eq(1),
            source.sop.eq((h_read == 0) & (v_read == 0)),
            source.eop.eq((h_read == 7) & (v_read == 7)),
            If(source.ack,
                If(h_read == 7,
                    h_read_clr.eq(1),
                    If(v_read == 7,
                        NextState("IDLE")
                    ).Else(
                        v_read_inc.eq(1)
                    )
                ).Else(
                    h_read_inc.eq(1)
                )
            )
        )
Пример #18
0
    def __init__(self, dw):
        self.sink = stream.Endpoint(eth_phy_description(dw))
        self.source = stream.Endpoint(eth_phy_description(dw))

        # # #

        preamble = Signal(64, reset=eth_preamble)
        cnt_max = (64//dw) - 1
        cnt = Signal(max=cnt_max+1)
        clr_cnt = Signal()
        inc_cnt = Signal()

        self.sync += \
            If(clr_cnt,
                cnt.eq(0)
            ).Elif(inc_cnt,
                cnt.eq(cnt+1)
            )

        discard = Signal()
        clr_discard = Signal()
        set_discard = Signal()

        self.sync += \
            If(clr_discard,
                discard.eq(0)
            ).Elif(set_discard,
                discard.eq(1)
            )

        ref = Signal(dw)
        match = Signal()
        self.comb += [
            chooser(preamble, cnt, ref),
            match.eq(self.sink.data == ref)
        ]

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

        fsm.act("IDLE",
            self.sink.ack.eq(1),
            clr_cnt.eq(1),
            clr_discard.eq(1),
            If(self.sink.stb,
                clr_cnt.eq(0),
                inc_cnt.eq(1),
                clr_discard.eq(0),
                set_discard.eq(~match),
                NextState("CHECK"),
            )
        )
        fsm.act("CHECK",
            self.sink.ack.eq(1),
            If(self.sink.stb,
                set_discard.eq(~match),
                If(cnt == cnt_max,
                    If(discard | (~match),
                        NextState("IDLE")
                    ).Else(
                        NextState("COPY")
                    )
                ).Else(
                    inc_cnt.eq(1)
                )
            )
        )
        self.comb += [
            self.source.data.eq(self.sink.data),
            self.source.last_be.eq(self.sink.last_be)
        ]
        fsm.act("COPY",
            self.sink.connect(self.source, leave_out=set(["data", "last_be"])),
            If(self.source.stb & self.source.eop & self.source.ack,
                NextState("IDLE"),
            )
        )
Пример #19
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")
			)
		)
Пример #20
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)
		)
Пример #21
0
    def __init__(self, cachesize, master, slave):
        self._size = CSRStatus(8, reset=log2_int(cachesize))
        self.master = master
        self.slave = slave

        ###

        dw_from = flen(master.dat_r)
        dw_to = flen(slave.dat_r)
        if dw_to > dw_from and (dw_to % dw_from) != 0:
            raise ValueError("Slave data width must be a multiple of {dw}".format(dw=dw_from))
        if dw_to < dw_from and (dw_from % dw_to) != 0:
            raise ValueError("Master data width must be a multiple of {dw}".format(dw=dw_to))

        # Split address:
        # TAG | LINE NUMBER | LINE OFFSET
        offsetbits = log2_int(max(dw_to//dw_from, 1))
        addressbits = flen(slave.adr) + offsetbits
        linebits = log2_int(cachesize) - offsetbits
        tagbits = addressbits - linebits
        wordbits = log2_int(max(dw_from//dw_to, 1))
        adr_offset, adr_line, adr_tag = split(master.adr, offsetbits, linebits, tagbits)
        word = Signal(wordbits) if wordbits else None

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

        write_from_slave = 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_slave,
                displacer(slave.dat_r, word, data_port.dat_w),
                displacer(Replicate(1, dw_to//8), word, data_port.we)
            ).Else(
                data_port.dat_w.eq(Replicate(master.dat_w, max(dw_to//dw_from, 1))),
                If(master.cyc & master.stb & master.we & master.ack,
                    displacer(master.sel, adr_offset, data_port.we, 2**offsetbits, reverse=True)
                )
            ),
            chooser(data_port.dat_r, word, slave.dat_w),
            slave.sel.eq(2**(dw_to//8)-1),
            chooser(data_port.dat_r, adr_offset_r, master.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 += slave.adr.eq(Cat(word, adr_line, tag_do.tag))
        else:
            self.comb += slave.adr.eq(Cat(adr_line, tag_do.tag))

        # slave 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
        self.submodules.fsm = fsm = FSM(reset_state="IDLE")
        fsm.act("IDLE",
            If(master.cyc & master.stb,
                NextState("TEST_HIT")
            )
        )
        fsm.act("TEST_HIT",
            word_clr.eq(1),
            If(tag_do.tag == adr_tag,
                master.ack.eq(1),
                If(master.we,
                    tag_di.dirty.eq(1),
                    tag_port.we.eq(1)
                ),
                NextState("IDLE")
            ).Else(
                If(tag_do.dirty,
                    NextState("EVICT")
                ).Else(
                    NextState("REFILL_WRTAG")
                )
            )
        )

        fsm.act("EVICT",
            slave.stb.eq(1),
            slave.cyc.eq(1),
            slave.we.eq(1),
            If(slave.ack,
                word_inc.eq(1),
                 If(word_is_last(word),
                    NextState("REFILL_WRTAG")
                )
            )
        )
        fsm.act("REFILL_WRTAG",
            # Write the tag first to set the slave address
            tag_port.we.eq(1),
            word_clr.eq(1),
            NextState("REFILL")
        )
        fsm.act("REFILL",
            slave.stb.eq(1),
            slave.cyc.eq(1),
            slave.we.eq(0),
            If(slave.ack,
                write_from_slave.eq(1),
                word_inc.eq(1),
                If(word_is_last(word),
                    NextState("TEST_HIT"),
                ).Else(
                    NextState("REFILL")
                )
            )
        )
Пример #22
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")
		)