Exemplo n.º 1
0
    def __init__(self, wishbone, lasmim):

        ###

        # Control FSM
        self.submodules.fsm = fsm = FSM(reset_state="IDLE")
        fsm.act("IDLE", If(wishbone.cyc & wishbone.stb, NextState("REQUEST")))
        fsm.act(
            "REQUEST", lasmim.stb.eq(1), lasmim.we.eq(wishbone.we),
            If(
                lasmim.req_ack,
                If(wishbone.we,
                   NextState("WRITE_DATA")).Else(NextState("READ_DATA"))))
        fsm.act(
            "WRITE_DATA",
            If(lasmim.dat_w_ack, lasmim.dat_we.eq(wishbone.sel),
               wishbone.ack.eq(1), NextState("IDLE")))
        fsm.act("READ_DATA",
                If(lasmim.dat_r_ack, wishbone.ack.eq(1), NextState("IDLE")))

        # Address / Datapath
        self.comb += [
            lasmim.adr.eq(wishbone.adr),
            If(
                lasmim.dat_w_ack,
                lasmim.dat_w.eq(wishbone.dat_w),
            ),
            wishbone.dat_r.eq(lasmim.dat_r)
        ]
Exemplo n.º 2
0
    def __init__(self, sink_description, source_description, header):
        self.sink = sink = stream.Endpoint(sink_description)
        self.source = source = stream.Endpoint(source_description)
        self.header = Signal(header.length * 8)

        # # #

        dw = len(self.sink.data)

        header_reg = Signal(header.length * 8)
        header_words = (header.length * 8) // dw
        load = Signal()
        shift = Signal()
        counter = Signal(max=max(header_words, 2))
        counter_reset = Signal()
        counter_ce = Signal()
        self.sync += \
            If(counter_reset,
                counter.eq(0)
            ).Elif(counter_ce,
                counter.eq(counter + 1)
            )

        self.comb += header.encode(sink, self.header)
        if header_words == 1:
            self.sync += [If(load, header_reg.eq(self.header))]
        else:
            self.sync += [
                If(load, header_reg.eq(self.header)).Elif(
                    shift, header_reg.eq(Cat(header_reg[dw:], Signal(dw))))
            ]

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

        if header_words == 1:
            idle_next_state = "COPY"
        else:
            idle_next_state = "SEND_HEADER"

        fsm.act(
            "IDLE", sink.ready.eq(1), counter_reset.eq(1),
            If(
                sink.valid, sink.ready.eq(0), source.valid.eq(1),
                source.last.eq(0), source.data.eq(self.header[:dw]),
                If(source.valid & source.ready, load.eq(1),
                   NextState(idle_next_state))))
        if header_words != 1:
            fsm.act(
                "SEND_HEADER", source.valid.eq(1), source.last.eq(0),
                source.data.eq(header_reg[dw:2 * dw]),
                If(source.valid & source.ready, shift.eq(1), counter_ce.eq(1),
                   If(counter == header_words - 2, NextState("COPY"))))
        if hasattr(sink, "error"):
            self.comb += source.error.eq(sink.error)
        fsm.act(
            "COPY", source.valid.eq(sink.valid), source.last.eq(sink.last),
            source.data.eq(sink.data),
            If(source.valid & source.ready, sink.ready.eq(1),
               If(source.last, NextState("IDLE"))))
Exemplo n.º 3
0
    def __init__(self, clock_pads, pads, with_hw_init_reset):
        self._reset = CSRStorage()

        # # #

        self.clock_domains.cd_eth_rx = ClockDomain()
        self.clock_domains.cd_eth_tx = ClockDomain()

        # RX
        dcm_reset = Signal()
        dcm_locked = Signal()

        timer = WaitTimer(1024)
        fsm = FSM(reset_state="DCM_RESET")
        self.submodules += timer, fsm

        fsm.act("DCM_RESET", dcm_reset.eq(1), timer.wait.eq(1),
                If(timer.done, timer.wait.eq(0), NextState("DCM_WAIT")))
        fsm.act("DCM_WAIT", timer.wait.eq(1),
                If(timer.done, NextState("DCM_CHECK_LOCK")))
        fsm.act("DCM_CHECK_LOCK", If(~dcm_locked, NextState("DCM_RESET")))

        clk90_rx = Signal()
        clk0_rx = Signal()
        clk0_rx_bufg = Signal()
        self.specials += Instance("DCM",
                                  i_CLKIN=clock_pads.rx,
                                  i_CLKFB=clk0_rx_bufg,
                                  o_CLK0=clk0_rx,
                                  o_CLK90=clk90_rx,
                                  o_LOCKED=dcm_locked,
                                  i_PSEN=0,
                                  i_PSCLK=0,
                                  i_PSINCDEC=0,
                                  i_RST=dcm_reset)

        self.specials += Instance("BUFG", i_I=clk0_rx, o_O=clk0_rx_bufg)
        self.specials += Instance("BUFG", i_I=clk90_rx, o_O=self.cd_eth_rx.clk)

        # TX
        self.specials += DDROutput(1, 0, clock_pads.tx, ClockSignal("eth_tx"))
        self.specials += Instance("BUFG",
                                  i_I=self.cd_eth_rx.clk,
                                  o_O=self.cd_eth_tx.clk)

        # Reset
        reset = Signal()
        if with_hw_init_reset:
            self.submodules.hw_reset = LiteEthPHYHWReset()
            self.comb += reset.eq(self._reset.storage | self.hw_reset.reset)
        else:
            self.comb += reset.eq(self._reset.storage)

        self.comb += pads.rst_n.eq(~reset)
        self.specials += [
            AsyncResetSynchronizer(self.cd_eth_tx, reset),
            AsyncResetSynchronizer(self.cd_eth_rx, reset),
        ]
