Exemple #1
0
    def __init__(self, clk_freq, rd_data):
        self.clk_freq = clk_freq
        self.rd_data = [0] + rd_data
        self.rd_idx = 0

        # timings
        self.tRDInactive = self.ns(49) # RXF# inactive after RD# cycle
        self.tWRInactive = self.ns(49) # TXE# inactive after WR# cycle

        # pads
        self.data = Signal(8)
        self.rxf_n = Signal(reset=1)
        self.txe_n = Signal(reset=1)
        self.rd_n = Signal(reset=1)
        self.wr_n = Signal(reset=1)

        self.init = True
        self.wr_data = []
        self.wait_wr_n = False
        self.rd_done = 0


        self.data_w = Signal(8)
        self.data_r = Signal(8)

        self.specials += Tristate(self.data, self.data_r, ~self.rd_n, self.data_w)

        self.last_wr_n = 1
        self.last_rd_n = 1

        self.wr_delay = 0
        self.rd_delay = 0
Exemple #2
0
    def __init__(self, rd_data):
        RandRun.__init__(self, 10)
        self.rd_data = [0] + rd_data
        self.rd_idx = 0

        # pads
        self.data = Signal(8)
        self.rxf_n = Signal(reset=1)
        self.txe_n = Signal(reset=1)
        self.rd_n = Signal(reset=1)
        self.wr_n = Signal(reset=1)
        self.oe_n = Signal(reset=1)
        self.siwua = Signal()
        self.pwren_n = Signal(reset=1)

        self.init = True
        self.wr_data = []
        self.wait_wr_n = False
        self.rd_done = 0

        self.data_w = Signal(8)
        self.data_r = Signal(8)

        self.specials += Tristate(self.data, self.data_r, ~self.oe_n,
                                  self.data_w)
Exemple #3
0
    def __init__(self, pads):
        self._w = CSRStorage(3, name="w")
        self._r = CSRStatus(1, name="r")

        # # #

        data_w = Signal()
        data_oe = Signal()
        data_r = Signal()
        self.comb += [
            pads.mdc.eq(self._w.storage[0]),
            data_oe.eq(self._w.storage[1]),
            data_w.eq(self._w.storage[2])
        ]
        self.specials += [
            MultiReg(data_r, self._r.status[0]),
            Tristate(pads.mdio, data_w, data_oe, data_r)
        ]
Exemple #4
0
    def __init__(self,
                 pads,
                 clk_freq,
                 fifo_depth=32,
                 read_time=128,
                 write_time=128):
        dw = len(pads.data)

        # read fifo (FTDI --> SoC)
        read_fifo = ClockDomainsRenamer({
            "write": "usb",
            "read": "sys"
        })(stream.AsyncFIFO(phy_description(8), fifo_depth))
        read_buffer = ClockDomainsRenamer("usb")(stream.SyncFIFO(
            phy_description(8), 4))
        self.comb += read_buffer.source.connect(read_fifo.sink)

        # write fifo (SoC --> FTDI)
        write_fifo = ClockDomainsRenamer({
            "write": "sys",
            "read": "usb"
        })(stream.AsyncFIFO(phy_description(8), fifo_depth))

        self.submodules += read_fifo, read_buffer, write_fifo

        # sink / source interfaces
        self.sink = write_fifo.sink
        self.source = read_fifo.source

        # read / write arbitration
        wants_write = Signal()
        wants_read = Signal()

        txe_n = Signal()
        rxf_n = Signal()

        self.comb += [
            txe_n.eq(pads.txe_n),
            rxf_n.eq(pads.rxf_n),
            wants_write.eq(~txe_n & write_fifo.source.valid),
            wants_read.eq(~rxf_n & read_fifo.sink.ready),
        ]

        read_time_en, max_read_time = anti_starvation(self, read_time)
        write_time_en, max_write_time = anti_starvation(self, write_time)

        data_w_accepted = Signal(reset=1)

        fsm = FSM(reset_state="READ")
        self.submodules += ClockDomainsRenamer("usb")(fsm)

        fsm.act(
            "READ", read_time_en.eq(1),
            If(wants_write, If(~wants_read | max_read_time, NextState("RTW"))))
        fsm.act("RTW", NextState("WRITE"))
        fsm.act(
            "WRITE", write_time_en.eq(1),
            If(wants_read, If(~wants_write | max_write_time,
                              NextState("WTR"))),
            write_fifo.source.ready.eq(wants_write & data_w_accepted))
        fsm.act("WTR", NextState("READ"))

        # databus tristate
        data_w = Signal(dw)
        data_r = Signal(dw)
        data_oe = Signal()
        self.specials += Tristate(pads.data, data_w, data_oe, data_r)

        # read / write actions
        pads.oe_n.reset = 1
        pads.rd_n.reset = 1
        pads.wr_n.reset = 1

        self.sync.usb += [
            If(fsm.ongoing("READ"), data_oe.eq(0), pads.oe_n.eq(0),
               pads.rd_n.eq(~wants_read),
               pads.wr_n.eq(1)).Elif(fsm.ongoing("WRITE"), data_oe.eq(1),
                                     pads.oe_n.eq(1), pads.rd_n.eq(1),
                                     pads.wr_n.eq(~wants_write),
                                     data_w_accepted.eq(~txe_n)).Else(
                                         data_oe.eq(1),
                                         pads.oe_n.eq(~fsm.ongoing("WTR")),
                                         pads.rd_n.eq(1), pads.wr_n.eq(1)),
            read_buffer.sink.valid.eq(~pads.rd_n & ~rxf_n),
            read_buffer.sink.data.eq(data_r),
            If(~txe_n & data_w_accepted, data_w.eq(write_fifo.source.data))
        ]
