示例#1
0
文件: crc.py 项目: mithro/liteusb
    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
    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, reset_less=True)
        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.ready.eq(1),
            clr_cnt.eq(1),
            If(self.sink.valid,
                self.sink.ready.eq(0),
                NextState("INSERT"),
            )
        )
        fsm.act("INSERT",
            self.source.valid.eq(1),
            chooser(preamble, cnt, self.source.data),
            If(cnt == cnt_max,
                If(self.source.ready, NextState("COPY"))
            ).Else(
                inc_cnt.eq(self.source.ready)
            )
        )

        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.valid & self.sink.last & self.source.ready,
                NextState("IDLE"),
            )
        )
示例#3
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)
            )

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

        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.sink.valid & self.sink.last & self.source.ready,
                NextState("IDLE"),
            )
        )
示例#4
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"))
示例#5
0
    def __init__(self, cachesize, master, slave):
        self.master = master
        self.slave = slave

        ###

        dw_from = len(master.dat_r)
        dw_to = len(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 = len(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")
                )
            )
        )
示例#6
0
    def __init__(self):
        self.sink = sink = stream.Endpoint([("data", 128)])
        self.source = source = stream.Endpoint([("data", 16)])

        # # #

        # 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.valid & sink.ready)
        ]

        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.ready.eq(1),
            If(sink.valid,
                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.valid.eq(1),
            source.last.eq((h_read == 7) & (v_read == 7)),
            If(source.ready,
                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)
                )
            )
        )
示例#7
0
文件: edid.py 项目: mithro/litevideo
    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")))