Exemplo n.º 4
0
    def __init__(self, a, ba, tRP, tREFI, tRFC):
        self.req = Signal()
        self.ack = Signal()  # 1st command 1 cycle after assertion of ack
        self.cmd = CommandRequest(a, ba)

        ###

        # Refresh sequence generator:
        # PRECHARGE ALL --(tRP)--> AUTO REFRESH --(tRFC)--> done
        seq_start = Signal()
        seq_done = Signal()
        self.sync += [
            self.cmd.a.eq(2**10),
            self.cmd.ba.eq(0),
            self.cmd.cas_n.eq(1),
            self.cmd.ras_n.eq(1),
            self.cmd.we_n.eq(1),
            seq_done.eq(0)
        ]
        self.sync += timeline(
            seq_start, [(1, [self.cmd.ras_n.eq(0),
                             self.cmd.we_n.eq(0)]),
                        (1 + tRP, [self.cmd.cas_n.eq(0),
                                   self.cmd.ras_n.eq(0)]),
                        (1 + tRP + tRFC, [seq_done.eq(1)])])

        # Periodic refresh counter
        counter = Signal(max=tREFI)
        start = Signal()
        self.sync += [
            start.eq(0),
            If(counter == 0, start.eq(1),
               counter.eq(tREFI - 1)).Else(counter.eq(counter - 1))
        ]

        # Control FSM
        fsm = FSM()
        self.submodules += fsm
        fsm.act("IDLE", If(start, NextState("WAIT_GRANT")))
        fsm.act("WAIT_GRANT", self.req.eq(1),
                If(self.ack, seq_start.eq(1), NextState("WAIT_SEQ")))
        fsm.act("WAIT_SEQ", self.req.eq(1), If(seq_done, NextState("IDLE")))