Exemple #5
0
    def __init__(self,
                 pads,
                 clk_freq,
                 fifo_depth=32,
                 read_time=128,
                 write_time=128):
        dw = len(pads.data)
        self.clk_freq = clk_freq

        # timings
        tRD = self.ns(30)  # RD# active pulse width (t4)
        tRDDataSetup = self.ns(14)  # RD# to DATA (t3)
        tWRDataSetup = self.ns(5)  # DATA to WR# active setup time (t8)
        tWR = self.ns(30)  # WR# active pulse width (t10)
        tMultiReg = 2

        # read fifo (FTDI --> SoC)
        read_fifo = stream.SyncFIFO(phy_description(8), fifo_depth)

        # write fifo (SoC --> FTDI)
        write_fifo = stream.SyncFIFO(phy_description(8), fifo_depth)

        self.submodules += read_fifo, write_fifo

        # sink / source interfaces
        self.sink = write_fifo.sink
        self.source = read_fifo.source

        # read / write arbitration
        wants_write = Signal()
        wants_read = Signal()

        txe_n = Signal()
        rxf_n = Signal()

        self.specials += [
            MultiReg(pads.txe_n, txe_n),
            MultiReg(pads.rxf_n, rxf_n)
        ]

        self.comb += [
            wants_write.eq(~txe_n & write_fifo.source.valid),
            wants_read.eq(~rxf_n & read_fifo.sink.ready),
        ]

        read_time_en, max_read_time = anti_starvation(self, read_time)
        write_time_en, max_write_time = anti_starvation(self, write_time)

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

        read_done = Signal()
        write_done = Signal()
        commuting = Signal()

        fsm.act(
            "READ", read_time_en.eq(1),
            If(
                wants_write & read_done,
                If(~wants_read | max_read_time, commuting.eq(1),
                   NextState("RTW"))))
        fsm.act("RTW", NextState("WRITE"))
        fsm.act(
            "WRITE", write_time_en.eq(1),
            If(
                wants_read & write_done,
                If(~wants_write | max_write_time, commuting.eq(1),
                   NextState("WTR"))))
        fsm.act("WTR", NextState("READ"))

        # databus tristate
        data_w = Signal(dw)
        data_r_async = Signal(dw)
        data_r = Signal(dw)
        data_oe = Signal()
        self.specials += [
            Tristate(pads.data, data_w, data_oe, data_r_async),
            MultiReg(data_r_async, data_r)
        ]

        # read actions
        pads.rd_n.reset = 1

        read_fsm = FSM(reset_state="IDLE")
        self.submodules += read_fsm
        read_counter = Signal(8)
        read_counter_reset = Signal()
        read_counter_ce = Signal()
        self.sync += \
            If(read_counter_reset,
                read_counter.eq(0)
            ).Elif(read_counter_ce,
                read_counter.eq(read_counter + 1)
            )

        read_fsm.act(
            "IDLE", read_done.eq(1), read_counter_reset.eq(1),
            If(
                fsm.ongoing("READ") & wants_read,
                If(~commuting, NextState("PULSE_RD_N"))))
        read_fsm.act(
            "PULSE_RD_N", pads.rd_n.eq(0), read_counter_ce.eq(1),
            If(read_counter == max((tRD - 1), (tRDDataSetup + tMultiReg - 1)),
               NextState("ACQUIRE_DATA")))
        read_fsm.act("ACQUIRE_DATA", read_fifo.sink.valid.eq(1),
                     read_fifo.sink.data.eq(data_r), NextState("WAIT_RXF_N"))
        read_fsm.act("WAIT_RXF_N", If(rxf_n, NextState("IDLE")))

        # write actions
        pads.wr_n.reset = 1

        write_fsm = FSM(reset_state="IDLE")
        self.submodules += write_fsm
        write_counter = Signal(8)
        write_counter_reset = Signal()
        write_counter_ce = Signal()
        self.sync += \
            If(write_counter_reset,
                write_counter.eq(0)
            ).Elif(write_counter_ce,
                write_counter.eq(write_counter + 1)
            )

        write_fsm.act(
            "IDLE", write_done.eq(1), write_counter_reset.eq(1),
            If(
                fsm.ongoing("WRITE") & wants_write,
                If(~commuting, NextState("SET_DATA"))))
        write_fsm.act(
            "SET_DATA", data_oe.eq(1), data_w.eq(write_fifo.source.data),
            write_counter_ce.eq(1),
            If(write_counter == (tWRDataSetup - 1), write_counter_reset.eq(1),
               NextState("PULSE_WR_N")))
        write_fsm.act("PULSE_WR_N", data_oe.eq(1),
                      data_w.eq(write_fifo.source.data), pads.wr_n.eq(0),
                      write_counter_ce.eq(1),
                      If(write_counter == (tWR - 1), NextState("WAIT_TXE_N")))
        write_fsm.act(
            "WAIT_TXE_N",
            If(txe_n, write_fifo.source.ready.eq(1), NextState("IDLE")))
