Пример #1
0
    def __init__(self, phy, clk_freq, mode):
        self.submodules.etherbone = etherbone = Etherbone(mode)
        depacketizer = Depacketizer(clk_freq)
        packetizer = Packetizer()
        self.submodules += depacketizer, packetizer
        tx_cdc = stream.AsyncFIFO([("data", 32)], 8)
        tx_cdc = ClockDomainsRenamer({
            "write": "sys",
            "read": "serwb_serdes"
        })(tx_cdc)
        self.submodules += tx_cdc
        rx_cdc = stream.AsyncFIFO([("data", 32)], 8)
        rx_cdc = ClockDomainsRenamer({
            "write": "serwb_serdes",
            "read": "sys"
        })(rx_cdc)
        self.submodules += rx_cdc
        self.comb += [
            # core <--> etherbone
            depacketizer.source.connect(etherbone.sink),
            etherbone.source.connect(packetizer.sink),

            # core --> serdes
            packetizer.source.connect(tx_cdc.sink),
            If(tx_cdc.source.valid & phy.init.ready,
               phy.serdes.tx_data.eq(tx_cdc.source.data)),
            tx_cdc.source.ready.eq(phy.init.ready),

            # serdes --> core
            rx_cdc.sink.valid.eq(phy.init.ready),
            rx_cdc.sink.data.eq(phy.serdes.rx_data),
            rx_cdc.source.connect(depacketizer.sink),
        ]
Пример #2
0
    def __init__(self, pads, cd="ulpi"):
        self.submodules.ulpi_phy = ClockDomainsRenamer(cd)(ULPIPHYS7(pads))

        fifo_sink = stream.AsyncFIFO(self.ulpi_phy.sink.description, 4)
        self.submodules.fifo_sink = ClockDomainsRenamer({
            "write": "sys",
            "read": cd
        })(fifo_sink)

        fifo_source = stream.AsyncFIFO(self.ulpi_phy.source.description, 4)
        self.submodules.fifo_source = ClockDomainsRenamer({
            "write": cd,
            "read": "sys"
        })(fifo_source)

        self.sink = self.fifo_sink.sink
        self.source = self.fifo_source.source

        # # #

        self.rx_fifo = self.ulpi_phy.rx_fifo

        self.comb += [
            self.fifo_sink.source.connect(self.ulpi_phy.sink),
            self.ulpi_phy.source.connect(self.fifo_source.sink),
        ]