Exemplo n.º 5
0
    def __init__(self, phy_settings, geom_settings, timing_settings):
        if phy_settings.memtype in ["SDR"]:
            burst_length = phy_settings.nphases * 1  # command multiplication*SDR
        elif phy_settings.memtype in ["DDR", "LPDDR", "DDR2", "DDR3"]:
            burst_length = phy_settings.nphases * 2  # command multiplication*DDR
        burst_width = phy_settings.dfi_databits * phy_settings.nphases
        address_align = log2_int(burst_length)

        # # #

        self.dfi = dfi = dfibus.Interface(geom_settings.addressbits,
                                          geom_settings.bankbits,
                                          phy_settings.dfi_databits,
                                          phy_settings.nphases)

        self.bus = bus = wishbone.Interface(burst_width)

        rdphase = phy_settings.rdphase
        wrphase = phy_settings.wrphase

        precharge_all = Signal()
        activate = Signal()
        refresh = Signal()
        write = Signal()
        read = Signal()

        # Compute current column, bank and row from wishbone address
        slicer = _AddressSlicer(geom_settings.colbits, geom_settings.bankbits,
                                geom_settings.rowbits, address_align)

        # Manage banks
        bank_idle = Signal()
        bank_hit = Signal()

        banks = []
        for i in range(2**geom_settings.bankbits):
            bank = _Bank(geom_settings)
            self.comb += [
                bank.open.eq(activate),
                bank.reset.eq(precharge_all),
                bank.row.eq(slicer.row(bus.adr))
            ]
            banks.append(bank)
        self.submodules += banks

        cases = {}
        for i, bank in enumerate(banks):
            cases[i] = [bank.ce.eq(1)]
        self.comb += Case(slicer.bank(bus.adr), cases)

        self.comb += [
            bank_hit.eq(reduce(or_, [bank.hit & bank.ce for bank in banks])),
            bank_idle.eq(reduce(or_, [bank.idle & bank.ce for bank in banks])),
        ]

        # Timings
        write2precharge_timer = WaitTimer(2 + timing_settings.tWR - 1)
        self.submodules += write2precharge_timer
        self.comb += write2precharge_timer.wait.eq(~write)

        refresh_timer = WaitTimer(timing_settings.tREFI)
        self.submodules += refresh_timer
        self.comb += refresh_timer.wait.eq(~refresh)

        # Main FSM
        self.submodules.fsm = fsm = FSM()
        fsm.act(
            "IDLE",
            If(refresh_timer.done, NextState("PRECHARGE-ALL")).Elif(
                bus.stb & bus.cyc,
                If(bank_hit,
                   If(bus.we,
                      NextState("WRITE")).Else(NextState("READ"))).Elif(
                          ~bank_idle,
                          If(write2precharge_timer.done,
                             NextState("PRECHARGE"))).Else(
                                 NextState("ACTIVATE"))))
        fsm.act(
            "READ",
            read.eq(1),
            dfi.phases[rdphase].ras_n.eq(1),
            dfi.phases[rdphase].cas_n.eq(0),
            dfi.phases[rdphase].we_n.eq(1),
            dfi.phases[rdphase].rddata_en.eq(1),
            NextState("WAIT-READ-DONE"),
        )
        fsm.act(
            "WAIT-READ-DONE",
            If(dfi.phases[rdphase].rddata_valid, bus.ack.eq(1),
               NextState("IDLE")))
        fsm.act("WRITE", write.eq(1), dfi.phases[wrphase].ras_n.eq(1),
                dfi.phases[wrphase].cas_n.eq(0),
                dfi.phases[wrphase].we_n.eq(0),
                dfi.phases[wrphase].wrdata_en.eq(1),
                NextState("WRITE-LATENCY"))
        fsm.act("WRITE-ACK", bus.ack.eq(1), NextState("IDLE"))
        fsm.act("PRECHARGE-ALL", precharge_all.eq(1),
                dfi.phases[rdphase].ras_n.eq(0),
                dfi.phases[rdphase].cas_n.eq(1),
                dfi.phases[rdphase].we_n.eq(0), NextState("PRE-REFRESH"))
        fsm.act(
            "PRECHARGE",
            # do no reset bank since we are going to re-open it
            dfi.phases[0].ras_n.eq(0),
            dfi.phases[0].cas_n.eq(1),
            dfi.phases[0].we_n.eq(0),
            NextState("TRP"))
        fsm.act(
            "ACTIVATE",
            activate.eq(1),
            dfi.phases[0].ras_n.eq(0),
            dfi.phases[0].cas_n.eq(1),
            dfi.phases[0].we_n.eq(1),
            NextState("TRCD"),
        )
        fsm.act("REFRESH", refresh.eq(1), dfi.phases[rdphase].ras_n.eq(0),
                dfi.phases[rdphase].cas_n.eq(0),
                dfi.phases[rdphase].we_n.eq(1), NextState("POST-REFRESH"))
        fsm.delayed_enter("WRITE-LATENCY", "WRITE-ACK",
                          phy_settings.write_latency - 1)
        fsm.delayed_enter("TRP", "ACTIVATE", timing_settings.tRP - 1)
        fsm.delayed_enter("TRCD", "IDLE", timing_settings.tRCD - 1)
        fsm.delayed_enter("PRE-REFRESH", "REFRESH", timing_settings.tRP - 1)
        fsm.delayed_enter("POST-REFRESH", "IDLE", timing_settings.tRFC - 1)

        # DFI commands
        for phase in dfi.phases:
            if hasattr(phase, "reset_n"):
                self.comb += phase.reset_n.eq(1)
            if hasattr(phase, "odt"):
                self.comb += phase.odt.eq(1)
            self.comb += [
                phase.cke.eq(1),
                phase.cs_n.eq(0),
                phase.bank.eq(slicer.bank(bus.adr)),
                If(precharge_all, phase.address.eq(2**10)).Elif(
                    activate, phase.address.eq(slicer.row(bus.adr))).Elif(
                        write | read, phase.address.eq(slicer.col(bus.adr)))
            ]

        # DFI datapath
        self.comb += [
            bus.dat_r.eq(Cat(phase.rddata for phase in dfi.phases)),
            Cat(phase.wrdata for phase in dfi.phases).eq(bus.dat_w),
            Cat(phase.wrdata_mask for phase in dfi.phases).eq(~bus.sel),
        ]