Exemple #6
0
    def __init__(self, pads):
        addressbits = len(pads.a)
        bankbits = len(pads.ba)
        databits = len(pads.dq)

        self.settings = sdram_settings.PhySettings(
            memtype="SDR",
            dfi_databits=databits,
            nphases=1,
            rdphase=0,
            wrphase=0,
            rdcmdphase=0,
            wrcmdphase=0,
            cl=2,
            read_latency=4,
            write_latency=0
        )

        self.dfi = Interface(addressbits, bankbits, databits)

        ###

        #
        # Command/address
        #
        self.sync += [
            pads.a.eq(self.dfi.p0.address),
            pads.ba.eq(self.dfi.p0.bank),
            pads.cke.eq(self.dfi.p0.cke),
            pads.cas_n.eq(self.dfi.p0.cas_n),
            pads.ras_n.eq(self.dfi.p0.ras_n),
            pads.we_n.eq(self.dfi.p0.we_n)
        ]
        if hasattr(pads, "cs_n"):
            self.sync += pads.cs_n.eq(self.dfi.p0.cs_n)

        #
        # DQ/DQS/DM data
        #
        sd_dq_out = Signal(databits)
        drive_dq = Signal()
        self.sync += sd_dq_out.eq(self.dfi.p0.wrdata)
        self.specials += Tristate(pads.dq, sd_dq_out, drive_dq)
        self.sync += \
            If(self.dfi.p0.wrdata_en,
                pads.dm.eq(self.dfi.p0.wrdata_mask)
            ).Else(
                pads.dm.eq(0)
            )
        sd_dq_in_ps = Signal(databits)
        self.sync.sys_ps += sd_dq_in_ps.eq(pads.dq)
        self.sync += self.dfi.p0.rddata.eq(sd_dq_in_ps)

        #
        # DQ/DM control
        #
        d_dfi_wrdata_en = Signal()
        self.sync += d_dfi_wrdata_en.eq(self.dfi.p0.wrdata_en)
        self.comb += drive_dq.eq(d_dfi_wrdata_en)

        rddata_sr = Signal(4)
        self.comb += self.dfi.p0.rddata_valid.eq(rddata_sr[3])
        self.sync += rddata_sr.eq(Cat(self.dfi.p0.rddata_en, rddata_sr[:3]))