示例#8
0
    def __init__(self, phy, clk_freq):
        self.wishbone = wishbone.Interface()

        # # #

        byte_counter = Signal(3)
        byte_counter_reset = Signal()
        byte_counter_ce = Signal()
        self.sync += If(byte_counter_reset, byte_counter.eq(0)).Elif(byte_counter_ce, byte_counter.eq(byte_counter + 1))

        word_counter = Signal(3)
        word_counter_reset = Signal()
        word_counter_ce = Signal()
        self.sync += If(word_counter_reset, word_counter.eq(0)).Elif(word_counter_ce, word_counter.eq(word_counter + 1))

        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 = ResetInserter()(FSM(reset_state="IDLE"))
        timer = WaitTimer(clk_freq // 10)
        self.submodules += fsm, timer
        self.comb += [fsm.reset.eq(timer.done), phy.source.ready.eq(1)]
        fsm.act(
            "IDLE",
            If(
                phy.source.valid,
                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.valid, length_ce.eq(1), NextState("RECEIVE_ADDRESS")))
        fsm.act(
            "RECEIVE_ADDRESS",
            If(
                phy.source.valid,
                address_ce.eq(1),
                byte_counter_ce.eq(1),
                If(
                    byte_counter == 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.valid,
                rx_data_ce.eq(1),
                byte_counter_ce.eq(1),
                If(byte_counter == 3, NextState("WRITE_DATA"), byte_counter_reset.eq(1)),
            ),
        )
        self.comb += [
            self.wishbone.adr.eq(address + word_counter),
            self.wishbone.dat_w.eq(data),
            self.wishbone.sel.eq(2 ** len(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 == (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, phy.sink.data, n=4, reverse=True)
        fsm.act(
            "SEND_DATA",
            phy.sink.valid.eq(1),
            If(
                phy.sink.ready,
                byte_counter_ce.eq(1),
                If(
                    byte_counter == 3,
                    word_counter_ce.eq(1),
                    If(word_counter == (length - 1), NextState("IDLE")).Else(
                        NextState("READ_DATA"), byte_counter_reset.eq(1)
                    ),
                ),
            ),
        )

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

        self.comb += phy.sink.last.eq((byte_counter == 3) & (word_counter == length - 1))

        if hasattr(phy.sink, "length"):
            self.comb += phy.sink.length.eq(4 * length)
示例#9
0
    def __init__(self, cachesize, master, slave):
        self.master = master
        self.slave = slave

        ###

        dw_from = len(master.dat_r)
        dw_to = len(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 = len(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"))))
示例#10
0
    def __init__(self,
                 mem_or_size,
                 address,
                 read_only=None,
                 init=None,
                 bus=None):
        if bus is None:
            bus = Interface()
        self.bus = bus
        data_width = len(self.bus.dat_w)
        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

        ###

        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 +
                                                  len(port.adr)])
        else:
            pv = self._page.storage
            self.comb += port.adr.eq(
                Cat(
                    self.bus.adr[word_bits:word_bits + len(port.adr) -
                                 len(pv)], pv))
示例#11
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.ready.eq(1),
            clr_cnt.eq(1),
            clr_discard.eq(1),
            If(self.sink.valid,
                clr_cnt.eq(0),
                inc_cnt.eq(1),
                clr_discard.eq(0),
                set_discard.eq(~match),
                NextState("CHECK"),
            )
        )
        fsm.act("CHECK",
            self.sink.ready.eq(1),
            If(self.sink.valid,
                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.valid & self.source.last & self.source.ready,
                NextState("IDLE"),
            )
        )
示例#12
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"):
            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)
        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")))
示例#13
0
    def __init__(self, mem_or_size, address, read_only=None, init=None, bus=None):
        if bus is None:
            bus = Interface()
        self.bus = bus
        data_width = len(self.bus.dat_w)
        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

        ###

        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+len(port.adr)])
        else:
            pv = self._page.storage
            self.comb += port.adr.eq(Cat(self.bus.adr[word_bits:word_bits+len(port.adr)-len(pv)], pv))
示例#14
0
    def __init__(self, phy, clk_freq):
        self.wishbone = wishbone.Interface()

        # # #

        byte_counter = Signal(3)
        byte_counter_reset = Signal()
        byte_counter_ce = Signal()
        self.sync += \
            If(byte_counter_reset,
                byte_counter.eq(0)
            ).Elif(byte_counter_ce,
                byte_counter.eq(byte_counter + 1)
            )

        word_counter = Signal(3)
        word_counter_reset = Signal()
        word_counter_ce = Signal()
        self.sync += \
            If(word_counter_reset,
                word_counter.eq(0)
            ).Elif(word_counter_ce,
                word_counter.eq(word_counter + 1)
            )

        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 = ResetInserter()(FSM(reset_state="IDLE"))
        timer = WaitTimer(clk_freq // 10)
        self.submodules += fsm, timer
        self.comb += [fsm.reset.eq(timer.done), phy.source.ready.eq(1)]
        fsm.act(
            "IDLE",
            If(
                phy.source.valid, 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.valid, length_ce.eq(1),
               NextState("RECEIVE_ADDRESS")))
        fsm.act(
            "RECEIVE_ADDRESS",
            If(
                phy.source.valid, address_ce.eq(1), byte_counter_ce.eq(1),
                If(
                    byte_counter == 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.valid, rx_data_ce.eq(1), byte_counter_ce.eq(1),
                If(byte_counter == 3, NextState("WRITE_DATA"),
                   byte_counter_reset.eq(1))))
        self.comb += [
            self.wishbone.adr.eq(address + word_counter),
            self.wishbone.dat_w.eq(data),
            self.wishbone.sel.eq(2**len(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 == (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, phy.sink.data, n=4, reverse=True)
        fsm.act(
            "SEND_DATA", phy.sink.valid.eq(1),
            If(
                phy.sink.ready, byte_counter_ce.eq(1),
                If(
                    byte_counter == 3, word_counter_ce.eq(1),
                    If(word_counter == (length - 1),
                       NextState("IDLE")).Else(NextState("READ_DATA"),
                                               byte_counter_reset.eq(1)))))

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

        self.comb += phy.sink.last.eq((byte_counter == 3)
                                      & (word_counter == length - 1))

        if hasattr(phy.sink, "length"):
            self.comb += phy.sink.length.eq(4 * length)
示例#15
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.ready.eq(1),
            clr_cnt.eq(1),
            clr_discard.eq(1),
            If(self.sink.valid,
                clr_cnt.eq(0),
                inc_cnt.eq(1),
                clr_discard.eq(0),
                set_discard.eq(~match),
                NextState("CHECK"),
            )
        )
        fsm.act("CHECK",
            self.sink.ready.eq(1),
            If(self.sink.valid,
                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, omit=set(["data", "last_be"])),
            If(self.source.valid & self.source.last & self.source.ready,
                NextState("IDLE"),
            )
        )
    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)

        ###

        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.comb += [
            pads.scl.w.eq(0),
            pads.scl.oe.eq(_scl_drv_reg),
            _scl_i_async.eq(pads.scl.r),
            pads.sda.w.eq(0),
            pads.sda.oe.eq(_sda_drv_reg),
            _sda_i_async.eq(pads.sda.r),
        ]
        self.specials += [
            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")))