Exemplo n.º 6
0
    def __init__(self, geom_settings, timing_settings, controller_settings,
                 address_align, bankn, req):
        self.refresh_req = Signal()
        self.refresh_gnt = Signal()
        self.cmd = CommandRequestRW(geom_settings.addressbits,
                                    geom_settings.bankbits)

        ###

        # Request FIFO
        layout = [("we", 1), ("adr", len(req.adr))]
        req_in = Record(layout)
        reqf = Record(layout)
        self.submodules.req_fifo = SyncFIFO(layout_len(layout),
                                            controller_settings.req_queue_size)
        self.comb += [
            self.req_fifo.din.eq(req_in.raw_bits()),
            reqf.raw_bits().eq(self.req_fifo.dout)
        ]
        self.comb += [
            req_in.we.eq(req.we),
            req_in.adr.eq(req.adr),
            self.req_fifo.we.eq(req.stb),
            req.req_ack.eq(self.req_fifo.writable),
            self.req_fifo.re.eq(req.dat_w_ack | req.dat_r_ack),
            req.lock.eq(self.req_fifo.readable)
        ]

        slicer = _AddressSlicer(geom_settings.colbits, address_align)

        # Row tracking
        has_openrow = Signal()
        openrow = Signal(geom_settings.rowbits)
        hit = Signal()
        self.comb += hit.eq(openrow == slicer.row(reqf.adr))
        track_open = Signal()
        track_close = Signal()
        self.sync += [
            If(track_open, has_openrow.eq(1),
               openrow.eq(slicer.row(reqf.adr))),
            If(track_close, has_openrow.eq(0))
        ]

        # Address generation
        s_row_adr = Signal()
        self.comb += [
            self.cmd.ba.eq(bankn),
            If(s_row_adr, self.cmd.a.eq(slicer.row(reqf.adr))).Else(
                self.cmd.a.eq(slicer.col(reqf.adr)))
        ]

        # Respect write-to-precharge specification
        precharge_ok = Signal()
        t_unsafe_precharge = 2 + timing_settings.tWR - 1
        unsafe_precharge_count = Signal(max=t_unsafe_precharge + 1)
        self.comb += precharge_ok.eq(unsafe_precharge_count == 0)
        self.sync += [
            If(self.cmd.stb & self.cmd.ack & self.cmd.is_write,
               unsafe_precharge_count.eq(t_unsafe_precharge)).Elif(
                   ~precharge_ok,
                   unsafe_precharge_count.eq(unsafe_precharge_count - 1))
        ]

        # Control and command generation FSM
        fsm = FSM()
        self.submodules += fsm
        fsm.act(
            "REGULAR",
            If(self.refresh_req, NextState("REFRESH")).Elif(
                self.req_fifo.readable,
                If(
                    has_openrow,
                    If(
                        hit,
                        # NB: write-to-read specification is enforced by multiplexer
                        self.cmd.stb.eq(1),
                        req.dat_w_ack.eq(self.cmd.ack & reqf.we),
                        req.dat_r_ack.eq(self.cmd.ack & ~reqf.we),
                        self.cmd.is_read.eq(~reqf.we),
                        self.cmd.is_write.eq(reqf.we),
                        self.cmd.cas_n.eq(0),
                        self.cmd.we_n.eq(~reqf.we)).Else(
                            NextState("PRECHARGE"))).Else(
                                NextState("ACTIVATE"))))
        fsm.act(
            "PRECHARGE",
            # Notes:
            # 1. we are presenting the column address, A10 is always low
            # 2. since we always go to the ACTIVATE state, we do not need
            # to assert track_close.
            If(precharge_ok, self.cmd.stb.eq(1),
               If(self.cmd.ack, NextState("TRP")), self.cmd.ras_n.eq(0),
               self.cmd.we_n.eq(0), self.cmd.is_cmd.eq(1)))
        fsm.act("ACTIVATE", s_row_adr.eq(1), track_open.eq(1),
                self.cmd.stb.eq(1), self.cmd.is_cmd.eq(1),
                If(self.cmd.ack, NextState("TRCD")), self.cmd.ras_n.eq(0))
        fsm.act("REFRESH", self.refresh_gnt.eq(precharge_ok),
                track_close.eq(1), self.cmd.is_cmd.eq(1),
                If(~self.refresh_req, NextState("REGULAR")))
        fsm.delayed_enter("TRP", "ACTIVATE", timing_settings.tRP - 1)
        fsm.delayed_enter("TRCD", "REGULAR", timing_settings.tRCD - 1)