Exemple #7
0
    def __init__(self, pads, dw=32, timeout=1024):
        read_fifo = ClockDomainsRenamer({
            "write": "usb",
            "read": "sys"
        })(stream.AsyncFIFO(phy_description(dw), 128))
        write_fifo = ClockDomainsRenamer({
            "write": "sys",
            "read": "usb"
        })(stream.AsyncFIFO(phy_description(dw), 128))

        read_buffer = ClockDomainsRenamer("usb")(stream.SyncFIFO(
            phy_description(dw), 4))
        self.comb += read_buffer.source.connect(read_fifo.sink)

        self.submodules += read_fifo
        self.submodules += read_buffer
        self.submodules += write_fifo

        self.read_buffer = read_buffer

        self.sink = write_fifo.sink
        self.source = read_fifo.source

        self.tdata_w = tdata_w = Signal(dw)
        self.data_r = data_r = Signal(dw)
        self.data_oe = data_oe = Signal()
        self.specials += Tristate(pads.data, tdata_w, data_oe, data_r)

        data_w = Signal(dw)
        _data_w = Signal(dw)
        self.sync.usb += [_data_w.eq(data_w)]
        for i in range(dw):
            self.specials += [
                Instance("ODDR",
                         p_DDR_CLK_EDGE="SAME_EDGE",
                         i_C=ClockSignal("usb"),
                         i_CE=1,
                         i_S=0,
                         i_R=0,
                         i_D1=_data_w[i],
                         i_D2=data_w[i],
                         o_Q=tdata_w[i])
            ]

        self.rd_n = rd_n = Signal()
        _rd_n = Signal(reset=1)
        self.wr_n = wr_n = Signal()
        _wr_n = Signal(reset=1)
        self.oe_n = oe_n = Signal()
        _oe_n = Signal(reset=1)
        self.sync.usb += [
            _rd_n.eq(rd_n),
            _wr_n.eq(wr_n),
            _oe_n.eq(oe_n),
        ]
        self.specials += [
            Instance("ODDR",
                     p_DDR_CLK_EDGE="SAME_EDGE",
                     i_C=ClockSignal("usb"),
                     i_CE=1,
                     i_S=0,
                     i_R=0,
                     i_D1=_rd_n,
                     i_D2=rd_n,
                     o_Q=pads.rd_n),
            Instance("ODDR",
                     p_DDR_CLK_EDGE="SAME_EDGE",
                     i_C=ClockSignal("usb"),
                     i_CE=1,
                     i_S=0,
                     i_R=0,
                     i_D1=_wr_n,
                     i_D2=wr_n,
                     o_Q=pads.wr_n),
            Instance("ODDR",
                     p_DDR_CLK_EDGE="SAME_EDGE",
                     i_C=ClockSignal("usb"),
                     i_CE=1,
                     i_S=0,
                     i_R=0,
                     i_D1=_oe_n,
                     i_D2=oe_n,
                     o_Q=pads.oe_n)
        ]

        self.comb += [
            pads.rst.eq(~ResetSignal("usb")),
            pads.be.eq(0xf),
            pads.siwua.eq(1),
            data_oe.eq(oe_n),
        ]

        fsm = FSM()
        self.submodules.fsm = ClockDomainsRenamer("usb")(fsm)

        self.tempsendval = tempsendval = Signal(dw)
        self.temptosend = temptosend = Signal()

        self.tempreadval = tempreadval = Signal(dw)
        self.temptoread = temptoread = Signal()

        self.wants_read = wants_read = Signal()
        self.wants_write = wants_write = Signal()
        self.cnt_write = cnt_write = Signal(max=timeout + 1)
        self.cnt_read = cnt_read = Signal(max=timeout + 1)

        first_write = Signal()

        self.comb += [
            wants_read.eq(~temptoread & ~pads.rxf_n),
            wants_write.eq((temptosend | write_fifo.source.valid)
                           & (pads.txe_n == 0)),
        ]

        self.fsmstate = Signal(4)
        self.comb += [
            self.fsmstate.eq(
                Cat(fsm.ongoing("IDLE"), fsm.ongoing("WRITE"),
                    fsm.ongoing("RDWAIT"), fsm.ongoing("READ")))
        ]

        self.sync.usb += [
            If(~fsm.ongoing("READ"),
               If(temptoread, If(read_buffer.sink.ready, temptoread.eq(0))))
        ]
        self.comb += [
            If(
                ~fsm.ongoing("READ"),
                If(
                    temptoread,
                    read_buffer.sink.data.eq(tempreadval),
                    read_buffer.sink.valid.eq(1),
                ))
        ]

        fsm.act(
            "IDLE", rd_n.eq(1), wr_n.eq(1),
            If(
                wants_write,
                oe_n.eq(1),
                NextValue(cnt_write, 0),
                NextValue(first_write, 1),
                NextState("WRITE"),
            ).Elif(wants_read, oe_n.eq(0),
                   NextState("RDWAIT")).Else(oe_n.eq(1), ))

        fsm.act(
            "WRITE", If(
                wants_read,
                NextValue(cnt_write, cnt_write + 1),
            ), NextValue(first_write, 0), rd_n.eq(1),
            If(
                pads.txe_n, oe_n.eq(1), wr_n.eq(1),
                write_fifo.source.ready.eq(0),
                If(write_fifo.source.valid & ~first_write,
                   NextValue(temptosend, 1)),
                NextState("IDLE")).Elif(
                    temptosend, oe_n.eq(1), data_w.eq(tempsendval), wr_n.eq(0),
                    NextValue(temptosend,
                              0)).Elif(cnt_write > timeout, oe_n.eq(0),
                                       NextState("RDWAIT")).Elif(
                                           write_fifo.source.valid,
                                           oe_n.eq(1),
                                           data_w.eq(write_fifo.source.data),
                                           write_fifo.source.ready.eq(1),
                                           NextValue(tempsendval,
                                                     write_fifo.source.data),
                                           NextValue(temptosend, 0),
                                           wr_n.eq(0),
                                       ).Else(oe_n.eq(1), wr_n.eq(1),
                                              NextValue(temptosend, 0),
                                              NextState("IDLE")))

        fsm.act("RDWAIT", rd_n.eq(0), oe_n.eq(0), wr_n.eq(1),
                NextValue(cnt_read, 0), NextState("READ"))

        fsm.act(
            "READ", If(
                wants_write,
                NextValue(cnt_read, cnt_read + 1),
            ), wr_n.eq(1),
            If(
                pads.rxf_n,
                oe_n.eq(0),
                rd_n.eq(1),
                NextState("IDLE"),
            ).Elif(
                cnt_read > timeout,
                NextValue(cnt_write, 0),
                NextValue(first_write, 1),
                NextState("WRITE"),
                oe_n.eq(1),
            ).Else(
                oe_n.eq(0), read_buffer.sink.valid.eq(1),
                read_buffer.sink.data.eq(data_r),
                NextValue(tempreadval, data_r),
                If(read_buffer.sink.ready,
                   rd_n.eq(0)).Else(NextValue(temptoread, 1),
                                    NextState("IDLE"), rd_n.eq(1))))
    def __init__(self,
                 platform,
                 usb_connector=0,
                 with_usb2=True,
                 with_usb2_analyzer=False,
                 with_usb3=True,
                 with_usb3_analyzer=False):
        BaseSoC.__init__(self, platform)

        # usb ios
        usb_reset_n = platform.request("usb_reset_n", usb_connector)
        if with_usb2:
            usb_ulpi = platform.request("usb_ulpi", usb_connector)
        if with_usb3:
            usb_pipe_ctrl = platform.request("usb_pipe_ctrl", usb_connector)
            usb_pipe_status = platform.request("usb_pipe_status",
                                               usb_connector)
            usb_pipe_data = platform.request("usb_pipe_data", usb_connector)

        usb2_reset_n = Signal(reset=1)
        usb3_reset_n = Signal(reset=1)
        self.comb += usb_reset_n.eq(usb2_reset_n & usb3_reset_n)

        # usb2 core
        if with_usb2:

            class USB2Control(Module, AutoCSR):
                def __init__(self):
                    self._phy_enable = CSRStorage()
                    self._core_enable = CSRStorage()

                    # probably not working but prevent synthesis optimizations
                    self._buf_in_addr = CSRStorage(9)
                    self._buf_in_data = CSRStorage(8)
                    self._buf_in_wren = CSR()
                    self._buf_in_ready = CSRStatus()
                    self._buf_in_commit = CSR()
                    self._buf_in_commit_len = CSRStorage(10)
                    self._buf_in_commit_ack = CSRStatus()

                    self._buf_out_addr = CSRStorage(9)
                    self._buf_out_q = CSRStatus(8)
                    self._buf_out_len = CSRStatus(10)
                    self._buf_out_hasdata = CSRStatus()
                    self._buf_out_arm = CSR()
                    self._buf_out_arm_ack = CSRStatus()

                    # # #

                    self.phy_enable = self._phy_enable.storage
                    self.core_enable = self._core_enable.storage

                    self.buf_in_addr = self._buf_in_addr.storage
                    self.buf_in_data = self._buf_in_data.storage
                    self.buf_in_wren = self._buf_in_wren.re & self._buf_in_wren.r
                    self.buf_in_ready = self._buf_in_ready.status
                    self.buf_in_commit = self._buf_in_commit.re & self._buf_in_commit.r
                    self.buf_in_commit_len = self._buf_in_commit_len.storage
                    self.buf_in_commit_ack = self._buf_in_commit_ack.status

                    self.buf_out_addr = self._buf_out_addr.storage
                    self.buf_out_q = self._buf_out_q.status
                    self.buf_out_len = self._buf_out_len.status
                    self.buf_out_hasdata = self._buf_out_hasdata.status
                    self.buf_out_arm = self._buf_out_arm.re & self._buf_out_arm.r
                    self.buf_out_arm_ack = self._buf_out_arm_ack.status

            self.submodules.usb2_control = USB2Control()

            self.clock_domains.cd_ulpi = ClockDomain()
            self.comb += self.cd_ulpi.clk.eq(usb_ulpi.clk)

            self.cd_ulpi.clk.attr.add("keep")
            self.platform.add_period_constraint(self.cd_ulpi.clk, 16.667)
            self.platform.add_false_path_constraints(self.crg.cd_sys.clk,
                                                     self.cd_ulpi.clk)

            stat_connected = Signal()
            stat_fs = Signal()
            stat_hs = Signal()
            stat_configured = Signal()

            vend_req_act = Signal()
            vend_req_request = Signal(8)
            vend_req_val = Signal(16)

            err_crc_pid = Signal()
            err_crc_tok = Signal()
            err_crc_pkt = Signal()
            err_pid_out_of_seq = Signal()
            err_setup_pkt = Signal()

            dbg_frame_num = Signal(11)
            dbg_linestate = Signal(2)

            self.comb += usb2_reset_n.eq(self.usb2_control.phy_enable)
            self.specials += Instance(
                "usb2_top",
                i_ext_clk=ClockSignal(),
                i_reset_n=self.usb2_control.core_enable,
                #o_reset_n_out=,
                i_phy_ulpi_clk=usb_ulpi.clk,
                io_phy_ulpi_d=usb_ulpi.data,
                i_phy_ulpi_dir=usb_ulpi.dir,
                o_phy_ulpi_stp=usb_ulpi.stp,
                i_phy_ulpi_nxt=usb_ulpi.nxt,
                i_opt_disable_all=0,
                i_opt_enable_hs=0,
                i_opt_ignore_vbus=0,
                o_stat_connected=stat_connected,
                o_stat_fs=stat_fs,
                o_stat_hs=stat_hs,
                o_stat_configured=stat_configured,
                i_buf_in_addr=self.usb2_control.buf_in_addr,
                i_buf_in_data=self.usb2_control.buf_in_data,
                i_buf_in_wren=self.usb2_control.buf_in_wren,
                o_buf_in_ready=self.usb2_control.buf_in_ready,
                i_buf_in_commit=self.usb2_control.buf_in_commit,
                i_buf_in_commit_len=self.usb2_control.buf_in_commit_len,
                o_buf_in_commit_ack=self.usb2_control.buf_in_commit_ack,
                i_buf_out_addr=self.usb2_control.buf_out_addr,
                o_buf_out_q=self.usb2_control.buf_out_q,
                o_buf_out_len=self.usb2_control.buf_out_len,
                o_buf_out_hasdata=self.usb2_control.buf_out_hasdata,
                i_buf_out_arm=self.usb2_control.buf_out_arm,
                o_buf_out_arm_ack=self.usb2_control.buf_out_arm_ack,
                o_vend_req_act=vend_req_act,
                o_vend_req_request=vend_req_request,
                o_vend_req_val=vend_req_val,
                o_err_crc_pid=err_crc_pid,
                o_err_crc_tok=err_crc_tok,
                o_err_crc_pkt=err_crc_pkt,
                o_err_pid_out_of_seq=err_pid_out_of_seq,
                o_err_setup_pkt=err_setup_pkt,
                o_dbg_frame_num=dbg_frame_num,
                o_dbg_linestate=dbg_linestate)
            platform.add_verilog_include_path(os.path.join("core"))
            platform.add_verilog_include_path(os.path.join("core", "usb2"))
            platform.add_source_dir(os.path.join("core", "usb2"))

            # usb2 debug
            if with_usb2_analyzer:
                analyzer_signals = [
                    dbg_frame_num, dbg_linestate, stat_connected, stat_fs,
                    stat_hs, stat_configured, vend_req_act, vend_req_request,
                    vend_req_val, err_crc_pid, err_crc_tok, err_crc_pkt,
                    err_pid_out_of_seq, err_setup_pkt
                ]
                self.submodules.analyzer = LiteScopeAnalyzer(analyzer_signals,
                                                             2048,
                                                             cd="ulpi")

        # usb3 core
        if with_usb3:

            class USB3Control(Module, AutoCSR):
                def __init__(self):
                    self._phy_enable = CSRStorage()
                    self._core_enable = CSRStorage()

                    # probably not working but prevent synthesis optimizations
                    self._buf_in_addr = CSRStorage(9)
                    self._buf_in_data = CSRStorage(32)
                    self._buf_in_wren = CSR()
                    self._buf_in_request = CSRStatus()
                    self._buf_in_ready = CSRStatus()
                    self._buf_in_commit = CSR()
                    self._buf_in_commit_len = CSRStorage(11)
                    self._buf_in_commit_ack = CSRStatus()

                    self._buf_out_addr = CSRStorage(9)
                    self._buf_out_q = CSRStatus(32)
                    self._buf_out_len = CSRStatus(11)
                    self._buf_out_hasdata = CSRStatus()
                    self._buf_out_arm = CSR()
                    self._buf_out_arm_ack = CSRStatus()

                    # # #

                    self.phy_enable = self._phy_enable.storage
                    self.core_enable = self._core_enable.storage

                    self.buf_in_addr = self._buf_in_addr.storage
                    self.buf_in_data = self._buf_in_data.storage
                    self.buf_in_wren = self._buf_in_wren.re & self._buf_in_wren.r
                    self.buf_in_request = self._buf_in_request.status
                    self.buf_in_ready = self._buf_in_ready.status
                    self.buf_in_commit = self._buf_in_commit.re & self._buf_in_commit.r
                    self.buf_in_commit_len = self._buf_in_commit_len.storage
                    self.buf_in_commit_ack = self._buf_in_commit_ack.status

                    self.buf_out_addr = self._buf_out_addr.storage
                    self.buf_out_q = self._buf_out_q.status
                    self.buf_out_len = self._buf_out_len.status
                    self.buf_out_hasdata = self._buf_out_hasdata.status
                    self.buf_out_arm = self._buf_out_arm.re & self._buf_out_arm.r
                    self.buf_out_arm_ack = self._buf_out_arm_ack.status

            self.submodules.usb3_control = USB3Control()

            phy_pipe_pll_locked = Signal()
            phy_pipe_pll_fb = Signal()

            phy_pipe_half_clk_pll = Signal()
            phy_pipe_half_clk_phase_pll = Signal()
            phy_pipe_quarter_clk_pll = Signal()
            phy_pipe_tx_clk_phase_pll = Signal()

            phy_pipe_half_clk = Signal()
            phy_pipe_half_clk_phase = Signal()
            phy_pipe_quarter_clk = Signal()
            phy_pipe_tx_clk_phase = Signal()

            self.specials += [
                Instance(
                    "PLLE2_BASE",
                    p_STARTUP_WAIT="FALSE",
                    o_LOCKED=phy_pipe_pll_locked,

                    # VCO @ 1GHz
                    p_REF_JITTER1=0.01,
                    p_CLKIN1_PERIOD=4.0,
                    p_CLKFBOUT_MULT=4,
                    p_DIVCLK_DIVIDE=1,
                    i_CLKIN1=usb_pipe_data.rx_clk,
                    i_CLKFBIN=phy_pipe_pll_fb,
                    o_CLKFBOUT=phy_pipe_pll_fb,

                    # 125MHz: 1/2 PCLK
                    p_CLKOUT0_DIVIDE=8,
                    p_CLKOUT0_PHASE=0.0,
                    o_CLKOUT0=phy_pipe_half_clk_pll,

                    # 125MHz: 1/2 PCLK, phase shift 90
                    p_CLKOUT1_DIVIDE=8,
                    p_CLKOUT1_PHASE=90.0,
                    o_CLKOUT1=phy_pipe_half_clk_phase_pll,

                    # 62.5MHz: 1/4 PCLK
                    p_CLKOUT2_DIVIDE=16,
                    p_CLKOUT2_PHASE=0.0,
                    o_CLKOUT2=phy_pipe_quarter_clk_pll,

                    # 250Mhz: TX CLK, phase shift 90
                    p_CLKOUT3_DIVIDE=4,
                    p_CLKOUT3_PHASE=90.0,
                    o_CLKOUT3=phy_pipe_tx_clk_phase_pll),
                Instance("BUFG",
                         i_I=phy_pipe_half_clk_pll,
                         o_O=phy_pipe_half_clk),
                Instance("BUFG",
                         i_I=phy_pipe_half_clk_phase_pll,
                         o_O=phy_pipe_half_clk_phase),
                Instance("BUFG",
                         i_I=phy_pipe_quarter_clk_pll,
                         o_O=phy_pipe_quarter_clk),
                Instance("BUFG",
                         i_I=phy_pipe_tx_clk_phase_pll,
                         o_O=phy_pipe_tx_clk_phase),
            ]

            self.clock_domains.cd_phy_pipe_half = ClockDomain()
            self.clock_domains.cd_phy_pipe_half_phase = ClockDomain()
            self.clock_domains.cd_phy_pipe_quarter = ClockDomain()
            self.clock_domains.cd_phy_pipe_tx_phase = ClockDomain()
            self.comb += [
                self.cd_phy_pipe_half.clk.eq(phy_pipe_half_clk),
                self.cd_phy_pipe_half_phase.clk.eq(phy_pipe_half_clk_phase),
                self.cd_phy_pipe_quarter.clk.eq(phy_pipe_quarter_clk),
                self.cd_phy_pipe_tx_phase.clk.eq(phy_pipe_tx_clk_phase)
            ]
            self.specials += [
                AsyncResetSynchronizer(self.cd_phy_pipe_half,
                                       ~phy_pipe_pll_locked),
                AsyncResetSynchronizer(self.cd_phy_pipe_half_phase,
                                       ~phy_pipe_pll_locked),
                AsyncResetSynchronizer(self.cd_phy_pipe_quarter,
                                       ~phy_pipe_pll_locked),
                AsyncResetSynchronizer(self.cd_phy_pipe_tx_phase,
                                       ~phy_pipe_pll_locked)
            ]
            self.cd_phy_pipe_half.clk.attr.add("keep")
            self.cd_phy_pipe_half_phase.clk.attr.add("keep")
            self.cd_phy_pipe_quarter.clk.attr.add("keep")
            self.cd_phy_pipe_tx_phase.clk.attr.add("keep")
            self.platform.add_period_constraint(self.cd_phy_pipe_half.clk, 8.0)
            self.platform.add_period_constraint(
                self.cd_phy_pipe_half_phase.clk, 8.0)
            self.platform.add_period_constraint(self.cd_phy_pipe_quarter.clk,
                                                16.0)
            self.platform.add_period_constraint(self.cd_phy_pipe_tx_phase.clk,
                                                4.0)
            self.platform.add_false_path_constraints(
                self.crg.cd_sys.clk, self.cd_phy_pipe_half.clk,
                self.cd_phy_pipe_half_phase.clk, self.cd_phy_pipe_quarter.clk,
                self.cd_phy_pipe_tx_phase.clk)

            phy_pipe_rx_data = Signal(32)
            phy_pipe_rx_datak = Signal(4)
            phy_pipe_rx_valid = Signal(2)

            phy_pipe_tx_data = Signal(32)
            phy_pipe_tx_datak = Signal(4)

            phy_rx_status = Signal(6)
            phy_phy_status = Signal(2)

            dbg_pipe_state = Signal(6)
            dbg_ltssm_state = Signal(5)

            usb_pipe_status_phy_status = Signal()
            self.specials += Tristate(usb_pipe_status.phy_status, 0,
                                      ~usb3_reset_n,
                                      usb_pipe_status_phy_status)

            self.comb += usb3_reset_n.eq(self.usb3_control.phy_enable)
            self.specials += Instance(
                "usb3_top",
                i_ext_clk=ClockSignal(),
                i_reset_n=self.usb3_control.core_enable,
                i_phy_pipe_half_clk=ClockSignal("phy_pipe_half"),
                i_phy_pipe_half_clk_phase=ClockSignal("phy_pipe_half_phase"),
                i_phy_pipe_quarter_clk=ClockSignal("phy_pipe_quarter"),
                i_phy_pipe_rx_data=phy_pipe_rx_data,
                i_phy_pipe_rx_datak=phy_pipe_rx_datak,
                i_phy_pipe_rx_valid=phy_pipe_rx_valid,
                o_phy_pipe_tx_data=phy_pipe_tx_data,
                o_phy_pipe_tx_datak=phy_pipe_tx_datak,

                #o_phy_reset_n=,
                #o_phy_out_enable=,
                o_phy_phy_reset_n=usb_pipe_ctrl.phy_reset_n,
                o_phy_tx_detrx_lpbk=usb_pipe_ctrl.tx_detrx_lpbk,
                o_phy_tx_elecidle=usb_pipe_ctrl.tx_elecidle,
                io_phy_rx_elecidle=usb_pipe_status.rx_elecidle,
                i_phy_rx_status=phy_rx_status,
                o_phy_power_down=usb_pipe_ctrl.power_down,
                i_phy_phy_status_i=phy_phy_status,
                #o_phy_phy_status_o=,
                i_phy_pwrpresent=usb_pipe_status.pwr_present,
                o_phy_tx_oneszeros=usb_pipe_ctrl.tx_oneszeros,
                o_phy_tx_deemph=usb_pipe_ctrl.tx_deemph,
                o_phy_tx_margin=usb_pipe_ctrl.tx_margin,
                o_phy_tx_swing=usb_pipe_ctrl.tx_swing,
                o_phy_rx_polarity=usb_pipe_ctrl.rx_polarity,
                o_phy_rx_termination=usb_pipe_ctrl.rx_termination,
                o_phy_rate=usb_pipe_ctrl.rate,
                o_phy_elas_buf_mode=usb_pipe_ctrl.elas_buf_mode,
                i_buf_in_addr=self.usb3_control.buf_in_addr,
                i_buf_in_data=self.usb3_control.buf_in_data,
                i_buf_in_wren=self.usb3_control.buf_in_wren,
                o_buf_in_request=self.usb3_control.buf_in_request,
                o_buf_in_ready=self.usb3_control.buf_in_ready,
                i_buf_in_commit=self.usb3_control.buf_in_commit,
                i_buf_in_commit_len=self.usb3_control.buf_in_commit_len,
                o_buf_in_commit_ack=self.usb3_control.buf_in_commit_ack,
                i_buf_out_addr=self.usb3_control.buf_out_addr,
                o_buf_out_q=self.usb3_control.buf_out_q,
                o_buf_out_len=self.usb3_control.buf_out_len,
                o_buf_out_hasdata=self.usb3_control.buf_out_hasdata,
                i_buf_out_arm=self.usb3_control.buf_out_arm,
                o_buf_out_arm_ack=self.usb3_control.buf_out_arm_ack,

                #o_vend_req_act=,
                #o_vend_req_request=,
                #o_vend_req_val=,
                o_dbg_pipe_state=dbg_pipe_state,
                o_dbg_ltssm_state=dbg_ltssm_state)
            platform.add_verilog_include_path(os.path.join("core"))
            platform.add_verilog_include_path(os.path.join("core", "usb3"))
            platform.add_source_dir(os.path.join("core", "usb3"))

            # ddr inputs
            self.specials += Instance(
                "IDDR",
                p_DDR_CLK_EDGE="SAME_EDGE_PIPELINED",
                i_C=ClockSignal("phy_pipe_half"),
                i_CE=1,
                i_S=0,
                i_R=0,
                i_D=usb_pipe_data.rx_valid,
                o_Q1=phy_pipe_rx_valid[0],
                o_Q2=phy_pipe_rx_valid[1],
            )
            for i in range(16):
                self.specials += Instance(
                    "IDDR",
                    p_DDR_CLK_EDGE="SAME_EDGE_PIPELINED",
                    i_C=ClockSignal("phy_pipe_half"),
                    i_CE=1,
                    i_S=0,
                    i_R=0,
                    i_D=usb_pipe_data.rx_data[i],
                    o_Q1=phy_pipe_rx_data[i],
                    o_Q2=phy_pipe_rx_data[16 + i],
                )
            for i in range(2):
                self.specials += Instance(
                    "IDDR",
                    p_DDR_CLK_EDGE="SAME_EDGE_PIPELINED",
                    i_C=ClockSignal("phy_pipe_half"),
                    i_CE=1,
                    i_S=0,
                    i_R=0,
                    i_D=usb_pipe_data.rx_datak[i],
                    o_Q1=phy_pipe_rx_datak[i],
                    o_Q2=phy_pipe_rx_datak[2 + i],
                )
            for i in range(3):
                self.specials += Instance(
                    "IDDR",
                    p_DDR_CLK_EDGE="SAME_EDGE_PIPELINED",
                    i_C=ClockSignal("phy_pipe_half"),
                    i_CE=1,
                    i_S=0,
                    i_R=0,
                    i_D=usb_pipe_status.rx_status[i],
                    o_Q1=phy_rx_status[i],
                    o_Q2=phy_rx_status[3 + i],
                )
            self.specials += Instance(
                "IDDR",
                p_DDR_CLK_EDGE="SAME_EDGE_PIPELINED",
                i_C=ClockSignal("phy_pipe_half"),
                i_CE=1,
                i_S=0,
                i_R=0,
                i_D=usb_pipe_status_phy_status,
                o_Q1=phy_phy_status[0],
                o_Q2=phy_phy_status[1],
            )

            # ddr outputs
            self.specials += Instance(
                "ODDR",
                p_DDR_CLK_EDGE="SAME_EDGE",
                i_C=ClockSignal("phy_pipe_tx_phase"),
                i_CE=1,
                i_S=0,
                i_R=0,
                i_D1=1,
                i_D2=0,
                o_Q=usb_pipe_data.tx_clk,
            )
            for i in range(16):
                self.specials += Instance(
                    "ODDR",
                    p_DDR_CLK_EDGE="SAME_EDGE",
                    i_C=ClockSignal("phy_pipe_half_phase"),
                    i_CE=1,
                    i_S=0,
                    i_R=0,
                    i_D1=phy_pipe_tx_data[i],
                    i_D2=phy_pipe_tx_data[16 + i],
                    o_Q=usb_pipe_data.tx_data[i],
                )
            for i in range(2):
                self.specials += Instance(
                    "ODDR",
                    p_DDR_CLK_EDGE="SAME_EDGE",
                    i_C=ClockSignal("phy_pipe_half_phase"),
                    i_CE=1,
                    i_S=0,
                    i_R=0,
                    i_D1=phy_pipe_tx_datak[i],
                    i_D2=phy_pipe_tx_datak[2 + i],
                    o_Q=usb_pipe_data.tx_datak[i],
                )

            # usb3 debug
            if with_usb3_analyzer:
                analyzer_signals = [
                    dbg_pipe_state, dbg_ltssm_state,
                    usb_pipe_ctrl.tx_detrx_lpbk, usb_pipe_ctrl.tx_elecidle,
                    usb_pipe_status.rx_elecidle, usb_pipe_ctrl.power_down,
                    usb_pipe_status.phy_status, usb_pipe_status.pwr_present,
                    usb_pipe_ctrl.tx_oneszeros, usb_pipe_ctrl.tx_deemph,
                    usb_pipe_ctrl.tx_margin, usb_pipe_ctrl.tx_swing,
                    usb_pipe_ctrl.rx_polarity, usb_pipe_ctrl.rx_termination,
                    usb_pipe_ctrl.rate, usb_pipe_ctrl.elas_buf_mode,
                    phy_pipe_rx_valid, phy_pipe_rx_data, phy_pipe_rx_datak,
                    phy_pipe_tx_data, phy_pipe_tx_datak
                ]
                self.submodules.analyzer = LiteScopeAnalyzer(
                    analyzer_signals, 2048, cd="phy_pipe_half")
Exemple #9
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")))