Пример #3
0
    def __init__(self,
                 port_from,
                 port_to,
                 cmd_depth=4,
                 wdata_depth=16,
                 rdata_depth=16):
        assert port_from.address_width == port_to.address_width
        assert port_from.data_width == port_to.data_width
        assert port_from.mode == port_to.mode

        address_width = port_from.address_width
        data_width = port_from.data_width
        mode = port_from.mode
        clock_domain_from = port_from.clock_domain
        clock_domain_to = port_to.clock_domain

        # # #

        cmd_fifo = stream.AsyncFIFO([("we", 1), ("addr", address_width)],
                                    cmd_depth)
        cmd_fifo = ClockDomainsRenamer({
            "write": clock_domain_from,
            "read": clock_domain_to
        })(cmd_fifo)
        self.submodules += cmd_fifo
        self.submodules += stream.Pipeline(port_from.cmd, cmd_fifo,
                                           port_to.cmd)

        if mode == "write" or mode == "both":
            wdata_fifo = stream.AsyncFIFO([("data", data_width),
                                           ("we", data_width // 8)],
                                          wdata_depth)
            wdata_fifo = ClockDomainsRenamer({
                "write": clock_domain_from,
                "read": clock_domain_to
            })(wdata_fifo)
            self.submodules += wdata_fifo
            self.submodules += stream.Pipeline(port_from.wdata, wdata_fifo,
                                               port_to.wdata)

        if mode == "read" or mode == "both":
            rdata_fifo = stream.AsyncFIFO([("data", data_width)], rdata_depth)
            rdata_fifo = ClockDomainsRenamer({
                "write": clock_domain_to,
                "read": clock_domain_from
            })(rdata_fifo)
            self.submodules += rdata_fifo
            self.submodules += stream.Pipeline(port_to.rdata, rdata_fifo,
                                               port_from.rdata)
Пример #4
0
    def __init__(self, clock_domain="sys", phy_dw=16):
        self.sink   = stream.Endpoint([("data", phy_dw), ("ctrl", phy_dw//8)])
        self.source = stream.Endpoint([("data", 32), ("ctrl", 4)])

        # # #

        converter = stream.StrideConverter(
            [("data", phy_dw), ("ctrl", phy_dw//8)],
            [("data", 32), ("ctrl", 4)],
            reverse=False)
        converter = stream.BufferizeEndpoints({"sink":   stream.DIR_SINK})(converter)
        converter = ClockDomainsRenamer(clock_domain)(converter)
        self.submodules.converter = converter
        cdc = stream.AsyncFIFO([("data", 32), ("ctrl", 4)], 8, buffered=True)
        cdc = ClockDomainsRenamer({"write": clock_domain, "read": "sys"})(cdc)
        self.submodules.cdc = cdc
        skip_remover = RXSKPRemover()
        self.submodules.skip_remover = skip_remover
        word_aligner = RXWordAligner()
        word_aligner = stream.BufferizeEndpoints({"source": stream.DIR_SOURCE})(word_aligner)
        self.submodules.word_aligner = word_aligner
        self.comb += [
            self.sink.connect(converter.sink),
            converter.source.connect(cdc.sink),
            cdc.source.connect(skip_remover.sink),
            skip_remover.source.connect(word_aligner.sink),
            word_aligner.source.connect(self.source),
        ]
Пример #5
0
    def __init__(self, phy, phy_cd):
        assert len(phy.source.data) in [16, 32]
        self.sink   =   sink = stream.Endpoint([("data", len(phy.source.data)), ("ctrl", len(phy.source.ctrl))])
        self.source = source = stream.Endpoint([("data", 32), ("ctrl", 4)])

        # # #

        use_ebuf = (len(phy.source.data) == 32)

        if use_ebuf:
            ebuf = ElasticBuffer(len(phy.source.data) + len(phy.source.ctrl), 4, phy_cd, "jesd")
            self.submodules.ebuf = ebuf
            self.comb += [
                sink.ready.eq(1),
                ebuf.din[:32].eq(sink.data),
                ebuf.din[32:].eq(sink.ctrl),
                source.valid.eq(1),
                source.data.eq(ebuf.dout[:32]),
                source.ctrl.eq(ebuf.dout[32:])
            ]
        else:
            converter = stream.StrideConverter(
                [("data", len(phy.source.data)), ("ctrl", len(phy.source.ctrl))],
                [("data", 32), ("ctrl", 4)],
                reverse=False)
            converter = ClockDomainsRenamer(phy_cd)(converter)
            self.submodules += converter
            cdc = stream.AsyncFIFO([("data", 32), ("ctrl", 4)], 4)
            cdc = ClockDomainsRenamer({"write": phy_cd, "read": "jesd"})(cdc)
            self.submodules += cdc
            self.comb += [
                sink.connect(converter.sink),
                converter.source.connect(cdc.sink),
                cdc.source.connect(source)
            ]
Пример #6
0
    def __init__(self, platform, *args, **kwargs):
        BaseSoC.__init__(self, platform, *args, **kwargs)

        encoder_port = self.sdram.crossbar.get_port(mode="read", dw=128)
        self.submodules.encoder_reader = EncoderDMAReader(encoder_port)
        encoder_cdc = stream.AsyncFIFO([("data", 128)], 4)
        encoder_cdc = ClockDomainsRenamer({
            "write": "sys",
            "read": "encoder"
        })(encoder_cdc)
        encoder_buffer = ClockDomainsRenamer("encoder")(EncoderBuffer())
        encoder = Encoder(platform)
        encoder_streamer = USBStreamer(platform, platform.request("fx2"))
        self.submodules += encoder_cdc, encoder_buffer, encoder, encoder_streamer

        self.comb += [
            self.encoder_reader.source.connect(encoder_cdc.sink),
            encoder_cdc.source.connect(encoder_buffer.sink),
            encoder_buffer.source.connect(encoder.sink),
            encoder.source.connect(encoder_streamer.sink)
        ]
        self.add_wb_slave(mem_decoder(self.mem_map["encoder"]), encoder.bus)
        self.add_memory_region("encoder",
                               self.mem_map["encoder"] + self.shadow_base,
                               0x2000)

        self.platform.add_period_constraint(encoder_streamer.cd_usb.clk, 10.0)

        encoder_streamer.cd_usb.clk.attr.add("keep")
        self.crg.cd_encoder.clk.attr.add("keep")
        self.platform.add_false_path_constraints(self.crg.cd_sys.clk,
                                                 self.crg.cd_encoder.clk,
                                                 encoder_streamer.cd_usb.clk)
Пример #7
0
    def __init__(self, clock_domain="sys", phy_dw=16):
        self.sink = stream.Endpoint([("data", 32), ("ctrl", 4)])
        self.source = stream.Endpoint([("data", phy_dw),
                                       ("ctrl", phy_dw // 8)])

        # # #

        # Clock compensation
        skip_inserter = TXSKPInserter()
        self.submodules += skip_inserter

        # Clock domain crossing
        cdc = stream.AsyncFIFO([("data", 32), ("ctrl", 4)], 8, buffered=True)
        cdc = ClockDomainsRenamer({"write": "sys", "read": clock_domain})(cdc)
        self.submodules.cdc = cdc

        # Data-width adaptation
        converter = stream.StrideConverter([("data", 32), ("ctrl", 4)],
                                           [("data", phy_dw),
                                            ("ctrl", phy_dw // 8)],
                                           reverse=False)
        converter = stream.BufferizeEndpoints({"source":
                                               stream.DIR_SOURCE})(converter)
        converter = ClockDomainsRenamer(clock_domain)(converter)
        self.submodules.converter = converter

        # Flow
        self.comb += [
            self.sink.connect(skip_inserter.sink),
            skip_inserter.source.connect(cdc.sink),
            cdc.source.connect(converter.sink),
            converter.source.connect(self.source)
        ]
Пример #8
0
    def __init__(self,
                 port_from,
                 port_to,
                 cmd_depth=4,
                 wdata_depth=16,
                 rdata_depth=16):
        assert port_from.aw == port_to.aw
        assert port_from.dw == port_to.dw
        assert port_from.mode == port_to.mode

        aw = port_from.aw
        dw = port_from.dw
        mode = port_from.mode
        cd_from = port_from.cd
        cd_to = port_to.cd

        # # #

        cmd_fifo = stream.AsyncFIFO([("we", 1), ("adr", aw)], cmd_depth)
        cmd_fifo = ClockDomainsRenamer({
            "write": cd_from,
            "read": cd_to
        })(cmd_fifo)
        self.submodules += cmd_fifo
        self.submodules += stream.Pipeline(port_from.cmd, cmd_fifo,
                                           port_to.cmd)

        if mode == "write" or mode == "both":
            wdata_fifo = stream.AsyncFIFO([("data", dw), ("we", dw // 8)],
                                          wdata_depth)
            wdata_fifo = ClockDomainsRenamer({
                "write": cd_from,
                "read": cd_to
            })(wdata_fifo)
            self.submodules += wdata_fifo
            self.submodules += stream.Pipeline(port_from.wdata, wdata_fifo,
                                               port_to.wdata)

        if mode == "read" or mode == "both":
            rdata_fifo = stream.AsyncFIFO([("data", dw)], rdata_depth)
            rdata_fifo = ClockDomainsRenamer({
                "write": cd_to,
                "read": cd_from
            })(rdata_fifo)
            self.submodules += rdata_fifo
            self.submodules += stream.Pipeline(port_to.rdata, rdata_fifo,
                                               port_from.rdata)
Пример #9
0
    def __init__(self, fifo_depth=8, simulation=False):
        self.sink_data  = CSRStorage(32)
        self.sink_ready = CSRStatus()
        self.start      = CSR()
        self.done       = CSRStatus()

        # # #

        _run  = Signal()
        _csib = Signal(reset=1)
        _i    = Signal(32, reset=0xffffffff)

        # Create slow icap clk (sys_clk/4) ---------------------------------------------------------
        self.clock_domains.cd_icap = ClockDomain()
        icap_clk_counter = Signal(4)
        self.sync += icap_clk_counter.eq(icap_clk_counter + 1)
        self.sync += self.cd_icap.clk.eq(icap_clk_counter[1])

        # FIFO
        fifo = stream.AsyncFIFO([("data", 32)], fifo_depth)
        fifo = ClockDomainsRenamer({"write": "sys", "read": "icap"})(fifo)
        self.submodules += fifo
        self.comb += [
            fifo.sink.valid.eq(self.sink_data.re),
            fifo.sink.data.eq(self.sink_data.storage),
            self.sink_ready.status.eq(fifo.sink.ready),
        ]

        # Generate ICAP commands
        self.sync.icap += [
            If(self.start.re,
                _run.eq(1),
            ).Elif(~fifo.source.valid,
                _run.eq(0)
            )
        ]
        self.comb += [
            self.done.status.eq(~_run),
            If(_run,
                _i.eq(fifo.source.data),
                _csib.eq(0),
                fifo.source.ready.eq(1)
            )
        ]

        self._csib = _csib
        self._i    = _i

        # ICAP instance
        if not simulation:
            self.specials += [
                Instance("ICAPE2",
                    p_ICAP_WIDTH="X32",
                    i_CLK=ClockSignal("icap"),
                    i_CSIB=_csib,
                    i_RDWRB=0,
                    i_I=Cat(*[_i[8*i:8*(i+1)][::-1] for i in range(4)]),
                )
            ]
Пример #10
0
    def get_port(self, udp_port, dw=8, cd="sys"):
        if udp_port in self.users.keys():
            raise ValueError("Port {0:#x} already assigned".format(udp_port))

        user_port = LiteEthUDPUserPort(dw)
        internal_port = LiteEthUDPUserPort(8)

        # tx
        tx_stream = user_port.sink
        if cd is not "sys":
            tx_cdc = stream.AsyncFIFO(eth_udp_user_description(user_port.dw),
                                      4)
            tx_cdc = ClockDomainsRenamer({"write": cd, "read": "sys"})(tx_cdc)
            self.submodules += tx_cdc
            self.comb += tx_stream.connect(tx_cdc.sink)
            tx_stream = tx_cdc.source
        if dw != 8:
            tx_converter = stream.StrideConverter(
                eth_udp_user_description(user_port.dw),
                eth_udp_user_description(8))
            self.submodules += tx_converter
            self.comb += tx_stream.connect(tx_converter.sink)
            tx_stream = tx_converter.source
        self.comb += tx_stream.connect(internal_port.sink)

        # rx
        rx_stream = internal_port.source
        if dw != 8:
            rx_converter = stream.StrideConverter(
                eth_udp_user_description(8),
                eth_udp_user_description(user_port.dw))
            self.submodules += rx_converter
            self.comb += rx_stream.connect(rx_converter.sink)
            rx_stream = rx_converter.source
        if cd is not "sys":
            rx_cdc = stream.AsyncFIFO(eth_udp_user_description(user_port.dw),
                                      4)
            rx_cdc = ClockDomainsRenamer({"write": "sys", "read": cd})(rx_cdc)
            self.submodules += rx_cdc
            self.comb += rx_stream.connect(rx_cdc.sink)
            rx_stream = rx_cdc.source
        self.comb += rx_stream.connect(user_port.source)

        self.users[udp_port] = internal_port

        return user_port
Пример #11
0
    def __init__(self, data_width, depth=16):
        self.sink = sink = stream.Endpoint(core_layout(data_width))
        self.source = source = stream.Endpoint(core_layout(data_width))

        self.enable = CSRStorage()
        self.done = CSRStatus()

        self.mem_write = CSR()
        self.mem_mask = CSRStorage(data_width)
        self.mem_value = CSRStorage(data_width)
        self.mem_full = CSRStatus()

        # # #

        # Control re-synchronization
        enable = Signal()
        enable_d = Signal()
        self.specials += MultiReg(self.enable.storage, enable, "scope")
        self.sync.scope += enable_d.eq(enable)

        # Status re-synchronization
        done = Signal()
        self.specials += MultiReg(done, self.done.status)

        # Memory and configuration
        mem = stream.AsyncFIFO([("mask", data_width), ("value", data_width)],
                               depth)
        mem = ClockDomainsRenamer({"write": "sys", "read": "scope"})(mem)
        self.submodules += mem
        self.comb += [
            mem.sink.valid.eq(self.mem_write.re),
            mem.sink.mask.eq(self.mem_mask.storage),
            mem.sink.value.eq(self.mem_value.storage),
            self.mem_full.status.eq(~mem.sink.ready)
        ]

        # Hit and memory read/flush
        hit = Signal()
        flush = WaitTimer(2 * depth)
        flush = ClockDomainsRenamer("scope")(flush)
        self.submodules += flush
        self.comb += [
            flush.wait.eq(~(~enable & enable_d)),  # flush when disabling
            hit.eq((sink.data & mem.source.mask) == (mem.source.value
                                                     & mem.source.mask)),
            mem.source.ready.eq((enable & hit) | ~flush.done),
        ]

        # Output
        self.comb += [
            sink.connect(source),
            # Done when all triggers have been consumed
            done.eq(~mem.source.valid),
            source.hit.eq(done)
        ]
Пример #12
0
    def __init__(self, cd):
        self.cd = cd
        self.users = []
        self.master = LiteSPIMasterPort()
        if cd != "sys":
            rx_cdc = stream.AsyncFIFO(spi_phy2core_layout, 32, buffered=True)
            tx_cdc = stream.AsyncFIFO(spi_core2phy_layout, 32, buffered=True)
            self.submodules.rx_cdc = ClockDomainsRenamer({
                "write": cd,
                "read": "sys"
            })(rx_cdc)
            self.submodules.tx_cdc = ClockDomainsRenamer({
                "write": "sys",
                "read": cd
            })(tx_cdc)
            self.comb += [
                self.rx_cdc.source.connect(self.master.sink),
                self.master.source.connect(self.tx_cdc.sink),
            ]

        self.cs = Signal()
        self.user_cs = []
        self.user_request = []
Пример #13
0
    def __init__(self, rx_mux, cd):
        self.cd = cd
        self.users = OrderedDict()
        self.rx_mux = rx_mux
        self.master = LiteSPIMasterPort()

        if cd is not "sys":
            rx_cdc = stream.AsyncFIFO(spi_phy_data_layout, 32, buffered=True)
            tx_cdc = stream.AsyncFIFO(spi_phy_ctl_layout, 32, buffered=True)
            self.submodules.rx_cdc = ClockDomainsRenamer({
                "write": "litespi",
                "read": "sys"
            })(rx_cdc)
            self.submodules.tx_cdc = ClockDomainsRenamer({
                "write": "sys",
                "read": "litespi"
            })(tx_cdc)
            self.comb += [
                self.rx_cdc.source.connect(self.master.sink),
                self.master.source.connect(self.tx_cdc.sink),
            ]

        self.cs_n = Signal()
        self.user_cs = {}
    def __init__(self, cd): # CD is the clock domain of the dram port
        self.source = stream.Endpoint(frame_parameter_layout +
                                      frame_dma_layout)  # outputs are a cd-synchronized set of parameter from CSRs

        # # #

        cdc = stream.AsyncFIFO(self.source.description, 2)
        cdc = ClockDomainsRenamer({"write": "sys",
                                   "read": cd})(cdc)
        self.submodules += cdc

        self.enable = CSRStorage()
        for name, width in frame_parameter_layout + frame_dma_layout:
            setattr(self, name, CSRStorage(width, name=name, atomic_write=True))  # builds the CSR list
            self.comb += getattr(cdc.sink, name).eq(getattr(self, name).storage)  # assigns them to the sink
        self.comb += cdc.sink.valid.eq(self.enable.storage)  # I don't quite get this line, seems source.valid should be assigned here??
        self.comb += cdc.source.connect(self.source)   # FIFO's output ("source") is now our output
Пример #15
0
    def __init__(self, cd):
        self.source = stream.Endpoint(frame_parameter_layout +
                                      frame_dma_layout)

        # # #

        cdc = stream.AsyncFIFO(self.source.description, 2)
        cdc = ClockDomainsRenamer({"write": "sys", "read": cd})(cdc)
        self.submodules += cdc

        self.enable = CSRStorage()
        for name, width in frame_parameter_layout + frame_dma_layout:
            setattr(self, name, CSRStorage(width, name=name,
                                           atomic_write=True))
            self.comb += getattr(cdc.sink,
                                 name).eq(getattr(self, name).storage)
        self.comb += cdc.sink.valid.eq(self.enable.storage)
        self.comb += cdc.source.connect(self.source)
Пример #16
0
    def __init__(self, fifo_depth=8, icap_clk_div=4, simulation=False):
        self.sink_data  = CSRStorage(32, reset_less=True)
        self.sink_ready = CSRStatus()

        # # #

        # Create slow icap_clk (sys_clk/4) ---------------------------------------------------------
        icap_clk_counter = Signal(log2_int(icap_clk_div))
        self.clock_domains.cd_icap = ClockDomain()
        self.sync += icap_clk_counter.eq(icap_clk_counter + 1)
        self.sync += self.cd_icap.clk.eq(icap_clk_counter[-1])

        # FIFO (sys_clk to icap_clk) ---------------------------------------------------------------
        fifo = stream.AsyncFIFO([("data", 32)], fifo_depth)
        fifo = ClockDomainsRenamer({"write": "sys", "read": "icap"})(fifo)
        self.submodules += fifo
        self.comb += [
            fifo.sink.valid.eq(self.sink_data.re),
            fifo.sink.data.eq(self.sink_data.storage),
            self.sink_ready.status.eq(fifo.sink.ready),
        ]

        # Generate ICAP commands -------------------------------------------------------------------
        self._csib = _csib = Signal(reset=1)
        self._i    =    _i = Signal(32, reset=0xffffffff)
        self.comb += [
            fifo.source.ready.eq(1),
            If(fifo.source.valid,
                _csib.eq(0),
                _i.eq(fifo.source.data)
            )
        ]

        # ICAP instance ----------------------------------------------------------------------------
        if not simulation:
            self.specials += [
                Instance("ICAPE2",
                    p_ICAP_WIDTH="X32",
                    i_CLK=ClockSignal("icap"),
                    i_CSIB=_csib,
                    i_RDWRB=0,
                    i_I=Cat(*[_i[8*i:8*(i+1)][::-1] for i in range(4)]),
                )
            ]
Пример #17
0
    def __init__(self, dw, cd_ratio):
        self.sink = stream.Endpoint(core_layout(dw))
        self.source = stream.Endpoint(core_layout(dw * cd_ratio))

        # # #

        self.submodules.buffer = stream.Buffer(core_layout(dw))
        self.submodules.trigger = FrontendTrigger(dw)
        self.submodules.subsampler = FrontendSubSampler(dw)
        self.submodules.converter = stream.StrideConverter(
            core_layout(dw, 1), core_layout(dw * cd_ratio, cd_ratio))
        self.submodules.fifo = ClockDomainsRenamer({
            "write": "sys",
            "read": "new_sys"
        })(stream.AsyncFIFO(core_layout(dw * cd_ratio, cd_ratio), 8))
        self.submodules.pipeline = stream.Pipeline(self.sink, self.buffer,
                                                   self.trigger,
                                                   self.subsampler,
                                                   self.converter, self.fifo,
                                                   self.source)
Пример #18
0
    def __init__(self, platform, pads):
        self.sink = sink = stream.Endpoint([("data", 8)])

        # # #

        self.clock_domains.cd_usb = ClockDomain()
        self.specials += [
            Instance("IBUFG", i_I=pads.ifclk, o_O=self.cd_usb.clk),
        ]

        self.specials += AsyncResetSynchronizer(self.cd_usb, ResetSignal())

        fifo = stream.AsyncFIFO([("data", 8)], 4)
        fifo = ClockDomainsRenamer({"write": "encoder", "read": "usb"})(fifo)
        self.submodules.fifo = fifo
        self.comb += Record.connect(sink, fifo.sink)

        self.specials += Instance(
            "fx2_jpeg_streamer",
            # clk, rst
            i_rst=ResetSignal("usb"),
            i_clk=ClockSignal("usb"),

            # jpeg encoder interface
            i_sink_stb=fifo.source.valid,
            i_sink_data=fifo.source.data,
            o_sink_ack=fifo.source.ready,

            # cypress fx2 slave fifo interface
            io_fx2_data=pads.data,
            i_fx2_full_n=pads.flagb,
            i_fx2_empty_n=pads.flagc,
            o_fx2_addr=pads.addr,
            o_fx2_cs_n=pads.cs_n,
            o_fx2_wr_n=pads.wr_n,
            o_fx2_rd_n=pads.rd_n,
            o_fx2_oe_n=pads.oe_n,
            o_fx2_pktend_n=pads.pktend_n)

        # add vhdl sources
        platform.add_source_dir(os.path.join("gateware", "streamer", "vhdl"))
Пример #19
0
    def __init__(self,
                 jtag=None,
                 device=None,
                 data_width=8,
                 clock_domain="sys"):
        """JTAG PHY

        Provides a simple JTAG to LiteX stream module to easily stream data to/from the FPGA
        over JTAG.

        Wire format: data_width + 2 bits, LSB first.

        Host to Target:
          - TX ready : bit 0
          - RX data: : bit 1 to data_width
          - RX valid : bit data_width + 1

        Target to Host:
          - RX ready : bit 0
          - TX data  : bit 1 to data_width
          - TX valid : bit data_width + 1
        """
        self.sink = sink = stream.Endpoint([("data", data_width)])
        self.source = source = stream.Endpoint([("data", data_width)])

        # # #

        valid = Signal()
        data = Signal(data_width)
        count = Signal(max=data_width)

        # JTAG TAP ---------------------------------------------------------------------------------
        if jtag is None:
            if device[:3] == "xc6":
                jtag = S6JTAG()
            elif device[:3] == "xc7":
                jtag = S7JTAG()
            elif device[:4] in ["xcku", "xcvu"]:
                jtag = USJTAG()
            else:
                raise NotImplementedError
            self.submodules += jtag

        # JTAG clock domain ------------------------------------------------------------------------
        self.clock_domains.cd_jtag = ClockDomain()
        self.comb += ClockSignal("jtag").eq(jtag.tck)
        self.specials += AsyncResetSynchronizer(self.cd_jtag,
                                                ResetSignal("sys"))

        # JTAG clock domain crossing ---------------------------------------------------------------
        if clock_domain != "jtag":
            tx_cdc = stream.AsyncFIFO([("data", data_width)], 4)
            tx_cdc = ClockDomainsRenamer({
                "write": clock_domain,
                "read": "jtag"
            })(tx_cdc)
            rx_cdc = stream.AsyncFIFO([("data", data_width)], 4)
            rx_cdc = ClockDomainsRenamer({
                "write": "jtag",
                "read": clock_domain
            })(rx_cdc)
            self.submodules += tx_cdc, rx_cdc
            self.comb += [
                sink.connect(tx_cdc.sink),
                rx_cdc.source.connect(source)
            ]
            sink, source = tx_cdc.source, rx_cdc.sink

        # JTAG Xfer FSM ----------------------------------------------------------------------------
        fsm = FSM(reset_state="XFER-READY")
        fsm = ClockDomainsRenamer("jtag")(fsm)
        fsm = ResetInserter()(fsm)
        self.submodules += fsm
        self.comb += fsm.reset.eq(jtag.reset | jtag.capture)
        fsm.act(
            "XFER-READY", jtag.tdo.eq(source.ready),
            If(jtag.shift, sink.ready.eq(jtag.tdi),
               NextValue(valid, sink.valid), NextValue(data, sink.data),
               NextValue(count, 0), NextState("XFER-DATA")))
        fsm.act(
            "XFER-DATA", jtag.tdo.eq(data),
            If(jtag.shift, NextValue(count, count + 1),
               NextValue(data, Cat(data[1:], jtag.tdi)),
               If(count == (data_width - 1), NextState("XFER-VALID"))))
        fsm.act(
            "XFER-VALID", jtag.tdo.eq(valid),
            If(jtag.shift, source.valid.eq(jtag.tdi), NextState("XFER-READY")))
        self.comb += source.data.eq(data)
Пример #20
0
    def __init__(self,
                 platform,
                 with_cpu=True,
                 with_sdram=True,
                 with_etherbone=True,
                 with_gtp=True,
                 gtp_connector="pcie",
                 gtp_refclk="pcie",
                 gtp_linerate=5e9,
                 with_gtp_bist=True,
                 with_gtp_freqmeter=True,
                 with_record=True):
        sys_clk_freq = int(100e6)

        # SoCSDRAM ---------------------------------------------------------------------------------
        SoCSDRAM.__init__(
            self,
            platform,
            sys_clk_freq,
            cpu_type="vexriscv" if with_cpu else None,
            csr_data_width=32,
            with_uart=with_cpu,
            uart_name="crossover",
            integrated_rom_size=0x8000 if with_cpu else 0x0000,
            integrated_main_ram_size=0x1000 if not with_sdram else 0x0000,
            ident="PCIe Analyzer LiteX SoC",
            ident_version=True)

        # CRG --------------------------------------------------------------------------------------
        self.submodules.crg = _CRG(platform, sys_clk_freq)

        # DDR3 SDRAM -------------------------------------------------------------------------------
        if not self.integrated_main_ram_size:
            self.submodules.ddrphy = s7ddrphy.A7DDRPHY(
                platform.request("ddram"),
                memtype="DDR3",
                nphases=4,
                sys_clk_freq=sys_clk_freq)
            self.add_csr("ddrphy")
            sdram_module = K4B2G1646F(sys_clk_freq, "1:4")
            self.register_sdram(self.ddrphy,
                                geom_settings=sdram_module.geom_settings,
                                timing_settings=sdram_module.timing_settings)

        # Etherbone --------------------------------------------------------------------------------
        if with_etherbone:
            # ethphy
            self.submodules.ethphy = LiteEthPHYRMII(
                clock_pads=self.platform.request("eth_clocks"),
                pads=self.platform.request("eth"))
            self.add_csr("ethphy")
            # ethcore
            self.submodules.ethcore = LiteEthUDPIPCore(
                phy=self.ethphy,
                mac_address=0x10e2d5000000,
                ip_address="192.168.1.50",
                clk_freq=self.clk_freq)
            # etherbone
            self.submodules.etherbone = LiteEthEtherbone(
                self.ethcore.udp, 1234)
            self.add_wb_master(self.etherbone.wishbone.bus)
            # timing constraints
            self.platform.add_period_constraint(self.ethphy.crg.cd_eth_rx.clk,
                                                1e9 / 50e6)
            self.platform.add_period_constraint(self.ethphy.crg.cd_eth_tx.clk,
                                                1e9 / 50e6)
            self.platform.add_false_path_constraints(
                self.crg.cd_sys.clk, self.ethphy.crg.cd_eth_rx.clk,
                self.ethphy.crg.cd_eth_tx.clk)

        # GTP RefClk -------------------------------------------------------------------------------
        if with_gtp:
            assert gtp_refclk in ["pcie", "internal"]
            if gtp_refclk == "pcie":
                refclk = Signal()
                refclk_freq = 100e6
                refclk_pads = platform.request("pcie_refclk")
                self.specials += Instance("IBUFDS_GTE2",
                                          i_CEB=0,
                                          i_I=refclk_pads.p,
                                          i_IB=refclk_pads.n,
                                          o_O=refclk)
            else:
                refclk = Signal()
                refclk_freq = 100e6
                self.comb += refclk.eq(ClockSignal("clk100"))
                platform.add_platform_command(
                    "set_property SEVERITY {{Warning}} [get_drc_checks REQP-49]"
                )

        # GTP PLL ----------------------------------------------------------------------------------
        if with_gtp:
            qpll = GTPQuadPLL(refclk, refclk_freq, gtp_linerate)
            print(qpll)
            self.submodules += qpll

        # GTPs -------------------------------------------------------------------------------------
        if with_gtp:
            for i in range(2):
                tx_pads = platform.request(gtp_connector + "_tx", i)
                rx_pads = platform.request(gtp_connector + "_rx", i)
                gtp = GTP(qpll,
                          tx_pads,
                          rx_pads,
                          sys_clk_freq,
                          data_width=20,
                          clock_aligner=False,
                          tx_buffer_enable=True,
                          rx_buffer_enable=True)
                gtp.add_stream_endpoints()
                setattr(self.submodules, "gtp" + str(i), gtp)
                platform.add_period_constraint(gtp.cd_tx.clk,
                                               1e9 / gtp.tx_clk_freq)
                platform.add_period_constraint(gtp.cd_rx.clk,
                                               1e9 / gtp.rx_clk_freq)
                self.platform.add_false_path_constraints(
                    self.crg.cd_sys.clk, gtp.cd_tx.clk, gtp.cd_rx.clk)

        # GTPs FreqMeters --------------------------------------------------------------------------
        if with_gtp_freqmeter:
            self.submodules.gtp0_tx_freq = FreqMeter(ClockSignal("gtp0_tx"))
            self.submodules.gtp0_rx_freq = FreqMeter(ClockSignal("gtp0_rx"))
            self.submodules.gtp1_tx_freq = FreqMeter(ClockSignal("gtp1_tx"))
            self.submodules.gtp1_rx_freq = FreqMeter(ClockSignal("gtp1_rx"))
            self.add_csr("gtp0_tx_freq")
            self.add_csr("gtp0_rx_freq")
            self.add_csr("gtp1_tx_freq")
            self.add_csr("gtp1_rx_freq")

        # GTPs BIST --------------------------------------------------------------------------------
        if with_gtp_bist:
            self.submodules.gtp0_tx_bist = GTPTXBIST(self.gtp0, "gtp0_tx")
            self.submodules.gtp0_rx_bist = GTPRXBIST(self.gtp0, "gtp0_rx")
            self.submodules.gtp1_tx_bist = GTPTXBIST(self.gtp1, "gtp1_tx")
            self.submodules.gtp1_rx_bist = GTPRXBIST(self.gtp1, "gtp1_rx")
            self.add_csr("gtp0_tx_bist")
            self.add_csr("gtp0_rx_bist")
            self.add_csr("gtp1_tx_bist")
            self.add_csr("gtp1_rx_bist")

        # Record -----------------------------------------------------------------------------------
        # FIXME: use better data/ctrl packing (or separate recorders)
        if with_record:
            # Convert RX stream from 16-bit@250MHz to 64-bit@sys_clk
            rx_converter = stream.StrideConverter([("data", 16), ("ctrl", 2)],
                                                  [("data", 96), ("ctrl", 12)],
                                                  reverse=False)
            rx_converter = ClockDomainsRenamer("gtp0_rx")(rx_converter)
            self.submodules.rx_converter = rx_converter
            rx_cdc = stream.AsyncFIFO([("data", 96), ("ctrl", 12)],
                                      8,
                                      buffered=True)
            rx_cdc = ClockDomainsRenamer({
                "write": "gtp0_rx",
                "read": "sys"
            })(rx_cdc)
            self.submodules.rx_cdc = rx_cdc
            # RX DMA Recorder
            self.submodules.rx_dma_recorder = LiteDRAMDMAWriter(
                self.sdram.crossbar.get_port("write", 128))
            self.rx_dma_recorder.add_csr()
            self.add_csr("rx_dma_recorder")
            self.comb += [
                gtp.source.connect(rx_converter.sink),
                rx_converter.source.connect(rx_cdc.sink),
                self.rx_dma_recorder.sink.valid.eq(rx_cdc.source.valid),
                self.rx_dma_recorder.sink.data[0:96].eq(rx_cdc.source.data),
                self.rx_dma_recorder.sink.data[96:108].eq(rx_cdc.source.ctrl),
            ]
Пример #21
0
Файл: jtag.py Проект: hplp/litex
    def __init__(self,
                 jtag=None,
                 device=None,
                 data_width=8,
                 clock_domain="sys",
                 chain=1,
                 platform=None):
        """JTAG PHY

        Provides a simple JTAG to LiteX stream module to easily stream data to/from the FPGA
        over JTAG.

        Wire format: data_width + 2 bits, LSB first.

        Host to Target:
          - TX ready : bit 0
          - RX data: : bit 1 to data_width
          - RX valid : bit data_width + 1

        Target to Host:
          - RX ready : bit 0
          - TX data  : bit 1 to data_width
          - TX valid : bit data_width + 1
        """
        self.sink = sink = stream.Endpoint([("data", data_width)])
        self.source = source = stream.Endpoint([("data", data_width)])

        # # #

        # JTAG TAP ---------------------------------------------------------------------------------
        if jtag is None:
            jtag_tdi_delay = 0
            # Xilinx.
            if XilinxJTAG.get_primitive(device) is not None:
                jtag = XilinxJTAG(primitive=XilinxJTAG.get_primitive(device),
                                  chain=chain)
                jtag_tdi_delay = XilinxJTAG.get_tdi_delay(device)
            # Lattice.
            elif device[:5] == "LFE5U":
                jtag = ECP5JTAG()
            # Altera/Intel.
            elif AlteraJTAG.get_primitive(device) is not None:
                platform.add_reserved_jtag_decls()
                jtag = AlteraJTAG(primitive=AlteraJTAG.get_primitive(device),
                                  pads=platform.get_reserved_jtag_pads())
            else:
                print(device)
                raise NotImplementedError
            self.submodules.jtag = jtag

        # JTAG clock domain ------------------------------------------------------------------------
        self.clock_domains.cd_jtag = ClockDomain()
        self.comb += ClockSignal("jtag").eq(jtag.tck)
        self.specials += AsyncResetSynchronizer(self.cd_jtag,
                                                ResetSignal(clock_domain))

        # JTAG clock domain crossing ---------------------------------------------------------------
        if clock_domain != "jtag":
            tx_cdc = stream.AsyncFIFO([("data", data_width)], 4)
            tx_cdc = ClockDomainsRenamer({
                "write": clock_domain,
                "read": "jtag"
            })(tx_cdc)
            rx_cdc = stream.AsyncFIFO([("data", data_width)], 4)
            rx_cdc = ClockDomainsRenamer({
                "write": "jtag",
                "read": clock_domain
            })(rx_cdc)
            self.submodules.tx_cdc = tx_cdc
            self.submodules.rx_cdc = rx_cdc
            self.comb += [
                sink.connect(tx_cdc.sink),
                rx_cdc.source.connect(source)
            ]
            sink, source = tx_cdc.source, rx_cdc.sink

        # JTAG TDI/TDO Delay -----------------------------------------------------------------------
        jtag_tdi = jtag.tdi
        jtag_tdo = jtag.tdo
        if jtag_tdi_delay:
            jtag_tdi_sr = Signal(data_width + 2 - jtag_tdi_delay)
            self.sync.jtag += If(jtag.shift,
                                 jtag_tdi_sr.eq(Cat(jtag.tdi, jtag_tdi_sr)))
            jtag_tdi = jtag_tdi_sr[-1]

        # JTAG Xfer FSM ----------------------------------------------------------------------------
        valid = Signal()
        ready = Signal()
        data = Signal(data_width)
        count = Signal(max=data_width)

        fsm = FSM(reset_state="XFER-READY")
        fsm = ClockDomainsRenamer("jtag")(fsm)
        fsm = ResetInserter()(fsm)
        self.submodules += fsm
        self.comb += fsm.reset.eq(jtag.reset | jtag.capture)
        fsm.act(
            "XFER-READY", jtag_tdo.eq(ready),
            If(jtag.shift, sink.ready.eq(jtag_tdi),
               NextValue(valid, sink.valid), NextValue(data, sink.data),
               NextValue(count, 0), NextState("XFER-DATA")))
        fsm.act(
            "XFER-DATA", jtag_tdo.eq(data),
            If(jtag.shift, NextValue(count, count + 1),
               NextValue(data, Cat(data[1:], jtag_tdi)),
               If(count == (data_width - 1), NextState("XFER-VALID"))))
        fsm.act(
            "XFER-VALID", jtag_tdo.eq(valid),
            If(jtag.shift, source.valid.eq(jtag_tdi), source.data.eq(data),
               NextValue(ready, source.ready), NextState("XFER-READY")))
Пример #22
0
    def __init__(self,
                 layout,
                 depth=16,
                 sync_fifo=True,
                 sync_stages=2,
                 buffered=False,
                 xpm=True,
                 reset="sink"):
        cd_sink = "write"
        cd_source = "read"
        self.sink = stream.Endpoint(layout)
        self.source = stream.Endpoint(layout)
        if xpm == False:
            if sync_fifo is True:
                fifo = stream.AsyncFIFO(layout, depth=depth, buffered=buffered)
            else:
                fifo = stream.SyncFIFO(layout, depth, buffered=buffered)
            self.submodules.fifo = fifo
            self.comb += [
                self.sink.connect(fifo.sink),
                fifo.source.connect(self.source)
            ]
        else:
            desc = self.sink.description
            data_layout = [
                ("payload", desc.payload_layout),
                ("param", desc.param_layout),
            ]

            self._fifo_in = fifo_in = Record(data_layout)
            self._fifo_out = fifo_out = Record(data_layout)

            self.comb += [
                fifo_in.payload.eq(self.sink.payload),
                fifo_in.param.eq(self.sink.param),
                self.source.payload.eq(fifo_out.payload),
                self.source.param.eq(fifo_out.param),
            ]
            _tdata_len = ((len(fifo_in.raw_bits()) + 7) // 8) * 8
            _padding_len = _tdata_len - len(fifo_in.raw_bits())

            self.xpm_params = dict(
                p_CASCADE_HEIGHT=0,  # 0 = auto
                p_CDC_SYNC_STAGES=2 if sync_fifo else sync_stages,
                p_CLOCKING_MODE="common_clock"
                if sync_fifo else "independent_clock",
                p_ECC_MODE="no_ecc",
                p_FIFO_DEPTH=depth,
                p_FIFO_MEMORY_TYPE="auto",
                p_PROG_EMPTY_THRESH=10,
                p_SIM_ASSERT_CHK=1,
                p_TDATA_WIDTH=_tdata_len,
                p_TDEST_WIDTH=1,
                p_TID_WIDTH=1,
                p_TUSER_WIDTH=1,
                p_USE_ADV_FEATURES="1000",
                o_almost_empty_axis=Signal(),
                o_almost_full_axis=Signal(),
                o_dbiterr_axis=Signal(),
                i_m_aclk=0b0 if sync_fifo else ClockSignal(cd_source),
                o_m_axis_tdata=Cat(fifo_out.raw_bits(), Signal(_padding_len))
                if _padding_len != 0 else fifo_out.raw_bits(),
                o_m_axis_tdest=Signal(),
                o_m_axis_tid=Signal(),
                o_m_axis_tkeep=Signal(_tdata_len // 8),
                o_m_axis_tlast=self.source.last,
                o_m_axis_tstrb=Signal(_tdata_len // 8),
                o_m_axis_tuser=self.source.first,
                o_m_axis_tvalid=self.source.valid,
                i_m_axis_tready=self.source.ready,
                o_prog_empty_axis=Signal(),
                o_prog_full_axis=Signal(),
                o_rd_data_count_axis=Signal(),
                o_sbiterr_axis=Signal(),
                o_wr_data_count_axis=Signal(),
                i_injectdbiterr_axis=0b0,
                i_injectsbiterr_axis=0b0,
                i_s_aclk=ClockSignal() if sync_fifo else ClockSignal(cd_sink),
                i_s_aresetn=(~ResetSignal(cd_sink)) if reset == "sink" else
                (~ResetSignal(cd_source)),
                i_s_axis_tdata=Cat(fifo_in.raw_bits(),
                                   Replicate(C(0b0), _padding_len)),
                i_s_axis_tdest=0b0,
                i_s_axis_tid=0b0,
                i_s_axis_tkeep=Replicate(C(0b1), _tdata_len // 8),
                i_s_axis_tlast=self.sink.last,
                i_s_axis_tstrb=Replicate(C(0b1), _tdata_len // 8),
                i_s_axis_tuser=self.sink.first,
                i_s_axis_tvalid=self.sink.valid,
                o_s_axis_tready=self.sink.ready,
            )
Пример #23
0
def _get_uart_fifo(depth, sink_cd="sys", source_cd="sys"):
    if sink_cd != source_cd:
        fifo = stream.AsyncFIFO([("data", 8)], depth)
        return ClockDomainsRenamer({"write": sink_cd, "read": source_cd})(fifo)
    else:
        return stream.SyncFIFO([("data", 8)], depth, buffered=True)
Пример #24
0
    def __init__(self, word_width, fifo_depth):
        # in pix clock domain
        self.valid_i = Signal()
        self.vsync = Signal()
        self.de = Signal()
        self.r = Signal(8)
        self.g = Signal(8)
        self.b = Signal(8)

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

        self._overflow = CSR()

        # # #

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

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

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

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

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

        self.comb += [
            fifo.source.connect(self.frame),
            self.busy.eq(0)
        ]

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

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

        overflow_mask = Signal()
        self.comb += [
            self._overflow.w.eq(sys_overflow & ~overflow_mask),
            self.overflow_reset.i.eq(self._overflow.re)
        ]
        self.sync += \
            If(self._overflow.re,
                overflow_mask.eq(1)
            ).Elif(self.overflow_reset_ack.o,
                overflow_mask.eq(0)
            )
Пример #25
0
    def __init__(self, phy):
        self.sink = stream.Endpoint([("data", 32)])
        self.source = stream.Endpoint([("data", 32)])

        self.argument = CSRStorage(32)
        self.command = CSRStorage(32)
        self.send = CSR()

        self.response = CSRStatus(128)

        self.cmdevt = CSRStatus(4)
        self.dataevt = CSRStatus(4)

        self.blocksize = CSRStorage(16)
        self.blockcount = CSRStorage(32)

        self.timeout = CSRStorage(32, reset=2**16)

        # # #

        argument = Signal(32)
        command = Signal(32)
        response = Signal(136)
        cmdevt = Signal(4)
        dataevt = Signal(4)
        blocksize = Signal(16)
        blockcount = Signal(32)
        timeout = Signal(32)

        # sys to sd cdc
        self.specials += [
            MultiReg(self.argument.storage, argument, "sd"),
            MultiReg(self.command.storage, command, "sd"),
            MultiReg(self.blocksize.storage, blocksize, "sd"),
            MultiReg(self.blockcount.storage, blockcount, "sd"),
            MultiReg(self.timeout.storage, timeout, "sd"),
        ]

        # sd to sys cdc
        response_cdc = BusSynchronizer(136, "sd", "sys")
        cmdevt_cdc = BusSynchronizer(4, "sd", "sys")
        dataevt_cdc = BusSynchronizer(4, "sd", "sys")
        self.submodules += response_cdc, cmdevt_cdc, dataevt_cdc
        self.comb += [
            response_cdc.i.eq(response),
            self.response.status.eq(response_cdc.o[:128]),
            cmdevt_cdc.i.eq(cmdevt),
            self.cmdevt.status.eq(cmdevt_cdc.o),
            dataevt_cdc.i.eq(dataevt),
            self.dataevt.status.eq(dataevt_cdc.o)
        ]

        self.submodules.new_command = PulseSynchronizer("sys", "sd")
        self.comb += self.new_command.i.eq(self.send.re)

        self.comb += phy.cfg.timeout.eq(timeout)
        self.comb += phy.cfg.blocksize.eq(blocksize)

        self.submodules.crc7_inserter = crc7_inserter = ClockDomainsRenamer(
            "sd")(CRC(9, 7, 40))
        self.submodules.crc16_inserter = crc16_inserter = ClockDomainsRenamer(
            "sd")(CRCUpstreamInserter())
        self.submodules.crc16_checker = crc16_checker = ClockDomainsRenamer(
            "sd")(CRCDownstreamChecker())

        self.submodules.upstream_cdc = ClockDomainsRenamer({
            "write": "sys",
            "read": "sd"
        })(stream.AsyncFIFO(self.sink.description, 4))
        self.submodules.downstream_cdc = ClockDomainsRenamer({
            "write": "sd",
            "read": "sys"
        })(stream.AsyncFIFO(self.source.description, 4))

        self.submodules.upstream_converter = ClockDomainsRenamer("sd")(
            stream.StrideConverter([('data', 32)], [('data', 8)],
                                   reverse=True))
        self.submodules.downstream_converter = ClockDomainsRenamer("sd")(
            stream.StrideConverter([('data', 8)], [('data', 32)],
                                   reverse=True))

        self.comb += [
            self.sink.connect(self.upstream_cdc.sink),
            self.upstream_cdc.source.connect(self.upstream_converter.sink),
            self.upstream_converter.source.connect(crc16_inserter.sink),
            crc16_checker.source.connect(self.downstream_converter.sink),
            self.downstream_converter.source.connect(self.downstream_cdc.sink),
            self.downstream_cdc.source.connect(self.source)
        ]

        cmd_type = Signal(2)
        cmd_count = Signal(3)
        cmd_done = Signal()
        cmd_error = Signal()
        cmd_timeout = Signal()

        data_type = Signal(2)
        data_count = Signal(32)
        data_done = Signal()
        data_error = Signal()
        data_timeout = Signal()

        self.comb += [
            cmd_type.eq(command[0:2]),
            data_type.eq(command[5:7]),
            cmdevt.eq(Cat(cmd_done, cmd_error, cmd_timeout,
                          0)),  # FIXME cmd response CRC.
            dataevt.eq(
                Cat(data_done, data_error, data_timeout,
                    ~crc16_checker.valid)),
            crc7_inserter.val.eq(Cat(argument, command[8:14], 1, 0)),
            crc7_inserter.clr.eq(1),
            crc7_inserter.enable.eq(1),
        ]

        self.submodules.fsm = fsm = ClockDomainsRenamer("sd")(FSM())
        fsm.act(
            "IDLE", NextValue(cmd_done, 1), NextValue(data_done, 1),
            NextValue(cmd_count, 0), NextValue(data_count, 0),
            If(self.new_command.o, NextValue(cmd_done, 0),
               NextValue(cmd_error, 0), NextValue(cmd_timeout, 0),
               NextValue(data_done, 0), NextValue(data_error, 0),
               NextValue(data_timeout, 0), NextState("CMD")))
        fsm.act(
            "CMD", phy.cmdw.sink.valid.eq(1),
            Case(
                cmd_count, {
                    0:
                    phy.cmdw.sink.data.eq(Cat(command[8:14], 1, 0)),
                    1:
                    phy.cmdw.sink.data.eq(argument[24:32]),
                    2:
                    phy.cmdw.sink.data.eq(argument[16:24]),
                    3:
                    phy.cmdw.sink.data.eq(argument[8:16]),
                    4:
                    phy.cmdw.sink.data.eq(argument[0:8]),
                    5: [
                        phy.cmdw.sink.data.eq(Cat(1, crc7_inserter.crc)),
                        phy.cmdw.sink.last.eq(
                            cmd_type == SDCARD_CTRL_RESPONSE_NONE)
                    ]
                }),
            If(
                phy.cmdw.sink.valid & phy.cmdw.sink.ready,
                NextValue(cmd_count, cmd_count + 1),
                If(
                    cmd_count == (6 - 1),
                    If(cmd_type == SDCARD_CTRL_RESPONSE_NONE,
                       NextValue(cmd_done, 1),
                       NextState("IDLE")).Else(NextState("CMD-RESPONSE")))))
        fsm.act(
            "CMD-RESPONSE",
            phy.cmdr.sink.valid.eq(1),
            phy.cmdr.sink.last.eq(data_type == SDCARD_CTRL_DATA_TRANSFER_NONE),
            If(
                cmd_type == SDCARD_CTRL_RESPONSE_LONG,
                phy.cmdr.sink.length.eq(17)  # 136bits
            ).Else(phy.cmdr.sink.length.eq(6)  # 48bits
                   ),
            If(
                phy.cmdr.source.valid, phy.cmdr.source.ready.eq(1),
                If(phy.cmdr.source.status == SDCARD_STREAM_STATUS_TIMEOUT,
                   NextValue(cmd_timeout, 1), NextState("IDLE")).Elif(
                       phy.cmdr.source.last,
                       If(data_type == SDCARD_CTRL_DATA_TRANSFER_WRITE,
                          NextState("DATA-WRITE")).Elif(
                              data_type == SDCARD_CTRL_DATA_TRANSFER_READ,
                              NextState("DATA-READ")).Else(NextState("IDLE")),
                   ).Else(
                       NextValue(response, Cat(phy.cmdr.source.data,
                                               response)))))
        fsm.act(
            "DATA-WRITE", crc16_inserter.source.connect(phy.dataw.sink),
            If(
                phy.dataw.sink.valid & phy.dataw.sink.last
                & phy.dataw.sink.ready, NextValue(data_count, data_count + 1),
                If(data_count == (blockcount - 1), NextState("IDLE"))),
            phy.datar.source.ready.eq(1),
            If(
                phy.datar.source.valid,
                If(
                    phy.datar.source.status
                    != SDCARD_STREAM_STATUS_DATAACCEPTED,
                    NextValue(data_error, 1))))
        fsm.act(
            "DATA-READ", phy.datar.sink.valid.eq(1),
            phy.datar.sink.last.eq(data_count == (blockcount - 1)),
            phy.datar.source.ready.eq(1),
            If(
                phy.datar.source.valid,
                If(
                    phy.datar.source.status == SDCARD_STREAM_STATUS_OK,
                    phy.datar.source.connect(crc16_checker.sink,
                                             omit={"status"}),
                    If(phy.datar.source.last & phy.datar.source.ready,
                       NextValue(data_count, data_count + 1),
                       If(data_count == (blockcount - 1),
                          NextState("IDLE")))).Elif(
                              phy.datar.source.status ==
                              SDCARD_STREAM_STATUS_TIMEOUT,
                              NextValue(data_timeout, 1),
                              NextValue(data_count,
                                        0), phy.datar.source.ready.eq(1),
                              NextState("IDLE"))))
Пример #26
0
    def __init__(self, phy):
        self.sink = stream.Endpoint([("data", 32)])
        self.source = stream.Endpoint([("data", 32)])

        self.argument = CSRStorage(32)
        self.command = CSRStorage(32)
        self.response = CSRStatus(120)

        self.cmdevt = CSRStatus(32)
        self.dataevt = CSRStatus(32)

        self.blocksize = CSRStorage(16)
        self.blockcount = CSRStorage(32)

        self.datatimeout = CSRStorage(32, reset=2**16)
        self.cmdtimeout = CSRStorage(32, reset=2**16)

        self.datawcrcclear = CSRStorage()
        self.datawcrcvalids = CSRStatus(32)
        self.datawcrcerrors = CSRStatus(32)

        # # #

        argument = Signal(32)
        command = Signal(32)
        response = Signal(120)
        cmdevt = Signal(32)
        dataevt = Signal(32)
        blocksize = Signal(16)
        blockcount = Signal(32)
        datatimeout = Signal(32)
        cmdtimeout = Signal(32)

        # sys to sd cdc
        self.specials += [
            MultiReg(self.argument.storage, argument, "sd"),
            MultiReg(self.command.storage, command, "sd"),
            MultiReg(self.blocksize.storage, blocksize, "sd"),
            MultiReg(self.blockcount.storage, blockcount, "sd"),
            MultiReg(self.datatimeout.storage, datatimeout, "sd"),
            MultiReg(self.cmdtimeout.storage, cmdtimeout, "sd")
        ]

        # sd to sys cdc
        response_cdc = BusSynchronizer(120, "sd", "sys")
        cmdevt_cdc = BusSynchronizer(32, "sd", "sys")
        dataevt_cdc = BusSynchronizer(32, "sd", "sys")
        self.submodules += response_cdc, cmdevt_cdc, dataevt_cdc
        self.comb += [
            response_cdc.i.eq(response),
            self.response.status.eq(response_cdc.o),
            cmdevt_cdc.i.eq(cmdevt),
            self.cmdevt.status.eq(cmdevt_cdc.o),
            dataevt_cdc.i.eq(dataevt),
            self.dataevt.status.eq(dataevt_cdc.o)
        ]

        self.submodules.new_command = PulseSynchronizer("sys", "sd")
        self.comb += self.new_command.i.eq(self.command.re)

        self.comb += [
            phy.cfg.blocksize.eq(blocksize),
            phy.cfg.datatimeout.eq(datatimeout),
            phy.cfg.cmdtimeout.eq(cmdtimeout),
            phy.dataw.crc_clear.eq(self.datawcrcclear.storage),
            self.datawcrcvalids.status.eq(phy.dataw.crc_valids),
            self.datawcrcerrors.status.eq(phy.dataw.crc_errors)
        ]

        self.submodules.crc7inserter = ClockDomainsRenamer("sd")(CRC(9, 7, 40))
        self.submodules.crc7checker = ClockDomainsRenamer("sd")(CRCChecker(
            9, 7, 120))
        self.submodules.crc16inserter = ClockDomainsRenamer("sd")(
            CRCUpstreamInserter())
        self.submodules.crc16checker = ClockDomainsRenamer("sd")(
            CRCDownstreamChecker())

        self.submodules.upstream_cdc = ClockDomainsRenamer({
            "write": "sys",
            "read": "sd"
        })(stream.AsyncFIFO(self.sink.description, 4))
        self.submodules.downstream_cdc = ClockDomainsRenamer({
            "write": "sd",
            "read": "sys"
        })(stream.AsyncFIFO(self.source.description, 4))

        self.submodules.upstream_converter = ClockDomainsRenamer("sd")(
            stream.StrideConverter([('data', 32)], [('data', 8)],
                                   reverse=True))
        self.submodules.downstream_converter = ClockDomainsRenamer("sd")(
            stream.StrideConverter([('data', 8)], [('data', 32)],
                                   reverse=True))

        self.comb += [
            self.sink.connect(self.upstream_cdc.sink),
            self.upstream_cdc.source.connect(self.upstream_converter.sink),
            self.upstream_converter.source.connect(self.crc16inserter.sink),
            self.crc16checker.source.connect(self.downstream_converter.sink),
            self.downstream_converter.source.connect(self.downstream_cdc.sink),
            self.downstream_cdc.source.connect(self.source)
        ]

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

        csel = Signal(max=6)
        waitresp = Signal(2)
        dataxfer = Signal(2)
        cmddone = Signal(reset=1)
        datadone = Signal(reset=1)
        blkcnt = Signal(32)
        pos = Signal(2)

        cerrtimeout = Signal()
        cerrcrc_en = Signal()
        derrtimeout = Signal()
        derrwrite = Signal()
        derrread_en = Signal()

        self.comb += [
            waitresp.eq(command[0:2]),
            dataxfer.eq(command[5:7]),
            cmdevt.eq(
                Cat(cmddone, C(0, 1), cerrtimeout,
                    cerrcrc_en & ~self.crc7checker.valid)),
            dataevt.eq(
                Cat(datadone, derrwrite, derrtimeout,
                    derrread_en & ~self.crc16checker.valid)),
            self.crc7inserter.val.eq(Cat(argument, command[8:14], 1, 0)),
            self.crc7inserter.clr.eq(1),
            self.crc7inserter.enable.eq(1),
            self.crc7checker.val.eq(response)
        ]

        ccases = {}  # To send command and CRC
        ccases[0] = phy.sink.data.eq(Cat(command[8:14], 1, 0))
        for i in range(4):
            ccases[i + 1] = phy.sink.data.eq(argument[24 - 8 * i:32 - 8 * i])
        ccases[5] = [
            phy.sink.data.eq(Cat(1, self.crc7inserter.crc)),
            phy.sink.last.eq(waitresp == SDCARD_CTRL_RESPONSE_NONE)
        ]

        fsm.act(
            "IDLE", NextValue(pos, 0),
            If(self.new_command.o, NextValue(cmddone, 0),
               NextValue(cerrtimeout, 0), NextValue(cerrcrc_en, 0),
               NextValue(datadone, 0), NextValue(derrtimeout, 0),
               NextValue(derrwrite, 0), NextValue(derrread_en, 0),
               NextValue(response, 0), NextState("SEND_CMD")))

        fsm.act(
            "SEND_CMD", phy.sink.valid.eq(1), phy.sink.cmd_data_n.eq(1),
            phy.sink.rd_wr_n.eq(0), Case(csel, ccases),
            If(
                phy.sink.valid & phy.sink.ready,
                If(csel < 5, NextValue(csel, csel + 1)).Else(
                    NextValue(csel, 0),
                    If(waitresp == SDCARD_CTRL_RESPONSE_NONE,
                       NextValue(cmddone, 1),
                       NextState("IDLE")).Else(NextValue(cerrcrc_en, 1),
                                               NextState("RECV_RESP")))))

        fsm.act(
            "RECV_RESP",
            phy.sink.valid.eq(1),
            phy.sink.cmd_data_n.eq(1),
            phy.sink.rd_wr_n.eq(1),
            phy.sink.last.eq(dataxfer == SDCARD_CTRL_DATA_TRANSFER_NONE),
            If(
                waitresp == SDCARD_CTRL_RESPONSE_SHORT,
                phy.sink.data.eq(5)  # (5+1)*8 == 48bits
            ).Elif(
                waitresp == SDCARD_CTRL_RESPONSE_LONG,
                phy.sink.data.eq(16)  # (16+1)*8 == 136bits
            ),
            If(
                phy.source.valid,  # Wait for resp or timeout coming from phy
                phy.source.ready.eq(1),
                If(phy.source.status == SDCARD_STREAM_STATUS_TIMEOUT,
                   NextValue(cerrtimeout, 1), NextValue(cmddone, 1),
                   NextValue(datadone, 1), NextState("IDLE")).Elif(
                       phy.source.last,
                       # Check response CRC
                       NextValue(self.crc7checker.check, phy.source.data[1:8]),
                       NextValue(cmddone, 1),
                       If(dataxfer == SDCARD_CTRL_DATA_TRANSFER_READ,
                          NextValue(derrread_en, 1),
                          NextState("RECV_DATA")).Elif(
                              dataxfer == SDCARD_CTRL_DATA_TRANSFER_WRITE,
                              NextState("SEND_DATA")).Else(
                                  NextValue(datadone, 1), NextState("IDLE")),
                   ).Else(
                       NextValue(response, Cat(phy.source.data,
                                               response[0:112])))))

        fsm.act(
            "RECV_DATA",
            phy.sink.valid.eq(1),
            phy.sink.cmd_data_n.eq(0),
            phy.sink.rd_wr_n.eq(1),
            phy.sink.last.eq(blkcnt == (blockcount - 1)),
            phy.sink.data.eq(0),  # Read 1 block
            If(
                phy.source.valid,
                phy.source.ready.eq(1),
                If(
                    phy.source.status == SDCARD_STREAM_STATUS_OK,
                    self.crc16checker.sink.data.eq(
                        phy.source.data),  # Manual connect streams except ctrl
                    self.crc16checker.sink.valid.eq(phy.source.valid),
                    self.crc16checker.sink.last.eq(phy.source.last),
                    phy.source.ready.eq(self.crc16checker.sink.ready),
                    If(
                        phy.source.last & phy.source.ready,  # End of block
                        If(blkcnt < (blockcount - 1),
                           NextValue(blkcnt,
                                     blkcnt + 1), NextState("RECV_DATA")).Else(
                                         NextValue(blkcnt, 0),
                                         NextValue(datadone, 1),
                                         NextState("IDLE")))).Elif(
                                             phy.source.status ==
                                             SDCARD_STREAM_STATUS_TIMEOUT,
                                             NextValue(derrtimeout, 1),
                                             NextValue(blkcnt, 0),
                                             NextValue(datadone, 1),
                                             phy.source.ready.eq(1),
                                             NextState("IDLE"))))

        fsm.act(
            "SEND_DATA", phy.sink.valid.eq(self.crc16inserter.source.valid),
            phy.sink.cmd_data_n.eq(0), phy.sink.rd_wr_n.eq(0),
            phy.sink.last.eq(self.crc16inserter.source.last),
            phy.sink.data.eq(self.crc16inserter.source.data),
            self.crc16inserter.source.ready.eq(phy.sink.ready),
            If(
                self.crc16inserter.source.valid
                & self.crc16inserter.source.last
                & self.crc16inserter.source.ready,
                If(blkcnt < (blockcount - 1),
                   NextValue(blkcnt, blkcnt + 1)).Else(NextValue(blkcnt, 0),
                                                       NextValue(datadone, 1),
                                                       NextState("IDLE"))),
            If(
                phy.source.valid, phy.source.ready.eq(1),
                If(phy.source.status != SDCARD_STREAM_STATUS_DATAACCEPTED,
                   NextValue(derrwrite, 1))))
Пример #27
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))
        ]
    def __init__(self, cfg):
        self.pads = pads = _sdpads()
        self.sink = sink = stream.Endpoint([("data", 8)])
        self.source = source = stream.Endpoint([("data", 8), ("status", 3)])

        # # #

        cmdrfb_reset = Signal()

        self.submodules.cmdrfb = SDPHYRFB(pads.cmd.i, False)
        self.submodules.fifo = ClockDomainsRenamer({"write": "sd_fb", "read": "sd"})(
            stream.AsyncFIFO(self.cmdrfb.source.description, 4)
        )
        self.comb += self.cmdrfb.source.connect(self.fifo.sink)

        ctimeout = Signal(32)

        cread = Signal(10)
        ctoread = Signal(10)
        cnt = Signal(8)

        self.submodules.fsm = fsm = ClockDomainsRenamer("sd")(FSM(reset_state="IDLE"))

        fsm.act("IDLE",
            If(sink.valid,
                NextValue(ctimeout, 0),
                NextValue(cread, 0),
                NextValue(ctoread, sink.data),
                NextState("CMD_READSTART")
            ).Else(
                cmdrfb_reset.eq(1),
                self.fifo.source.ready.eq(1),
            )
        )
        self.specials += MultiReg(cmdrfb_reset, self.cmdrfb.reset, "sd_fb")

        fsm.act("CMD_READSTART",
            pads.cmd.oe.eq(0),
            pads.clk.eq(1),
            NextValue(ctimeout, ctimeout + 1),
            If(self.fifo.source.valid,
                NextState("CMD_READ")
            ).Elif(ctimeout > cfg.cmdtimeout,
                NextState("TIMEOUT")
            )
        )

        fsm.act("CMD_READ",
            pads.cmd.oe.eq(0),
            pads.clk.eq(1),
            source.valid.eq(self.fifo.source.valid),
            source.data.eq(self.fifo.source.data),
            source.status.eq(SDCARD_STREAM_STATUS_OK),
            source.last.eq(cread == ctoread),
            self.fifo.source.ready.eq(source.ready),
            If(source.valid & source.ready,
                NextValue(cread, cread + 1),
                If(cread == ctoread,
                    If(sink.last,
                        NextState("CMD_CLK8")
                    ).Else(
                        sink.ready.eq(1),
                        NextState("IDLE")
                    )
                )
            )
        )

        fsm.act("CMD_CLK8",
            If(cnt < 7,
                NextValue(cnt, cnt + 1),
                pads.clk.eq(1)
            ).Else(
                NextValue(cnt, 0),
                sink.ready.eq(1),
                NextState("IDLE")
            )
        )

        fsm.act("TIMEOUT",
            source.valid.eq(1),
            source.data.eq(0),
            source.status.eq(SDCARD_STREAM_STATUS_TIMEOUT),
            source.last.eq(1),
            If(source.valid & source.ready,
                sink.ready.eq(1),
                NextState("IDLE")
            )
        )
Пример #29
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))))
Пример #30
0
    def __init__(self, data_width, depth):
        self.sink = sink = stream.Endpoint(core_layout(data_width))

        self.enable = CSRStorage()
        self.done = CSRStatus()

        self.length = CSRStorage(bits_for(depth))
        self.offset = CSRStorage(bits_for(depth))

        self.mem_valid = CSRStatus()
        self.mem_ready = CSR()
        self.mem_data = CSRStatus(data_width)

        # # #

        # control re-synchronization
        enable = Signal()
        enable_d = Signal()

        enable = Signal()
        enable_d = Signal()
        self.specials += MultiReg(self.enable.storage, enable, "scope")
        self.sync.scope += enable_d.eq(enable)

        length = Signal(max=depth)
        offset = Signal(max=depth)
        self.specials += [
            MultiReg(self.length.storage, length, "scope"),
            MultiReg(self.offset.storage, offset, "scope")
        ]

        # status re-synchronization
        done = Signal()
        self.specials += MultiReg(done, self.done.status)

        # memory
        mem = stream.SyncFIFO([("data", data_width)], depth, buffered=True)
        mem = ClockDomainsRenamer("scope")(mem)
        cdc = stream.AsyncFIFO([("data", data_width)], 4)
        cdc = ClockDomainsRenamer({"write": "scope", "read": "sys"})(cdc)
        self.submodules += mem, cdc

        # flush
        mem_flush = WaitTimer(depth)
        mem_flush = ClockDomainsRenamer("scope")(mem_flush)
        self.submodules += mem_flush

        # fsm
        fsm = FSM(reset_state="IDLE")
        fsm = ClockDomainsRenamer("scope")(fsm)
        self.submodules += fsm
        fsm.act("IDLE", done.eq(1), If(enable & ~enable_d, NextState("FLUSH")),
                sink.ready.eq(1), mem.source.connect(cdc.sink))
        fsm.act("FLUSH", sink.ready.eq(1), mem_flush.wait.eq(1),
                mem.source.ready.eq(1), If(mem_flush.done, NextState("WAIT")))
        fsm.act("WAIT", sink.connect(mem.sink, omit={"hit"}),
                If(sink.valid & sink.hit, NextState("RUN")),
                mem.source.ready.eq(mem.level >= self.offset.storage))
        fsm.act("RUN", sink.connect(mem.sink, omit={"hit"}),
                If(
                    mem.level >= self.length.storage,
                    NextState("IDLE"),
                ))

        # memory read
        self.comb += [
            self.mem_valid.status.eq(cdc.source.valid),
            cdc.source.ready.eq(self.mem_ready.re | ~self.enable.storage),
            self.mem_data.status.eq(cdc.source.data)
        ]