Exemplo n.º 7
0
    def __init__(self,
                 phy_settings,
                 geom_settings,
                 timing_settings,
                 controller_settings,
                 bank_machines,
                 refresher,
                 dfi,
                 lasmic,
                 with_bandwidth=False):
        assert (phy_settings.nphases == len(dfi.phases))
        self.phy_settings = phy_settings

        # Command choosing
        requests = [bm.cmd for bm in bank_machines]
        self.submodules.choose_cmd = choose_cmd = _CommandChooser(requests)
        self.submodules.choose_req = choose_req = _CommandChooser(requests)
        self.comb += [
            choose_cmd.want_reads.eq(0),
            choose_cmd.want_writes.eq(0)
        ]
        if phy_settings.nphases == 1:
            self.comb += [
                choose_cmd.want_cmds.eq(1),
                choose_req.want_cmds.eq(1)
            ]

        # Command steering
        nop = CommandRequest(geom_settings.addressbits, geom_settings.bankbits)
        commands = [nop, choose_cmd.cmd, choose_req.cmd,
                    refresher.cmd]  # nop must be 1st
        (STEER_NOP, STEER_CMD, STEER_REQ, STEER_REFRESH) = range(4)
        steerer = _Steerer(commands, dfi)
        self.submodules += steerer

        # Read/write turnaround
        read_available = Signal()
        write_available = Signal()
        self.comb += [
            read_available.eq(
                reduce(or_, [req.stb & req.is_read for req in requests])),
            write_available.eq(
                reduce(or_, [req.stb & req.is_write for req in requests]))
        ]

        def anti_starvation(timeout):
            en = Signal()
            max_time = Signal()
            if timeout:
                t = timeout - 1
                time = Signal(max=t + 1)
                self.comb += max_time.eq(time == 0)
                self.sync += If(~en, time.eq(t)).Elif(~max_time,
                                                      time.eq(time - 1))
            else:
                self.comb += max_time.eq(0)
            return en, max_time

        read_time_en, max_read_time = anti_starvation(
            controller_settings.read_time)
        write_time_en, max_write_time = anti_starvation(
            controller_settings.write_time)

        # Refresh
        self.comb += [bm.refresh_req.eq(refresher.req) for bm in bank_machines]
        go_to_refresh = Signal()
        self.comb += go_to_refresh.eq(
            reduce(and_, [bm.refresh_gnt for bm in bank_machines]))

        # Datapath
        all_rddata = [p.rddata for p in dfi.phases]
        all_wrdata = [p.wrdata for p in dfi.phases]
        all_wrdata_mask = [p.wrdata_mask for p in dfi.phases]
        self.comb += [
            lasmic.dat_r.eq(Cat(*all_rddata)),
            Cat(*all_wrdata).eq(lasmic.dat_w),
            Cat(*all_wrdata_mask).eq(~lasmic.dat_we)
        ]

        # Control FSM
        fsm = FSM()
        self.submodules += fsm

        def steerer_sel(steerer, phy_settings, r_w_n):
            r = []
            for i in range(phy_settings.nphases):
                s = steerer.sel[i].eq(STEER_NOP)
                if r_w_n == "read":
                    if i == phy_settings.rdphase:
                        s = steerer.sel[i].eq(STEER_REQ)
                    elif i == phy_settings.rdcmdphase:
                        s = steerer.sel[i].eq(STEER_CMD)
                elif r_w_n == "write":
                    if i == phy_settings.wrphase:
                        s = steerer.sel[i].eq(STEER_REQ)
                    elif i == phy_settings.wrcmdphase:
                        s = steerer.sel[i].eq(STEER_CMD)
                else:
                    raise ValueError
                r.append(s)
            return r

        fsm.act(
            "READ",
            read_time_en.eq(1),
            choose_req.want_reads.eq(1),
            choose_cmd.cmd.ack.eq(1),
            choose_req.cmd.ack.eq(1),
            steerer_sel(steerer, phy_settings, "read"),
            If(
                write_available,
                # TODO: switch only after several cycles of ~read_available?
                If(~read_available | max_read_time, NextState("RTW"))),
            If(go_to_refresh, NextState("REFRESH")))
        fsm.act(
            "WRITE", write_time_en.eq(1), choose_req.want_writes.eq(1),
            choose_cmd.cmd.ack.eq(1), choose_req.cmd.ack.eq(1),
            steerer_sel(steerer, phy_settings, "write"),
            If(read_available,
               If(~write_available | max_write_time, NextState("WTR"))),
            If(go_to_refresh, NextState("REFRESH")))
        fsm.act("REFRESH", steerer.sel[0].eq(STEER_REFRESH),
                refresher.ack.eq(1), If(~refresher.req, NextState("READ")))
        fsm.delayed_enter(
            "RTW", "WRITE", phy_settings.read_latency -
            1)  # FIXME: reduce this, actual limit is around (cl+1)/nphases
        fsm.delayed_enter("WTR", "READ", timing_settings.tWTR - 1)

        if controller_settings.with_bandwidth:
            data_width = phy_settings.dfi_databits * phy_settings.nphases
            self.submodules.bandwidth = Bandwidth(self.choose_req.cmd,
                                                  data_width)
Exemplo n.º 8
0
    def __init__(self, sink_description, source_description, header):
        self.sink = sink = stream.Endpoint(sink_description)
        self.source = source = stream.Endpoint(source_description)
        self.header = Signal(header.length * 8)

        # # #

        dw = len(sink.data)

        header_words = (header.length * 8) // dw

        shift = Signal()
        counter = Signal(max=max(header_words, 2))
        counter_reset = Signal()
        counter_ce = Signal()
        self.sync += \
            If(counter_reset,
                counter.eq(0)
            ).Elif(counter_ce,
                counter.eq(counter + 1)
            )

        if header_words == 1:
            self.sync += \
                If(shift,
                    self.header.eq(sink.data)
                )
        else:
            self.sync += \
                If(shift,
                    self.header.eq(Cat(self.header[dw:], sink.data))
                )

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

        if header_words == 1:
            idle_next_state = "COPY"
        else:
            idle_next_state = "RECEIVE_HEADER"

        fsm.act("IDLE", sink.ready.eq(1), counter_reset.eq(1),
                If(sink.valid, shift.eq(1), NextState(idle_next_state)))
        if header_words != 1:
            fsm.act(
                "RECEIVE_HEADER", sink.ready.eq(1),
                If(sink.valid, counter_ce.eq(1), shift.eq(1),
                   If(counter == header_words - 2, NextState("COPY"))))
        no_payload = Signal()
        self.sync += \
            If(fsm.before_entering("COPY"),
                no_payload.eq(sink.last)
            )

        if hasattr(sink, "error"):
            self.comb += source.error.eq(sink.error)
        self.comb += [
            source.last.eq(sink.last | no_payload),
            source.data.eq(sink.data),
            header.decode(self.header, source)
        ]
        fsm.act(
            "COPY", sink.ready.eq(source.ready),
            source.valid.eq(sink.valid | no_payload),
            If(source.valid & source.ready & source.last, NextState("IDLE")))
Exemplo n.º 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"))))
Exemplo n.º 10
0
    def __init__(self, master, slave):
        dw_from = len(master.dat_r)
        dw_to = len(slave.dat_w)
        ratio = dw_to // dw_from
        ratiobits = log2_int(ratio)

        # # #

        write = Signal()
        evict = Signal()
        refill = Signal()
        read = Signal()

        address = FlipFlop(30)
        self.submodules += address
        self.comb += address.d.eq(master.adr)

        counter = Signal(max=ratio)
        counter_ce = Signal()
        counter_reset = Signal()
        self.sync += \
            If(counter_reset,
                counter.eq(0)
            ).Elif(counter_ce,
                counter.eq(counter + 1)
            )
        counter_offset = Signal(max=ratio)
        counter_done = Signal()
        self.comb += [
            counter_offset.eq(address.q),
            counter_done.eq((counter + counter_offset) == ratio - 1)
        ]

        cached_data = Signal(dw_to)
        cached_sel = Signal(dw_to // 8)

        end_of_burst = Signal()
        self.comb += end_of_burst.eq(~master.cyc
                                     | (master.stb & master.cyc & master.ack
                                        & ((master.cti == 7) | counter_done)))

        need_refill = FlipFlop(reset=1)
        self.submodules += need_refill
        self.comb += [need_refill.reset.eq(end_of_burst), need_refill.d.eq(0)]

        # Main FSM
        self.submodules.fsm = fsm = FSM()
        fsm.act(
            "IDLE", counter_reset.eq(1),
            If(
                master.stb & master.cyc, address.ce.eq(1),
                If(master.we, NextState("WRITE")).Else(
                    If(need_refill.q,
                       NextState("REFILL")).Else(NextState("READ")))))
        fsm.act(
            "WRITE",
            If(master.stb & master.cyc, write.eq(1), counter_ce.eq(1),
               master.ack.eq(1),
               If(counter_done,
                  NextState("EVICT"))).Elif(~master.cyc, NextState("EVICT")))
        fsm.act("EVICT", evict.eq(1), slave.stb.eq(1), slave.we.eq(1),
                slave.cyc.eq(1), slave.dat_w.eq(cached_data),
                slave.sel.eq(cached_sel), If(slave.ack, NextState("IDLE")))
        fsm.act("REFILL", refill.eq(1), slave.stb.eq(1), slave.cyc.eq(1),
                If(slave.ack, need_refill.ce.eq(1), NextState("READ")))
        fsm.act("READ", read.eq(1),
                If(master.stb & master.cyc, master.ack.eq(1)),
                NextState("IDLE"))

        # Address
        self.comb += [
            slave.cti.eq(
                7),  # we are not able to generate bursts since up-converting
            slave.adr.eq(address.q[ratiobits:])
        ]

        # Datapath
        cached_datas = [FlipFlop(dw_from) for i in range(ratio)]
        cached_sels = [FlipFlop(dw_from // 8) for i in range(ratio)]
        self.submodules += cached_datas, cached_sels

        cases = {}
        for i in range(ratio):
            write_sel = Signal()
            cases[i] = write_sel.eq(1)
            self.comb += [
                cached_sels[i].reset.eq(counter_reset),
                If(
                    write,
                    cached_datas[i].d.eq(master.dat_w),
                ).Else(cached_datas[i].d.eq(slave.dat_r[dw_from * i:dw_from *
                                                        (i + 1)])),
                cached_sels[i].d.eq(master.sel),
                If((write & write_sel) | refill, cached_datas[i].ce.eq(1),
                   cached_sels[i].ce.eq(1))
            ]
        self.comb += Case(counter + counter_offset, cases)

        cases = {}
        for i in range(ratio):
            cases[i] = master.dat_r.eq(cached_datas[i].q)
        self.comb += Case(address.q[:ratiobits], cases)

        self.comb += [
            cached_data.eq(Cat([cached_data.q
                                for cached_data in cached_datas])),
            cached_sel.eq(Cat([cached_sel.q for cached_sel in cached_sels]))
        ]
Exemplo n.º 11
0
    def __init__(self, master, slave):
        dw_from = len(master.dat_r)
        dw_to = len(slave.dat_w)
        ratio = dw_from // dw_to

        # # #

        read = Signal()
        write = Signal()

        counter = Signal(max=ratio)
        counter_reset = Signal()
        counter_ce = Signal()
        self.sync += \
            If(counter_reset,
                counter.eq(0)
            ).Elif(counter_ce,
                counter.eq(counter + 1)
            )
        counter_done = Signal()
        self.comb += counter_done.eq(counter == ratio - 1)

        # Main FSM
        self.submodules.fsm = fsm = FSM(reset_state="IDLE")
        fsm.act(
            "IDLE", counter_reset.eq(1),
            If(master.stb & master.cyc,
               If(master.we, NextState("WRITE")).Else(NextState("READ"))))
        fsm.act(
            "WRITE", write.eq(1), slave.we.eq(1), slave.cyc.eq(1),
            If(
                master.stb & master.cyc, slave.stb.eq(1),
                If(slave.ack, counter_ce.eq(1),
                   If(counter_done, master.ack.eq(1),
                      NextState("IDLE")))).Elif(~master.cyc,
                                                NextState("IDLE")))
        fsm.act(
            "READ", read.eq(1), slave.cyc.eq(1),
            If(
                master.stb & master.cyc, slave.stb.eq(1),
                If(slave.ack, counter_ce.eq(1),
                   If(counter_done, master.ack.eq(1),
                      NextState("IDLE")))).Elif(~master.cyc,
                                                NextState("IDLE")))

        # Address
        self.comb += [
            If(
                counter_done,
                slave.cti.eq(7)  # indicate end of burst
            ).Else(slave.cti.eq(2)),
            slave.adr.eq(Cat(counter, master.adr))
        ]

        # Datapath
        cases = {}
        for i in range(ratio):
            cases[i] = [
                slave.sel.eq(master.sel[i * dw_to // 8:(i + 1) * dw_to]),
                slave.dat_w.eq(master.dat_w[i * dw_to:(i + 1) * dw_to])
            ]
        self.comb += Case(counter, cases)

        cached_data = Signal(dw_from)
        self.comb += master.dat_r.eq(Cat(cached_data[dw_to:], slave.dat_r))
        self.sync += \
            If(read & counter_ce,
                cached_data.eq(master.dat_r)
            )
Exemplo n.º 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")))
Exemplo n.º 13
0
    def __init__(self, dram_port, nslots):
        bus_aw = dram_port.aw
        bus_dw = dram_port.dw
        alignment_bits = bits_for(bus_dw//8) - 1

        fifo_word_width = bus_dw
        self.frame = stream.Endpoint([("sof", 1), ("pixels", fifo_word_width)])
        self._frame_size = CSRStorage(bus_aw + alignment_bits,
                                      alignment_bits=alignment_bits)
        self.submodules._slot_array = _SlotArray(nslots, bus_aw, alignment_bits)
        self.ev = self._slot_array.ev

        # # #

        # address generator + maximum memory word count to prevent DMA buffer
        # overrun
        reset_words = Signal()
        count_word = Signal()
        last_word = Signal()
        current_address = Signal(bus_aw)
        mwords_remaining = Signal(bus_aw)
        self.comb += [
            self._slot_array.address_reached.eq(current_address),
            last_word.eq(mwords_remaining == 1)
        ]
        self.sync += [
            If(reset_words,
                current_address.eq(self._slot_array.address),
                mwords_remaining.eq(self._frame_size.storage)
            ).Elif(count_word,
                current_address.eq(current_address + 1),
                mwords_remaining.eq(mwords_remaining - 1)
            )
        ]

        memory_word = Signal(bus_dw)
        pixbits = []
        for i in range(bus_dw//16):
            pixbits.append(self.frame.pixels)
        self.comb += memory_word.eq(Cat(*pixbits))

        # bus accessor
        self.submodules._bus_accessor = LiteDRAMDMAWriter(dram_port)
        self.comb += [
            self._bus_accessor.sink.address.eq(current_address),
            self._bus_accessor.sink.data.eq(memory_word)
        ]

        # control FSM
        fsm = FSM()
        self.submodules += fsm

        fsm.act("WAIT_SOF",
            reset_words.eq(1),
            self.frame.ready.eq(~self._slot_array.address_valid |
                                ~self.frame.sof),
            If(self._slot_array.address_valid &
               self.frame.sof &
               self.frame.valid,
               NextState("TRANSFER_PIXELS")
            )
        )
        fsm.act("TRANSFER_PIXELS",
            self.frame.ready.eq(self._bus_accessor.sink.ready),
            If(self.frame.valid,
                self._bus_accessor.sink.valid.eq(1),
                If(self._bus_accessor.sink.ready,
                    count_word.eq(1),
                    If(last_word,
                        NextState("EOF")
                    )
                )
            )
        )
        fsm.act("EOF",
            If(~dram_port.wdata.valid,
                self._slot_array.address_done.eq(1),
                NextState("WAIT_SOF")
            )
        )
Exemplo n.º 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)
Exemplo n.º 15
0
    def __init__(self, pads, rd_timing, wr_timing):
        self.bus = wishbone.Interface()

        ###

        data = TSTriple(16)
        lsb = Signal()

        self.specials += data.get_tristate(pads.d)
        self.comb += [data.oe.eq(pads.oe_n), pads.ce_n.eq(0)]

        load_lo = Signal()
        load_hi = Signal()
        store = Signal()

        pads.oe_n.reset, pads.we_n.reset = 1, 1
        self.sync += [
            pads.oe_n.eq(1),
            pads.we_n.eq(1),

            # Register data/address to avoid off-chip glitches
            If(
                self.bus.cyc & self.bus.stb,
                pads.adr.eq(Cat(lsb, self.bus.adr)),
                If(
                    self.bus.we,
                    # Only 16-bit writes are supported. Assume sel=0011 or 1100.
                    If(self.bus.sel[0], data.o.eq(self.bus.dat_w[:16])).Else(
                        data.o.eq(self.bus.dat_w[16:])
                    )).Else(pads.oe_n.eq(0))),
            If(load_lo, self.bus.dat_r[:16].eq(data.i)),
            If(load_hi, self.bus.dat_r[16:].eq(data.i)),
            If(store, pads.we_n.eq(0))
        ]

        # Typical timing of the flash chips:
        #  - 110ns address to output
        #  - 50ns write pulse width
        counter = Signal(max=max(rd_timing, wr_timing) + 1)
        counter_en = Signal()
        counter_wr_mode = Signal()
        counter_done = Signal()
        self.comb += counter_done.eq(
            counter == Mux(counter_wr_mode, wr_timing, rd_timing))
        self.sync += If(counter_en & ~counter_done,
                        counter.eq(counter + 1)).Else(counter.eq(0))

        fsm = FSM()
        self.submodules += fsm

        fsm.act(
            "IDLE",
            If(self.bus.cyc & self.bus.stb,
               If(self.bus.we, NextState("WR")).Else(NextState("RD_HI"))))
        fsm.act("RD_HI", lsb.eq(0), counter_en.eq(1),
                If(counter_done, load_hi.eq(1), NextState("RD_LO")))
        fsm.act("RD_LO", lsb.eq(1), counter_en.eq(1),
                If(counter_done, load_lo.eq(1), NextState("ACK")))
        fsm.act(
            "WR",
            # supported cases: sel=0011 [lsb=1] and sel=1100 [lsb=0]
            lsb.eq(self.bus.sel[0]),
            counter_wr_mode.eq(1),
            counter_en.eq(1),
            store.eq(1),
            If(counter_done, NextState("ACK")))
        fsm.act("ACK", self.bus.ack.eq(1), NextState("IDLE"))
Exemplo n.º 16
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)

        ###

        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")))