Ejemplo n.º 1
0
    def __init__(self, dram_port, fifo_depth=512):
        self.sink = sink = stream.Endpoint(frame_dma_layout)
        self.source = source = stream.Endpoint([("data", dram_port.dw)])

        # # #

        self.submodules.dma = LiteDRAMDMAReader(dram_port, fifo_depth, True)
        self.submodules.fsm = fsm = FSM(reset_state="IDLE")

        shift = log2_int(dram_port.dw // 8)
        base = Signal(dram_port.aw)
        length = Signal(dram_port.aw)
        offset = Signal(dram_port.aw)
        self.comb += [
            base.eq(sink.base[shift:]),
            length.eq(sink.length[shift:])
        ]

        fsm.act(
            "IDLE", NextValue(offset, 0),
            If(sink.valid, NextState("READ")).Else(dram_port.flush.eq(1), ))
        fsm.act(
            "READ", self.dma.sink.valid.eq(1),
            If(
                self.dma.sink.ready, NextValue(offset, offset + 1),
                If(offset == (length - 1), self.sink.ready.eq(1),
                   NextState("IDLE"))))
        self.comb += [
            self.dma.sink.address.eq(base + offset),
            self.dma.source.connect(self.source)
        ]
Ejemplo n.º 2
0
    def __init__(self, dram_port, hres=800, vres=600, base=0x00000000, fifo_depth=65536, clock_domain="sys", clock_faster_than_sys=False):
        self.vtg_sink  = vtg_sink = stream.Endpoint(video_timing_layout)
        self.source    = source   = stream.Endpoint(video_data_layout)
        self.underflow = Signal()

        # # #

        # Video DMA.
        from litedram.frontend.dma import LiteDRAMDMAReader
        self.submodules.dma = LiteDRAMDMAReader(dram_port, fifo_depth=fifo_depth//(dram_port.data_width//8), fifo_buffered=True)
        self.dma.add_csr(
            default_base   = base,
            default_length = hres*vres*32//8, # 32-bit RGB-444
            default_enable = 0,
            default_loop   = 1
        )

        # If DRAM Data Width > 32-bit and Video clock is faster than sys_clk:
        if (dram_port.data_width > 32) and clock_faster_than_sys:
            # Do Clock Domain Crossing first...
            self.submodules.cdc = stream.ClockDomainCrossing([("data", dram_port.data_width)], cd_from="sys", cd_to=clock_domain)
            self.comb += self.dma.source.connect(self.cdc.sink)
            # ... and then Data-Width Conversion.
            self.submodules.conv = stream.Converter(dram_port.data_width, 32)
            self.comb += self.cdc.source.connect(self.conv.sink)
            video_pipe_source = self.conv.source
        # Elsif DRAM Data Widt < 32-bit or Video clock is slower than sys_clk:
        else:
            # Do Data-Width Conversion first...
            self.submodules.conv = stream.Converter(dram_port.data_width, 32)
            self.comb += self.dma.source.connect(self.conv.sink)
            # ... and then Clock Domain Crossing.
            self.submodules.cdc = stream.ClockDomainCrossing([("data", 32)], cd_from="sys", cd_to=clock_domain)
            self.comb += self.conv.source.connect(self.cdc.sink)
            self.comb += If(dram_port.data_width < 32, # FIXME.
                self.cdc.sink.data[ 0: 8].eq(self.conv.source.data[16:24]),
                self.cdc.sink.data[16:24].eq(self.conv.source.data[ 0: 8]),
            )
            video_pipe_source = self.cdc.source

        # Video Generation.
        self.comb += [
            vtg_sink.ready.eq(1),
            If(vtg_sink.valid & vtg_sink.de,
                video_pipe_source.connect(source, keep={"valid", "ready"}),
                vtg_sink.ready.eq(source.valid & source.ready),

            ),
            vtg_sink.connect(source, keep={"de", "hsync", "vsync"}),
            source.r.eq(video_pipe_source.data[16:24]),
            source.g.eq(video_pipe_source.data[ 8:16]),
            source.b.eq(video_pipe_source.data[ 0: 8]),
        ]

        # Underflow.
        self.comb += self.underflow.eq(~source.valid)
Ejemplo n.º 3
0
    def __init__(self, dram_port, random):
        ashift = log2_int(dram_port.dw // 8)
        awidth = dram_port.aw + ashift
        self.start = Signal()
        self.done = Signal()
        self.base = Signal(awidth)
        self.length = Signal(awidth)
        self.ticks = Signal(32)
        self.errors = Signal(32)

        # # #

        gen_cls = LFSR if random else Counter
        gen = gen_cls(min(dram_port.dw, 32))  # FIXME: remove lfsr limitation
        dma = LiteDRAMDMAReader(dram_port)
        self.submodules += dma, gen

        # address
        cmd_counter = Signal(dram_port.aw, reset_less=True)

        cmd_fsm = FSM(reset_state="IDLE")
        self.submodules += cmd_fsm
        cmd_fsm.act(
            "IDLE", If(self.start, NextValue(cmd_counter, 0),
                       NextState("RUN")))
        cmd_fsm.act(
            "RUN", dma.sink.valid.eq(1),
            If(
                dma.sink.ready, NextValue(cmd_counter, cmd_counter + 1),
                If(cmd_counter == (self.length[ashift:] - 1),
                   NextState("DONE"))))
        cmd_fsm.act("DONE")
        self.comb += dma.sink.address.eq(self.base[ashift:] + cmd_counter)

        # data
        data_counter = Signal(dram_port.aw, reset_less=True)

        data_fsm = FSM(reset_state="IDLE")
        self.submodules += data_fsm
        data_fsm.act(
            "IDLE",
            If(self.start, NextValue(data_counter, 0),
               NextValue(self.errors, 0), NextState("RUN")),
            NextValue(self.ticks, 0))
        data_fsm.act(
            "RUN", dma.source.ready.eq(1),
            If(
                dma.source.valid, gen.ce.eq(1),
                NextValue(data_counter, data_counter + 1),
                If(dma.source.data != gen.o,
                   NextValue(self.errors, self.errors + 1)),
                If(data_counter == (self.length[ashift:] - 1),
                   NextState("DONE"))), NextValue(self.ticks, self.ticks + 1))
        data_fsm.act("DONE", self.done.eq(1))
Ejemplo n.º 4
0
    def __init__(self,
                 dram_port,
                 hres=800,
                 vres=600,
                 base=0x00000000,
                 clock_domain="sys"):
        self.vtg_sink = vtg_sink = stream.Endpoint(video_timing_layout)
        self.source = source = stream.Endpoint(video_data_layout)

        # # #

        # Video DMA.
        from litedram.frontend.dma import LiteDRAMDMAReader
        self.submodules.dma = LiteDRAMDMAReader(
            dram_port, fifo_depth=2048,
            fifo_buffered=True)  # FIXME: Adjust/Expose.
        self.dma.add_csr(
            default_base=base,
            default_length=hres * vres * 32 // 8,  # 32-bit RGB-444
            default_enable=0,
            default_loop=1)

        # FIXME: Make sure it will work for all DRAM's data-width/all Video resolutions.

        # Video Data-Width Converter.
        self.submodules.conv = stream.Converter(dram_port.data_width, 32)
        self.comb += self.dma.source.connect(self.conv.sink)

        # Video CDC.
        self.submodules.cdc = stream.ClockDomainCrossing([("data", 32)],
                                                         cd_from="sys",
                                                         cd_to=clock_domain)
        self.comb += self.conv.source.connect(self.cdc.sink)

        # Video Generation.
        self.comb += [
            vtg_sink.ready.eq(1),
            If(
                vtg_sink.valid & vtg_sink.de,
                self.cdc.source.connect(source, keep={"valid", "ready"}),
                vtg_sink.ready.eq(source.valid & source.ready),
            ),
            vtg_sink.connect(source, keep={"de", "hsync", "vsync"}),
            source.r.eq(self.cdc.source.data[16:24]),
            source.g.eq(self.cdc.source.data[8:16]),
            source.b.eq(self.cdc.source.data[0:8]),
        ]
Ejemplo n.º 5
0
    def __init__(self, dram_port):
        self.shoot = CSR()
        self.done = CSRStatus()
        self.base = CSRStorage(32)
        self.length = CSRStorage(32)

        self.source = source = stream.Endpoint([("data", 16)])

        # # #

        self.submodules.dma = dma = LiteDRAMDMAReader(dram_port)

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

        shift = log2_int(dram_port.dw // 8)
        base = Signal(dram_port.aw)
        length = Signal(dram_port.aw)
        offset = Signal(dram_port.aw)
        self.comb += [
            base.eq(self.base.storage[shift:]),
            length.eq(self.length.storage[shift:])
        ]

        fsm.act(
            "IDLE", self.done.status.eq(1),
            If(self.shoot.re & self.shoot.r, NextValue(offset, 0),
               NextState("RUN")))
        fsm.act(
            "RUN", dma.sink.valid.eq(1),
            If(dma.sink.ready, NextValue(offset, offset + 1),
               If(offset == (length - 1), NextState("IDLE"))))
        self.comb += dma.sink.address.eq(base + offset)

        self.submodules.converter = stream.Converter(dram_port.dw,
                                                     16,
                                                     reverse=True)
        self.comb += [
            self.dma.source.connect(self.converter.sink),
            self.converter.source.connect(self.source)
        ]
Ejemplo n.º 6
0
    def __init__(self,
                 platform,
                 with_cpu=True,
                 with_sdram=True,
                 with_etherbone=True,
                 with_pcie=True,
                 with_sdram_dmas=False,
                 with_hdmi_in0=True,
                 with_hdmi_out0=True):
        sys_clk_freq = int(100e6)

        # SoCSDRAM ---------------------------------------------------------------------------------
        SoCSDRAM.__init__(
            self,
            platform,
            sys_clk_freq,
            cpu_type="vexriscv" if with_cpu else None,
            cpu_variant="lite",
            l2_size=128,
            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="NeTV2 LiteX SoC",
            ident_version=True)

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

        # DNA --------------------------------------------------------------------------------------
        self.submodules.dna = DNA()
        self.dna.add_timing_constraints(platform, sys_clk_freq,
                                        self.crg.cd_sys.clk)
        self.add_csr("dna")

        # XADC -------------------------------------------------------------------------------------
        self.submodules.xadc = XADC()
        self.add_csr("xadc")

        # ICAP -------------------------------------------------------------------------------------
        self.submodules.icap = ICAP(platform)
        self.icap.add_timing_constraints(platform, sys_clk_freq,
                                         self.crg.cd_sys.clk)
        self.add_csr("icap")

        # Flash ------------------------------------------------------------------------------------
        self.submodules.flash = S7SPIFlash(platform.request("flash"),
                                           sys_clk_freq, 25e6)
        self.add_csr("flash")

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

        # PCIe -------------------------------------------------------------------------------------
        if with_pcie:
            # PHY ----------------------------------------------------------------------------------
            self.submodules.pcie_phy = S7PCIEPHY(platform,
                                                 platform.request("pcie_x1"),
                                                 data_width=64,
                                                 bar0_size=0x20000)
            platform.add_false_path_constraint(self.crg.cd_sys.clk,
                                               self.pcie_phy.cd_pcie.clk)
            self.add_csr("pcie_phy")

            # Endpoint -----------------------------------------------------------------------------
            self.submodules.pcie_endpoint = LitePCIeEndpoint(self.pcie_phy)

            # Wishbone bridge ----------------------------------------------------------------------
            self.submodules.pcie_bridge = LitePCIeWishboneBridge(
                self.pcie_endpoint, base_address=self.mem_map["csr"])
            self.add_wb_master(self.pcie_bridge.wishbone)

            # DMA0 ---------------------------------------------------------------------------------
            self.submodules.pcie_dma0 = LitePCIeDMA(self.pcie_phy,
                                                    self.pcie_endpoint,
                                                    with_buffering=True,
                                                    buffering_depth=1024,
                                                    with_loopback=True)
            self.add_csr("pcie_dma0")

            # DMA1 ---------------------------------------------------------------------------------
            self.submodules.pcie_dma1 = LitePCIeDMA(self.pcie_phy,
                                                    self.pcie_endpoint,
                                                    with_buffering=True,
                                                    buffering_depth=1024,
                                                    with_loopback=True)
            self.add_csr("pcie_dma1")

            self.add_constant("DMA_CHANNELS", 2)

            # MSI ----------------------------------------------------------------------------------
            self.submodules.pcie_msi = LitePCIeMSI()
            self.add_csr("pcie_msi")
            self.comb += self.pcie_msi.source.connect(self.pcie_phy.msi)
            self.interrupts = {
                "PCIE_DMA0_WRITER": self.pcie_dma0.writer.irq,
                "PCIE_DMA0_READER": self.pcie_dma0.reader.irq,
                "PCIE_DMA1_WRITER": self.pcie_dma1.writer.irq,
                "PCIE_DMA1_READER": self.pcie_dma1.reader.irq,
            }
            for i, (k, v) in enumerate(sorted(self.interrupts.items())):
                self.comb += self.pcie_msi.irqs[i].eq(v)
                self.add_constant(k + "_INTERRUPT", i)

            # FIXME : Dummy counter capture, connect to HDMI In ------------------------------------
            pcie_dma0_counter = Signal(32)
            self.sync += [
                self.pcie_dma0.sink.valid.eq(1),
                If(self.pcie_dma0.sink.ready,
                   pcie_dma0_counter.eq(pcie_dma0_counter + 1)),
                self.pcie_dma0.sink.data.eq(pcie_dma0_counter)
            ]

            pcie_dma1_counter = Signal(32)
            self.sync += [
                self.pcie_dma1.sink.valid.eq(1),
                If(self.pcie_dma1.sink.ready,
                   pcie_dma1_counter.eq(pcie_dma1_counter + 2)),
                self.pcie_dma1.sink.data.eq(pcie_dma1_counter)
            ]

        # SDRAM DMAs -------------------------------------------------------------------------------
        if with_sdram_dmas:
            self.submodules.sdram_reader = LiteDRAMDMAReader(
                self.sdram.crossbar.get_port())
            self.sdram_reader.add_csr()
            self.add_csr("sdram_reader")

            self.submodules.sdram_writer = LiteDRAMDMAReader(
                self.sdram.crossbar.get_port())
            self.sdram_writer.add_csr()
            self.add_csr("sdram_writer")

        # HDMI In 0 --------------------------------------------------------------------------------
        if with_hdmi_in0:
            hdmi_in0_pads = platform.request("hdmi_in", 0)
            self.submodules.hdmi_in0_freq = FreqMeter(period=sys_clk_freq)
            self.add_csr("hdmi_in0_freq")
            self.submodules.hdmi_in0 = HDMIIn(
                pads=hdmi_in0_pads,
                dram_port=self.sdram.crossbar.get_port(mode="write"),
                fifo_depth=512,
                device="xc7",
                split_mmcm=True)
            self.add_csr("hdmi_in0")
            self.add_csr("hdmi_in0_edid_mem")
            self.comb += self.hdmi_in0_freq.clk.eq(
                self.hdmi_in0.clocking.cd_pix.clk),
            platform.add_false_path_constraints(
                self.crg.cd_sys.clk, self.hdmi_in0.clocking.cd_pix.clk,
                self.hdmi_in0.clocking.cd_pix1p25x.clk,
                self.hdmi_in0.clocking.cd_pix5x.clk)
            self.platform.add_period_constraint(
                platform.lookup_request("hdmi_in", 0).clk_p, 1e9 / 74.25e6)

        # HDMI Out 0 -------------------------------------------------------------------------------
        if with_hdmi_out0:
            self.submodules.hdmi_out0 = VideoOut(
                device=platform.device,
                pads=platform.request("hdmi_out", 0),
                dram_port=self.sdram.crossbar.get_port(
                    mode="read",
                    data_width=16,
                    clock_domain="hdmi_out0_pix",
                    reverse=True),
                mode="ycbcr422",
                fifo_depth=512)
            self.add_csr("hdmi_out0")
            platform.add_false_path_constraints(
                self.crg.cd_sys.clk, self.hdmi_out0.driver.clocking.cd_pix.clk,
                self.hdmi_out0.driver.clocking.cd_pix5x.clk)
Ejemplo n.º 7
0
    def __init__(self, dram_port, hres=800, vres=600, base=0x00000000, fifo_depth=65536, clock_domain="sys", clock_faster_than_sys=False, format="rgb888"):
        self.vtg_sink  = vtg_sink = stream.Endpoint(video_timing_layout)
        self.source    = source   = stream.Endpoint(video_data_layout)
        self.underflow = Signal()

        self.depth = depth = {
            "rgb888" : 32,
            "rgb565" : 16
        }[format]

        # # #

        # Video DMA.
        from litedram.frontend.dma import LiteDRAMDMAReader
        self.submodules.dma = LiteDRAMDMAReader(dram_port, fifo_depth=fifo_depth//(dram_port.data_width//8), fifo_buffered=True)
        self.dma.add_csr(
            default_base   = base,
            default_length = hres*vres*depth//8, # 32-bit RGB-888 or 16-bit RGB-565
            default_enable = 0,
            default_loop   = 1
        )

        # If DRAM Data Width > depth and Video clock is faster than sys_clk:
        if (dram_port.data_width > depth) and clock_faster_than_sys:
            # Do Clock Domain Crossing first...
            self.submodules.cdc = stream.ClockDomainCrossing([("data", dram_port.data_width)], cd_from="sys", cd_to=clock_domain)
            self.comb += self.dma.source.connect(self.cdc.sink)
            # ... and then Data-Width Conversion.
            self.submodules.conv = ClockDomainsRenamer(clock_domain)(stream.Converter(dram_port.data_width, depth))
            self.comb += self.cdc.source.connect(self.conv.sink)
            video_pipe_source = self.conv.source
        # Elsif DRAM Data Width <= depth or Video clock is slower than sys_clk:
        else:
            # Do Data-Width Conversion first...
            self.submodules.conv = stream.Converter(dram_port.data_width, depth)
            self.comb += self.dma.source.connect(self.conv.sink)
            # ... and then Clock Domain Crossing.
            self.submodules.cdc = stream.ClockDomainCrossing([("data", depth)], cd_from="sys", cd_to=clock_domain)
            self.comb += self.conv.source.connect(self.cdc.sink)
            if (dram_port.data_width < depth) and (depth == 32): # FIXME.
                self.comb += [
                    self.cdc.sink.data[ 0: 8].eq(self.conv.source.data[16:24]),
                    self.cdc.sink.data[16:24].eq(self.conv.source.data[ 0: 8]),
                ]
            video_pipe_source = self.cdc.source

        # Video Generation.
        self.comb += [
            vtg_sink.ready.eq(1),
            If(vtg_sink.valid & vtg_sink.de,
                video_pipe_source.connect(source, keep={"valid", "ready"}),
                vtg_sink.ready.eq(source.valid & source.ready),

            ),
            vtg_sink.connect(source, keep={"de", "hsync", "vsync"}),
        ]
        if (depth == 32):
            self.comb += [
               source.r.eq(video_pipe_source.data[16:24]),
               source.g.eq(video_pipe_source.data[ 8:16]),
               source.b.eq(video_pipe_source.data[ 0: 8]),
            ]
        else: # depth == 16
            self.comb += [
                source.r.eq(Cat(Signal(3, reset = 0), video_pipe_source.data[ 0: 5])),
                source.g.eq(Cat(Signal(2, reset = 0), video_pipe_source.data[ 5:11])),
                source.b.eq(Cat(Signal(3, reset = 0), video_pipe_source.data[11:16])),
            ]

        # Underflow.
        self.comb += self.underflow.eq(~source.valid)
Ejemplo n.º 8
0
    def __init__(self, dram_port):
        self.reset = CSRStorage()
        self.start = CSRStorage()
        self.done = CSRStatus()

        self.count = CSRStorage(size=32)
        self.r_count = CSRStatus(size=32)
        self.pointer = CSRStatus(size=32)

        self.mem_base = CSRStorage(size=32)
        self.mem_mask = CSRStorage(size=32)
        self.data_mask = CSRStorage(size=32)  # patterns

        # FIXME: Increase fifo depth
        dma = LiteDRAMDMAReader(dram_port, fifo_depth=1, fifo_buffered=False)
        self.submodules += dma

        self.memory_w0 = Memory(32, 1024)
        self.memory_w1 = Memory(32, 1024)
        self.memory_w2 = Memory(32, 1024)
        self.memory_w3 = Memory(32, 1024)
        self.memory_adr = Memory(32, 1024)
        self.specials += self.memory_w0, self.memory_w1, \
                         self.memory_w2, self.memory_w3, \
                         self.memory_adr

        self.autocsr_exclude = 'memory_w0', 'memory_w1', \
                               'memory_w2', 'memory_w3', \
                               'memory_adr'

        w0_port = self.memory_w0.get_port()
        w1_port = self.memory_w1.get_port()
        w2_port = self.memory_w2.get_port()
        w3_port = self.memory_w3.get_port()
        adr_port = self.memory_adr.get_port()
        self.specials += w0_port, w1_port, w2_port, w3_port, adr_port

        cmd_counter = Signal(32)
        self.sync += self.r_count.status.eq(cmd_counter)

        self.comb += [
            w0_port.adr.eq(cmd_counter & self.data_mask.storage),
            w1_port.adr.eq(cmd_counter & self.data_mask.storage),
            w2_port.adr.eq(cmd_counter & self.data_mask.storage),
            w3_port.adr.eq(cmd_counter & self.data_mask.storage),
            adr_port.adr.eq(cmd_counter & self.data_mask.storage),
        ]

        data_pattern = Signal(32 * 4)
        self.comb += [
            dma.sink.address.eq(self.mem_base.storage + adr_port.dat_r +
                                (cmd_counter & self.mem_mask.storage)),
            data_pattern.eq(
                Cat(w0_port.dat_r, w1_port.dat_r, w2_port.dat_r,
                    w3_port.dat_r)),
        ]

        fsm = FSM(reset_state="IDLE")
        self.submodules += fsm
        fsm.act(
            "IDLE",
            If(
                self.start.storage,
                NextValue(cmd_counter, 0),
                NextValue(self.pointer.status, 0xdeadbeef),
                NextState("WAIT"),
            ))
        fsm.act(
            "WAIT",
            If(cmd_counter >= self.count.storage,
               NextState("DONE")).Else(NextState("WR_ADR")))
        fsm.act("WR_ADR", dma.sink.valid.eq(1),
                If(dma.sink.ready, NextState("RD_DATA")))
        fsm.act(
            "RD_DATA", dma.source.ready.eq(1),
            If(
                dma.source.valid, NextValue(cmd_counter, cmd_counter + 1),
                If(dma.source.data != data_pattern,
                   NextValue(self.pointer.status, cmd_counter)),
                NextState("WAIT")))
        fsm.act("DONE", self.done.status.eq(1),
                If(self.reset.storage, NextState("IDLE")))
Ejemplo n.º 9
0
    def __init__(self,
                 toolchain="vivado",
                 sys_clk_freq=int(100e6),
                 args=None,
                 ip_address="192.168.100.50",
                 mac_address=0x10e2d5000001,
                 udp_port=1234,
                 **kwargs):
        if not args.sim:
            platform = arty.Platform(toolchain=toolchain)
        else:
            platform = Platform()

        # SoCCore ----------------------------------------------------------------------------------
        SoCCore.__init__(self,
                         platform,
                         sys_clk_freq,
                         ident="LiteX SoC on Arty A7",
                         ident_version=True,
                         **kwargs)

        # CRG --------------------------------------------------------------------------------------
        if not args.sim:
            self.submodules.crg = _CRG(platform, sys_clk_freq, args)
        else:
            self.submodules.crg = CRG(platform.request("sys_clk"))

        # DDR3 SDRAM -------------------------------------------------------------------------------
        if not args.sim:
            self.submodules.ddrphy = s7ddrphy.A7DDRPHY(
                platform.request("ddram"),
                memtype="DDR3",
                nphases=4,
                sys_clk_freq=sys_clk_freq)
        else:
            from litedram.gen import get_dram_ios
            core_config = dict()
            core_config["sdram_module_nb"] = 2  # Number of byte groups
            core_config["sdram_rank_nb"] = 1  # Number of ranks
            core_config['sdram_module'] = getattr(litedram_modules,
                                                  'MT41K128M16')
            core_config["memtype"] = "DDR3"  # DRAM type

            platform.add_extension(get_dram_ios(core_config))
            sdram_module = core_config["sdram_module"](
                sys_clk_freq,
                rate={
                    "DDR2": "1:2",
                    "DDR3": "1:4",
                    "DDR4": "1:4"
                }[core_config["memtype"]])

            from litex.tools.litex_sim import get_sdram_phy_settings
            sdram_clk_freq = int(100e6)  # FIXME: use 100MHz timings
            phy_settings = get_sdram_phy_settings(
                memtype=sdram_module.memtype,
                data_width=core_config["sdram_module_nb"] * 8,
                clk_freq=sdram_clk_freq)

            self.submodules.ddrphy = SDRAMPHYModel(
                module=sdram_module,
                settings=phy_settings,
                clk_freq=sdram_clk_freq,
                verbosity=3,
            )

        class ControllerDynamicSettings(Module, AutoCSR, AutoDoc):
            """Allows to change LiteDRAMController behaviour at runtime"""
            def __init__(self):
                self.refresh = CSRStorage(
                    reset=1,
                    description="Enable/disable Refresh commands sending")

        self.submodules.controller_settings = ControllerDynamicSettings()
        self.add_csr("controller_settings")
        controller_settings = ControllerSettings()
        controller_settings.with_auto_precharge = True
        controller_settings.with_refresh = self.controller_settings.refresh.storage

        self.add_csr("ddrphy")
        self.add_sdram(
            "sdram",
            phy=self.ddrphy,
            module=MT41K128M16(sys_clk_freq, "1:4"),
            origin=self.mem_map["main_ram"],
            size=kwargs.get("max_sdram_size", 0x40000000),
            l2_cache_size=0,
            l2_cache_min_data_width=0,  #128
            l2_cache_reverse=True,
            controller_settings=controller_settings)

        # Ethernet / Etherbone ---------------------------------------------------------------------
        if not args.sim:
            # Ethernet PHY (arty)
            self.submodules.ethphy = LiteEthPHYMII(
                clock_pads=self.platform.request("eth_clocks"),
                pads=self.platform.request("eth"))
            self.add_csr("ethphy")

            self.add_etherbone(phy=self.ethphy,
                               ip_address=ip_address,
                               mac_address=mac_address,
                               udp_port=udp_port)
        else:
            # Ethernet PHY (simulation)
            self.submodules.ethphy = LiteEthPHYModel(
                self.platform.request("eth", 0))  # FIXME
            self.add_csr("ethphy")

            # Ethernet Core
            ethcore = LiteEthUDPIPCore(self.ethphy,
                                       ip_address=ip_address,
                                       mac_address=mac_address,
                                       clk_freq=sys_clk_freq)
            self.submodules.ethcore = ethcore
            # Etherbone
            self.submodules.etherbone = LiteEthEtherbone(self.ethcore.udp,
                                                         udp_port,
                                                         mode="master")
            self.add_wb_master(self.etherbone.wishbone.bus)

        # Leds -------------------------------------------------------------------------------------
        self.submodules.leds = LedChaser(pads=platform.request_all("user_led"),
                                         sys_clk_freq=sys_clk_freq)
        self.add_csr("leds")

        # Analyzer ---------------------------------------------------------------------------------
        # analyzer_signals = [
        #    self.bus.masters['master0'].stb,
        #    self.bus.masters['master0'].cyc,
        #    self.bus.masters['master0'].adr,
        #    self.bus.masters['master0'].we,
        #    self.bus.masters['master0'].ack,
        #    self.bus.masters['master0'].sel,
        #    self.bus.masters['master0'].dat_w,
        #    self.bus.masters['master0'].dat_r,
        # ]
        # from litescope import LiteScopeAnalyzer
        # self.submodules.analyzer = LiteScopeAnalyzer(analyzer_signals,
        #    depth        = 512,
        #    clock_domain = "sys",
        #    csr_csv      = "analyzer.csv")
        # self.add_csr("analyzer")

        if args.sim:
            self.comb += platform.trace.eq(1)

        # Rowhammer --------------------------------------------------------------------------------
        from litedram.frontend.dma import LiteDRAMDMAReader, LiteDRAMDMAWriter

        self.submodules.rowhammer_dma = LiteDRAMDMAReader(
            self.sdram.crossbar.get_port())
        self.submodules.rowhammer = RowHammerDMA(self.rowhammer_dma)
        self.add_csr("rowhammer")

        # Bist -------------------------------------------------------------------------------------
        if not args.no_memory_bist:
            from litedram.frontend.bist import LiteDRAMBISTGenerator, LiteDRAMBISTChecker

            def add_xram(self, name, origin, mem):
                from litex.soc.interconnect import wishbone
                from litex.soc.integration.soc import SoCRegion
                ram_bus = wishbone.Interface(data_width=self.bus.data_width)
                ram = wishbone.SRAM(mem, bus=ram_bus)
                self.bus.add_slave(
                    name, ram.bus,
                    SoCRegion(origin=origin,
                              size=mem.width * mem.depth,
                              mode='rw'))
                self.check_if_exists(name)
                self.logger.info("RAM {} {} {}.".format(
                    colorer(name), colorer("added", color="green"),
                    self.bus.regions[name]))
                setattr(self.submodules, name, ram)
                return

            # ------------------------------ writer ------------------------------------
            memory_w0 = Memory(32, 1024)
            memory_w1 = Memory(32, 1024)
            memory_w2 = Memory(32, 1024)
            memory_w3 = Memory(32, 1024)
            memory_adr = Memory(32, 1024)

            add_xram(self, name='pattern_w0', mem=memory_w0, origin=0x20000000)
            add_xram(self, name='pattern_w1', mem=memory_w1, origin=0x21000000)
            add_xram(self, name='pattern_w2', mem=memory_w2, origin=0x22000000)
            add_xram(self, name='pattern_w3', mem=memory_w3, origin=0x23000000)
            add_xram(self,
                     name='pattern_adr',
                     mem=memory_adr,
                     origin=0x24000000)

            class Writer(Module, AutoCSR):
                def __init__(self, dram_port, w0_port, w1_port, w2_port,
                             w3_port, adr_port):
                    self.reset = CSRStorage()
                    self.start = CSRStorage()
                    self.done = CSRStatus()

                    self.count = CSRStorage(size=(32 * 1))

                    self.mem_base = CSRStorage(size=32)
                    self.mem_mask = CSRStorage(size=32)
                    self.data_mask = CSRStorage(size=32)  # patterns

                    dma = LiteDRAMDMAWriter(dram_port, fifo_depth=1)
                    self.submodules += dma

                    cmd_counter = Signal(32)

                    self.comb += [
                        w0_port.adr.eq(cmd_counter & self.data_mask.storage),
                        w1_port.adr.eq(cmd_counter & self.data_mask.storage),
                        w2_port.adr.eq(cmd_counter & self.data_mask.storage),
                        w3_port.adr.eq(cmd_counter & self.data_mask.storage),
                        adr_port.adr.eq(cmd_counter & self.data_mask.storage),
                    ]

                    self.comb += [
                        dma.sink.address.eq(self.mem_base.storage +
                                            adr_port.dat_r +
                                            (cmd_counter
                                             & self.mem_mask.storage)),
                        dma.sink.data.eq(
                            Cat(w0_port.dat_r, w1_port.dat_r, w2_port.dat_r,
                                w3_port.dat_r)),
                    ]

                    fsm = FSM(reset_state="IDLE")
                    self.submodules += fsm
                    fsm.act(
                        "IDLE",
                        If(
                            self.start.storage,
                            NextValue(cmd_counter, 0),
                            NextState("WAIT"),
                        ))
                    fsm.act(
                        "WAIT",
                        If(cmd_counter >= self.count.storage,
                           NextState("DONE")).Else(NextState("RUN")))
                    fsm.act(
                        "RUN", dma.sink.valid.eq(1),
                        If(dma.sink.ready,
                           NextValue(cmd_counter, cmd_counter + 1),
                           NextState("WAIT")))
                    fsm.act("DONE", self.done.status.eq(1),
                            If(self.reset.storage, NextState("IDLE")))

            dram_port = self.sdram.crossbar.get_port()
            w0_port = memory_w0.get_port()
            w1_port = memory_w1.get_port()
            w2_port = memory_w2.get_port()
            w3_port = memory_w3.get_port()
            adr_port = memory_adr.get_port()
            self.specials += w0_port, w1_port, w2_port, w3_port, adr_port
            self.submodules.writer = Writer(dram_port, w0_port, w1_port,
                                            w2_port, w3_port, adr_port)
            self.add_csr('writer')

            # ----------------------------- reader -------------------------------------
            memory_rd_w0 = Memory(32, 1024)
            memory_rd_w1 = Memory(32, 1024)
            memory_rd_w2 = Memory(32, 1024)
            memory_rd_w3 = Memory(32, 1024)
            memory_rd_adr = Memory(32, 1024)

            add_xram(self,
                     name='pattern_rd_w0',
                     mem=memory_rd_w0,
                     origin=0x30000000)
            add_xram(self,
                     name='pattern_rd_w1',
                     mem=memory_rd_w1,
                     origin=0x31000000)
            add_xram(self,
                     name='pattern_rd_w2',
                     mem=memory_rd_w2,
                     origin=0x32000000)
            add_xram(self,
                     name='pattern_rd_w3',
                     mem=memory_rd_w3,
                     origin=0x33000000)
            add_xram(self,
                     name='pattern_rd_adr',
                     mem=memory_rd_adr,
                     origin=0x34000000)

            class Reader(Module, AutoCSR):
                def __init__(self, dram_port, w0_port, w1_port, w2_port,
                             w3_port, adr_port):
                    self.reset = CSRStorage()
                    self.start = CSRStorage()
                    self.done = CSRStatus()

                    self.count = CSRStorage(size=32)
                    self.pointer = CSRStatus(size=32)

                    self.mem_base = CSRStorage(size=32)
                    self.mem_mask = CSRStorage(size=32)
                    self.data_mask = CSRStorage(size=32)  # patterns

                    dma = LiteDRAMDMAReader(dram_port,
                                            fifo_depth=1,
                                            fifo_buffered=False)
                    self.submodules += dma

                    cmd_counter = Signal(32)

                    self.comb += [
                        w0_port.adr.eq(cmd_counter & self.data_mask.storage),
                        w1_port.adr.eq(cmd_counter & self.data_mask.storage),
                        w2_port.adr.eq(cmd_counter & self.data_mask.storage),
                        w3_port.adr.eq(cmd_counter & self.data_mask.storage),
                        adr_port.adr.eq(cmd_counter & self.data_mask.storage),
                    ]

                    data_pattern = Signal(32 * 4)
                    self.comb += [
                        dma.sink.address.eq(self.mem_base.storage +
                                            adr_port.dat_r +
                                            (cmd_counter
                                             & self.mem_mask.storage)),
                        data_pattern.eq(
                            Cat(w0_port.dat_r, w1_port.dat_r, w2_port.dat_r,
                                w3_port.dat_r)),
                    ]

                    fsm = FSM(reset_state="IDLE")
                    self.submodules += fsm
                    fsm.act(
                        "IDLE",
                        If(
                            self.start.storage,
                            NextValue(cmd_counter, 0),
                            NextValue(self.pointer.status, 0xdeadbeef),
                            NextState("WAIT"),
                        ))
                    fsm.act(
                        "WAIT",
                        If(cmd_counter >= self.count.storage,
                           NextState("DONE")).Else(NextState("WR_ADR")))
                    fsm.act("WR_ADR", dma.sink.valid.eq(1),
                            If(dma.sink.ready, NextState("RD_DATA")))
                    fsm.act(
                        "RD_DATA", dma.source.ready.eq(1),
                        If(
                            dma.source.valid,
                            NextValue(cmd_counter, cmd_counter + 1),
                            If(dma.source.data != data_pattern,
                               NextValue(self.pointer.status, cmd_counter)),
                            NextState("WAIT")))
                    fsm.act("DONE", self.done.status.eq(1),
                            If(self.reset.storage, NextState("IDLE")))

            dram_rd_port = self.sdram.crossbar.get_port()
            w0_port = memory_rd_w0.get_port()
            w1_port = memory_rd_w1.get_port()
            w2_port = memory_rd_w2.get_port()
            w3_port = memory_rd_w3.get_port()
            adr_port = memory_rd_adr.get_port()
            self.specials += w0_port, w1_port, w2_port, w3_port, adr_port
            self.submodules.reader = Reader(dram_rd_port, w0_port, w1_port,
                                            w2_port, w3_port, adr_port)
            self.add_csr('reader')
Ejemplo n.º 10
0
    def __init__(self,
                 *,
                 args,
                 sys_clk_freq,
                 sdram_module_cls,
                 sdram_module_speedgrade=None,
                 sdram_module_spd_file=None,
                 ip_address="192.168.100.50",
                 mac_address=0x10e2d5000001,
                 udp_port=1234,
                 **kwargs):
        self.args = args
        self.sys_clk_freq = sys_clk_freq
        self.ip_address = ip_address
        self.mac_address = mac_address
        self.udp_port = udp_port

        # Platform ---------------------------------------------------------------------------------
        if not args.sim:
            self.platform = self.get_platform()
        else:
            self.platform = SimPlatform()

        githash = git.Repo(
            '.', search_parent_directories=True).git.rev_parse("HEAD")

        # SoCCore ----------------------------------------------------------------------------------
        SoCCore.__init__(
            self,
            self.platform,
            sys_clk_freq,
            ident="LiteX Row Hammer Tester SoC on {}, git: {}".format(
                self.platform.device, githash),
            ident_version=True,
            integrated_rom_mode='rw' if args.rw_bios_mem else 'r',
            **kwargs)

        # CRG --------------------------------------------------------------------------------------
        if not args.sim:
            self.submodules.crg = self.get_crg()
        else:
            self.submodules.crg = CRG(self.platform.request('sys_clk'))
            # Add dynamic simulation trace control, start enabled
            self.platform.add_debug(self, reset=1)

        # Leds -------------------------------------------------------------------------------------
        self.submodules.leds = LedChaser(
            pads=self.platform.request_all("user_led"),
            sys_clk_freq=sys_clk_freq)
        self.add_csr("leds")

        # SDRAM PHY --------------------------------------------------------------------------------
        if sdram_module_spd_file is not None:
            self.logger.info('Using DRAM module {} data: {}'.format(
                colorer('SPD'), sdram_module_spd_file))
            with open(sdram_module_spd_file, 'rb') as f:
                spd_data = f.read()
            module = SDRAMModule.from_spd_data(spd_data, self.sys_clk_freq)
        else:
            ratio = self.get_sdram_ratio()
            self.logger.info('Using DRAM module {} ratio {}'.format(
                colorer(sdram_module_cls.__name__), colorer(ratio)))
            module = sdram_module_cls(self.sys_clk_freq,
                                      ratio,
                                      speedgrade=sdram_module_speedgrade)

        if args.sim:
            # Use the hardware platform to retrieve values for simulation
            hw_pads = self.get_platform().request('ddram')
            core_config = dict(
                sdram_module_nb=len(hw_pads.dq) // 8,  # number of byte groups
                sdram_rank_nb=len(hw_pads.cs_n),  # number of ranks
                sdram_module=module,
                memtype=module.memtype,
            )
            # Add IO pins
            self.platform.add_extension(get_dram_ios(core_config))

            phy_settings = get_sdram_phy_settings(
                memtype=module.memtype,
                data_width=core_config["sdram_module_nb"] * 8,
                clk_freq=sys_clk_freq)

            self.submodules.ddrphy = SDRAMPHYModel(
                module=module,
                settings=phy_settings,
                clk_freq=sys_clk_freq,
                verbosity=3,
            )
        else:  # hardware
            self.submodules.ddrphy = self.get_ddrphy()
        self.add_csr("ddrphy")

        # SDRAM Controller--------------------------------------------------------------------------
        class ControllerDynamicSettings(Module, AutoCSR, AutoDoc, ModuleDoc):
            """Allows to change LiteDRAMController behaviour at runtime"""
            def __init__(self):
                self.refresh = CSRStorage(
                    reset=1,
                    description="Enable/disable Refresh commands sending")

        self.submodules.controller_settings = ControllerDynamicSettings()
        self.add_csr("controller_settings")
        controller_settings = ControllerSettings()
        controller_settings.with_auto_precharge = True
        controller_settings.with_refresh = self.controller_settings.refresh.storage
        controller_settings.refresh_cls = SyncableRefresher

        assert self.ddrphy.settings.memtype == module.memtype, \
            'Wrong DRAM module type: {} vs {}'.format(self.ddrphy.settings.memtype, module.memtype)
        self.add_sdram("sdram",
                       phy=self.ddrphy,
                       module=module,
                       origin=self.mem_map["main_ram"],
                       size=kwargs.get("max_sdram_size", 0x40000000),
                       l2_cache_size=0,
                       controller_settings=controller_settings)

        # CPU will report that leveling finished by writing to ddrctrl CSRs
        self.submodules.ddrctrl = LiteDRAMCoreControl()
        self.add_csr("ddrctrl")

        # Ethernet / Etherbone ---------------------------------------------------------------------
        if not args.sim:
            self.add_host_bridge()
        else:  # simulation
            self.submodules.ethphy = LiteEthPHYModel(
                self.platform.request("eth"))
            self.add_csr("ethphy")

            # Ethernet Core
            ethcore = LiteEthUDPIPCore(self.ethphy,
                                       ip_address=self.ip_address,
                                       mac_address=self.mac_address,
                                       clk_freq=self.sys_clk_freq)
            self.submodules.ethcore = ethcore
            # Etherbone
            self.submodules.etherbone = LiteEthEtherbone(self.ethcore.udp,
                                                         self.udp_port,
                                                         mode="master")
            self.add_wb_master(self.etherbone.wishbone.bus)

        # Rowhammer --------------------------------------------------------------------------------
        self.submodules.rowhammer_dma = LiteDRAMDMAReader(
            self.sdram.crossbar.get_port())
        self.submodules.rowhammer = RowHammerDMA(self.rowhammer_dma)
        self.add_csr("rowhammer")

        # Bist -------------------------------------------------------------------------------------
        if not args.no_memory_bist:
            pattern_data_size = int(args.pattern_data_size, 0)
            phy_settings = self.sdram.controller.settings.phy
            pattern_data_width = phy_settings.dfi_databits * phy_settings.nphases
            pattern_length = pattern_data_size // (pattern_data_width // 8)

            assert pattern_data_size % (pattern_data_width//8) == 0, \
                'Pattern data memory size must be multiple of {} bytes'.format(pattern_data_width//8)

            self.submodules.pattern_mem = PatternMemory(
                data_width=pattern_data_width, mem_depth=pattern_length)
            self.add_memory(self.pattern_mem.data,
                            name='pattern_data',
                            origin=0x20000000)
            self.add_memory(self.pattern_mem.addr,
                            name='pattern_addr',
                            origin=0x21000000)
            self.logger.info(
                '{}: Length: {}, Data Width: {}-bit, Address width: {}-bit'.
                format(colorer('BIST pattern'), colorer(pattern_length),
                       colorer(pattern_data_width), colorer(32)))

            assert controller_settings.address_mapping == 'ROW_BANK_COL'
            row_offset = controller_settings.geom.bankbits + controller_settings.geom.colbits
            inversion_kwargs = dict(
                rowbits=int(self.args.bist_inversion_rowbits, 0),
                row_shift=row_offset -
                self.sdram.controller.interface.address_align,
            )

            # Writer
            dram_wr_port = self.sdram.crossbar.get_port()
            self.submodules.writer = Writer(dram_wr_port, self.pattern_mem,
                                            **inversion_kwargs)
            self.writer.add_csrs()
            self.add_csr('writer')

            # Reader
            dram_rd_port = self.sdram.crossbar.get_port()
            self.submodules.reader = Reader(dram_rd_port, self.pattern_mem,
                                            **inversion_kwargs)
            self.reader.add_csrs()
            self.add_csr('reader')

            assert pattern_data_width == dram_wr_port.data_width
            assert pattern_data_width == dram_rd_port.data_width

        # Payload executor -------------------------------------------------------------------------
        if not args.no_payload_executor:
            # TODO: disconnect bus during payload execution
            phy_settings = self.sdram.controller.settings.phy

            scratchpad_width = phy_settings.dfi_databits * phy_settings.nphases
            payload_size = int(args.payload_size, 0)
            scratchpad_size = int(args.scratchpad_size, 0)
            assert payload_size % 4 == 0, 'Payload memory size must be multiple of 4 bytes'
            assert scratchpad_size % (scratchpad_width//8) == 0, \
                'Scratchpad memory size must be multiple of {} bytes'.format(scratchpad_width//8)

            scratchpad_depth = scratchpad_size // (scratchpad_width // 8)
            payload_mem = Memory(32, payload_size // 4)
            scratchpad_mem = Memory(scratchpad_width, scratchpad_depth)
            self.specials += payload_mem, scratchpad_mem

            self.add_memory(payload_mem, name='payload', origin=0x30000000)
            self.add_memory(scratchpad_mem,
                            name='scratchpad',
                            origin=0x31000000,
                            mode='r')
            self.logger.info('{}: Length: {}, Data Width: {}-bit'.format(
                colorer('Instruction payload'), colorer(payload_size // 4),
                colorer(32)))
            self.logger.info('{}: Length: {}, Data Width: {}-bit'.format(
                colorer('Scratchpad memory'), colorer(scratchpad_depth),
                colorer(scratchpad_width)))

            self.submodules.dfi_switch = DFISwitch(
                with_refresh=self.sdram.controller.settings.with_refresh,
                dfii=self.sdram.dfii,
                refresher_reset=self.sdram.controller.refresher.reset,
            )
            self.dfi_switch.add_csrs()
            self.add_csr('dfi_switch')

            self.submodules.payload_executor = PayloadExecutor(
                mem_payload=payload_mem,
                mem_scratchpad=scratchpad_mem,
                dfi_switch=self.dfi_switch,
                nranks=self.sdram.controller.settings.phy.nranks,
                bankbits=self.sdram.controller.settings.geom.bankbits,
                rowbits=self.sdram.controller.settings.geom.rowbits,
                colbits=self.sdram.controller.settings.geom.colbits,
                rdphase=self.sdram.controller.settings.phy.rdphase,
            )
            self.payload_executor.add_csrs()
            self.add_csr('payload_executor')
Ejemplo n.º 11
0
    def __init__(self, mode, dram_port, fifo_depth):
        assert mode == dram_port.mode
        ashift = log2_int(dram_port.dw // 8)
        awidth = dram_port.aw + ashift
        self.cd = dram_port.cd

        # control
        self.enable = Signal(reset=1)  # reset to 1 if not used
        self.start = Signal(reset=1)  # i / reset to 1 if not used
        self.idle = Signal()  # o
        self.slot = Signal()  # o

        # parameters
        self.slot0_base = Signal(awidth)  # in bytes
        self.slot1_base = Signal(awidth)  # in bytes
        self.length = Signal(awidth)  # in bytes

        # stream
        self.endpoint = endpoint = stream.Endpoint([("data", dram_port.dw)])

        # # #

        base = Signal(dram_port.aw)
        length = Signal(dram_port.aw)
        offset = Signal(dram_port.aw)

        # slot selection
        self.comb += \
            If(self.slot,
                base.eq(self.slot1_base[ashift:])
            ).Else(
                base.eq(self.slot0_base[ashift:]))

        # length
        self.comb += length.eq(self.length[ashift:])

        # dma
        if mode == "write":
            # dma
            self.submodules.dma = dma = ResetInserter()(LiteDRAMDMAWriter(
                dram_port, fifo_depth, True))
            # data
            self.comb += dma.sink.data.eq(endpoint.data)
        elif mode == "read":
            # dma
            self.submodules.dma = dma = ResetInserter()(LiteDRAMDMAReader(
                dram_port, fifo_depth, True))
            # data
            self.comb += [
                endpoint.valid.eq(dma.source.valid),
                dma.source.ready.eq(endpoint.ready),
                endpoint.data.eq(dma.source.data)
            ]

        # control
        self.submodules.fsm = fsm = FSM(reset_state="IDLE")
        fsm.act(
            "IDLE", self.idle.eq(1),
            If(self.enable & self.start, NextValue(offset, 0),
               NextState("RUN")))
        fsm.act(
            "RUN",
            If(
                mode == "write",
                dma.sink.valid.eq(endpoint.valid),
                endpoint.ready.eq(dma.sink.ready),
            ).Elif(
                mode == "read",
                dma.sink.valid.eq(1),
            ),
            If(~self.enable, dma.reset.eq(1), dram_port.flush.eq(1),
               NextState("IDLE")).Elif(
                   dma.sink.valid & dma.sink.ready,
                   NextValue(offset, offset + 1),
                   If(offset == (length - 1), NextValue(offset, 0),
                      NextValue(self.slot, ~self.slot))))
        self.comb += dma.sink.address.eq(base + offset)
Ejemplo n.º 12
0
    def __init__(self,
                 toolchain="vivado",
                 sys_clk_freq=int(100e6),
                 args=None,
                 ip_address="192.168.100.50",
                 mac_address=0x10e2d5000001,
                 udp_port=1234,
                 **kwargs):
        if not args.sim:
            platform = arty.Platform(toolchain=toolchain)
        else:
            platform = SimPlatform("SIM", _io)

        # SoCCore ----------------------------------------------------------------------------------
        SoCCore.__init__(self,
                         platform,
                         sys_clk_freq,
                         ident="LiteX SoC on Arty A7",
                         ident_version=True,
                         **kwargs)

        # CRG --------------------------------------------------------------------------------------
        if not args.sim:
            self.submodules.crg = _CRG(platform, sys_clk_freq, args)
        else:
            self.submodules.crg = CRG(platform.request("sys_clk"))

        # DDR3 SDRAM -------------------------------------------------------------------------------
        if not args.sim:
            self.submodules.ddrphy = s7ddrphy.A7DDRPHY(
                platform.request("ddram"),
                memtype="DDR3",
                nphases=4,
                sys_clk_freq=sys_clk_freq)
        else:
            from litedram.gen import get_dram_ios
            core_config = dict()
            core_config["sdram_module_nb"] = 2  # Number of byte groups
            core_config["sdram_rank_nb"] = 1  # Number of ranks
            core_config['sdram_module'] = getattr(litedram_modules,
                                                  'MT41K128M16')
            core_config["memtype"] = "DDR3"  # DRAM type

            platform.add_extension(get_dram_ios(core_config))
            sdram_module = core_config["sdram_module"](
                sys_clk_freq,
                rate={
                    "DDR2": "1:2",
                    "DDR3": "1:4",
                    "DDR4": "1:4"
                }[core_config["memtype"]])

            from litex.tools.litex_sim import get_sdram_phy_settings
            sdram_clk_freq = int(100e6)  # FIXME: use 100MHz timings
            phy_settings = get_sdram_phy_settings(
                memtype=sdram_module.memtype,
                data_width=core_config["sdram_module_nb"] * 8,
                clk_freq=sdram_clk_freq)

            self.submodules.ddrphy = SDRAMPHYModel(
                module=sdram_module,
                settings=phy_settings,
                clk_freq=sdram_clk_freq,
                verbosity=3,
            )

        class ControllerDynamicSettings(Module, AutoCSR, AutoDoc):
            """Allows to change LiteDRAMController behaviour at runtime"""
            def __init__(self):
                self.refresh = CSRStorage(
                    reset=1,
                    description="Enable/disable Refresh commands sending")

        self.submodules.controller_settings = ControllerDynamicSettings()
        self.add_csr("controller_settings")
        controller_settings = ControllerSettings()
        controller_settings.with_auto_precharge = True
        controller_settings.with_refresh = self.controller_settings.refresh.storage

        self.add_csr("ddrphy")
        self.add_sdram(
            "sdram",
            phy=self.ddrphy,
            module=MT41K128M16(sys_clk_freq, "1:4"),
            origin=self.mem_map["main_ram"],
            size=kwargs.get("max_sdram_size", 0x40000000),
            l2_cache_size=0,
            l2_cache_min_data_width=0,  #128
            l2_cache_reverse=True,
            controller_settings=controller_settings)

        # Ethernet / Etherbone ---------------------------------------------------------------------
        if not args.sim:
            # Ethernet PHY (arty)
            self.submodules.ethphy = LiteEthPHYMII(
                clock_pads=self.platform.request("eth_clocks"),
                pads=self.platform.request("eth"))
            self.add_csr("ethphy")

            self.add_etherbone(phy=self.ethphy,
                               ip_address=ip_address,
                               mac_address=mac_address,
                               udp_port=udp_port)
        else:
            # Ethernet PHY (simulation)
            self.submodules.ethphy = LiteEthPHYModel(
                self.platform.request("eth", 0))  # FIXME
            self.add_csr("ethphy")

            # Ethernet Core
            ethcore = LiteEthUDPIPCore(self.ethphy,
                                       ip_address=ip_address,
                                       mac_address=mac_address,
                                       clk_freq=sys_clk_freq)
            self.submodules.ethcore = ethcore
            # Etherbone
            self.submodules.etherbone = LiteEthEtherbone(self.ethcore.udp,
                                                         udp_port,
                                                         mode="master")
            self.add_wb_master(self.etherbone.wishbone.bus)

        # Leds -------------------------------------------------------------------------------------
        self.submodules.leds = LedChaser(pads=platform.request_all("user_led"),
                                         sys_clk_freq=sys_clk_freq)
        self.add_csr("leds")

        if args.sim:
            self.comb += platform.trace.eq(1)

        # Rowhammer --------------------------------------------------------------------------------
        self.submodules.rowhammer_dma = LiteDRAMDMAReader(
            self.sdram.crossbar.get_port())
        self.submodules.rowhammer = RowHammerDMA(self.rowhammer_dma)
        self.add_csr("rowhammer")

        def add_xram(self, name, origin, mem, mode='rw'):
            from litex.soc.interconnect import wishbone
            from litex.soc.integration.soc import SoCRegion
            ram = wishbone.SRAM(mem,
                                bus=wishbone.Interface(data_width=mem.width),
                                read_only='w' not in mode)
            ram_bus = wishbone.Interface(data_width=self.bus.data_width)
            self.submodules += wishbone.Converter(ram_bus, ram.bus)
            region = SoCRegion(origin=origin,
                               size=mem.width // 8 * mem.depth,
                               mode=mode)
            self.bus.add_slave(name, ram_bus, region)
            self.check_if_exists(name)
            self.logger.info("RAM {} {} {}.".format(
                colorer(name), colorer("added", color="green"),
                self.bus.regions[name]))
            setattr(self.submodules, name, ram)

        # Bist -------------------------------------------------------------------------------------
        if not args.no_memory_bist:
            # ------------------------------ writer ------------------------------------
            dram_wr_port = self.sdram.crossbar.get_port()
            self.submodules.writer = Writer(dram_wr_port)
            self.add_csr('writer')

            # TODO: Rename as 'pattern_wr_w?'
            add_xram(self,
                     name='pattern_w0',
                     mem=self.writer.memory_w0,
                     origin=0x20000000)
            add_xram(self,
                     name='pattern_w1',
                     mem=self.writer.memory_w1,
                     origin=0x21000000)
            add_xram(self,
                     name='pattern_w2',
                     mem=self.writer.memory_w2,
                     origin=0x22000000)
            add_xram(self,
                     name='pattern_w3',
                     mem=self.writer.memory_w3,
                     origin=0x23000000)
            add_xram(self,
                     name='pattern_adr',
                     mem=self.writer.memory_adr,
                     origin=0x24000000)

            # ----------------------------- reader -------------------------------------
            dram_rd_port = self.sdram.crossbar.get_port()
            self.submodules.reader = Reader(dram_rd_port)
            self.add_csr('reader')

            add_xram(self,
                     name='pattern_rd_w0',
                     mem=self.reader.memory_w0,
                     origin=0x30000000)
            add_xram(self,
                     name='pattern_rd_w1',
                     mem=self.reader.memory_w1,
                     origin=0x31000000)
            add_xram(self,
                     name='pattern_rd_w2',
                     mem=self.reader.memory_w2,
                     origin=0x32000000)
            add_xram(self,
                     name='pattern_rd_w3',
                     mem=self.reader.memory_w3,
                     origin=0x33000000)
            add_xram(self,
                     name='pattern_rd_adr',
                     mem=self.reader.memory_adr,
                     origin=0x34000000)

        # Payload executor -------------------------------------------------------------------------
        if not args.no_payload_executor:
            # TODO: disconnect bus during payload execution

            phy_settings = self.sdram.controller.settings.phy
            scratchpad_width = phy_settings.dfi_databits * phy_settings.nphases
            scratchpad_size = 2**10

            payload_mem = Memory(32, 2**10)
            scratchpad_mem = Memory(scratchpad_width,
                                    scratchpad_size // (scratchpad_width // 8))
            self.specials += payload_mem, scratchpad_mem

            add_xram(self, name='payload', mem=payload_mem, origin=0x35000000)
            add_xram(self,
                     name='scratchpad',
                     mem=scratchpad_mem,
                     origin=0x36000000,
                     mode='r')

            self.submodules.payload_executor = PayloadExecutor(
                mem_payload=payload_mem,
                mem_scratchpad=scratchpad_mem,
                dfi=self.sdram.dfii.ext_dfi,
                dfi_sel=self.sdram.dfii.ext_dfi_sel,
                nranks=self.sdram.controller.settings.phy.nranks,
                bankbits=self.sdram.controller.settings.geom.bankbits,
                rowbits=self.sdram.controller.settings.geom.rowbits,
                colbits=self.sdram.controller.settings.geom.colbits,
                rdphase=self.sdram.controller.settings.phy.rdphase,
            )
            self.payload_executor.add_csrs()
            self.add_csr('payload_executor')
Ejemplo n.º 13
0
    def __init__(self, dram_port, pattern_mem, *, rowbits, row_shift):
        super().__init__(pattern_mem)

        self.doc = ModuleDoc("""
DMA DRAM reader.

Allows to check DRAM contents against a predefined pattern using DMA.

Pattern
-------

{common}

Reading errors
--------------

This module allows to check the locations of errors in the memory.
It scans the configured memory area and compares the values read to
the predefined pattern. If `skip_fifo` is 0, this module will stop
after each error encountered, so that it can be examined. Wait until
the `error_ready` CSR is 1. Then use the CSRs `error_offset`,
`error_data` and `error_expected` to examine the errors in the current
transfer. To continue reading, write 1 to `error_continue` CSR.
Setting `skip_fifo` to 1 will disable this behaviour entirely.

The final nubmer of errors can be read from `error_count`.
NOTE: This value represents the number of erroneous *DMA transfers*.

The current progress can be read from the `done` CSR.
        """.format(common=BISTModule.__doc__))

        error_desc = [
            ('offset', 32),
            ('data', dram_port.data_width),
            ('expected', dram_port.data_width),
        ]

        self.error_count = Signal(32)
        self.skip_fifo = Signal()
        self.error = stream.Endpoint(error_desc)

        dma = LiteDRAMDMAReader(dram_port, fifo_depth=4)
        self.submodules += dma

        # pass addresses from address FSM (command producer) to pattern FSM (data consumer)
        address_fifo = stream.SyncFIFO([('address', len(dma.sink.address))],
                                       depth=4)
        self.submodules += address_fifo

        # ----------------- Address FSM -----------------
        counter_addr = Signal(32)

        self.comb += [
            self.addr_port.adr.eq(counter_addr & self.data_mask),
            dma.sink.address.eq(self.addr_port.dat_r +
                                (counter_addr & self.mem_mask)),
        ]

        # Using temporary state 'WAIT' to obtain address offset from memory
        self.submodules.fsm_addr = fsm_addr = FSM()
        fsm_addr.act(
            "READY",
            If(
                self.start,
                NextValue(counter_addr, 0),
                NextState("WAIT"),
            ))
        fsm_addr.act(
            "WAIT",
            # FIXME: should be possible to write the address in WR_ADDR
            address_fifo.sink.valid.eq(counter_addr != 0),
            If(
                address_fifo.sink.ready | (counter_addr == 0),
                If(counter_addr >= self.count,
                   NextState("READY")).Else(NextState("WR_ADDR"))))
        fsm_addr.act(
            "WR_ADDR",
            dma.sink.valid.eq(1),
            If(
                dma.sink.ready,
                # send the address in WAIT
                NextValue(address_fifo.sink.address, dma.sink.address),
                NextValue(counter_addr, counter_addr + 1),
                NextState("WAIT")))

        # ------------- Pattern FSM ----------------
        counter_gen = Signal(32)

        # Unmatched memory offsets
        error_fifo = stream.SyncFIFO(error_desc, depth=2, buffered=False)
        self.submodules += error_fifo

        # DMA data may be inverted using AddressSelector
        data_expected = Signal.like(dma.source.data)
        self.submodules.inverter = RowDataInverter(
            addr=address_fifo.source.address,
            data_in=self.data_port.dat_r,
            data_out=data_expected,
            rowbits=rowbits,
            row_shift=row_shift,
        )

        self.comb += [
            self.data_port.adr.eq(counter_gen & self.data_mask),
            self.error.offset.eq(error_fifo.source.offset),
            self.error.data.eq(error_fifo.source.data),
            self.error.expected.eq(error_fifo.source.expected),
            self.error.valid.eq(error_fifo.source.valid),
            error_fifo.source.ready.eq(self.error.ready | self.skip_fifo),
            self.done.eq(counter_gen),
        ]

        self.submodules.fsm_pattern = fsm_pattern = FSM()
        fsm_pattern.act(
            "READY", self.ready.eq(1),
            If(
                self.start,
                NextValue(counter_gen, 0),
                NextValue(self.error_count, 0),
                NextState("WAIT"),
            ))
        fsm_pattern.act(
            "WAIT",  # TODO: we could pipeline the access
            If(counter_gen >= self.count,
               NextState("READY")).Else(NextState("RD_DATA")))
        fsm_pattern.act(
            "RD_DATA",
            If(
                dma.source.valid & address_fifo.source.valid,
                # we must now change FSM state in single cycle
                dma.source.ready.eq(1),
                address_fifo.source.ready.eq(1),
                # count the command
                NextValue(counter_gen, counter_gen + 1),
                # next state depends on if there was an error
                If(
                    dma.source.data != data_expected,
                    NextValue(self.error_count, self.error_count + 1),
                    NextValue(error_fifo.sink.offset,
                              address_fifo.source.address),
                    NextValue(error_fifo.sink.data, dma.source.data),
                    NextValue(error_fifo.sink.expected, data_expected),
                    If(self.skip_fifo, NextState("WAIT")).Else(
                        NextState("WR_ERR"))).Else(NextState("WAIT"))))
        fsm_pattern.act(
            "WR_ERR", error_fifo.sink.valid.eq(1),
            If(error_fifo.sink.ready | self.skip_fifo, NextState("WAIT")))
Ejemplo n.º 14
0
    def __init__(self, dram_port, fifo_depth=512, genlock_stream=None):
        self.sink = sink = stream.Endpoint(
            frame_dma_layout)  # "inputs" are the DMA frame parameters
        self.source = source = stream.Endpoint([
            ("data", dram_port.dw)
        ])  # "output" is the data stream

        # # #

        self.submodules.dma = LiteDRAMDMAReader(dram_port, fifo_depth, True)
        self.submodules.fsm = fsm = FSM(reset_state="IDLE")

        shift = log2_int(dram_port.dw // 8)
        base = Signal(dram_port.aw)
        length = Signal(dram_port.aw)
        offset = Signal(dram_port.aw)
        self.delay_base = CSRStorage(32)
        delay_base = Signal(32)
        self.line_align = CSRStorage(16)
        line_align = Signal(16)
        self.line_skip = CSRStorage(32)
        line_skip = Signal(32)
        self.hres_out = CSRStorage(16)
        self.vres_out = CSRStorage(16)
        self.comb += [
            base.eq(
                sink.base[shift:]
            ),  # ignore the lower bits of the base + length to match the DMA's expectations
            length.eq(
                sink.length[shift:]
            ),  # need to noodle on what that expectation is, exactly...
        ]
        hres = Signal(16)
        vres = Signal(16)
        self.comb += [
            hres.eq(self.hres_out.storage),
            vres.eq(self.vres_out.storage),
        ]
        hcount = Signal(16)
        vcount = Signal(16)
        linecount = Signal(16)
        self.field = Signal()
        vsyncpos = Signal(16)
        even_loc = Signal(16)
        odd_loc = Signal(16)
        self.even_pos = CSRStatus(16)
        self.odd_pos = CSRStatus(16)
        self.comb += [
            self.even_pos.status.eq(even_loc),
            self.odd_pos.status.eq(odd_loc),
        ]
        self.field_pos = CSRStorage(16)
        self.interlace = CSRStorage(
            2)  # bit 0 is enable, bit 1 is even/odd priority
        field_pos = Signal(16)
        interlace = Signal(2)
        self.submodules.sync_field_pos = BusSynchronizer(
            self.field_pos.size, "sys", "pix_o")
        self.submodules.sync_interlace = BusSynchronizer(
            self.interlace.size, "sys", "pix_o")
        self.submodules.sync_delay_base = BusSynchronizer(
            self.delay_base.size, "sys", "pix_o")
        self.submodules.sync_line_skip = BusSynchronizer(
            self.line_skip.size, "sys", "pix_o")
        self.submodules.sync_line_align = BusSynchronizer(
            self.line_align.size, "sys", "pix_o")
        self.comb += [
            self.sync_field_pos.i.eq(self.field_pos.storage),
            self.sync_interlace.i.eq(self.interlace.storage),
            self.sync_delay_base.i.eq(self.delay_base.storage),
            self.sync_line_skip.i.eq(self.line_skip.storage),
            self.sync_line_align.i.eq(self.line_align.storage),
            field_pos.eq(self.sync_field_pos.o),
            interlace.eq(self.sync_interlace.o),
            delay_base.eq(self.sync_delay_base.o),
            line_skip.eq(self.sync_line_skip.o),
            line_align.eq(self.sync_line_align.o),
        ]
        squash = Signal()

        if genlock_stream != None:
            self.v = Signal()
            self.v_r = Signal()
            self.sof = Signal()
            self.sync += [
                self.v.eq(genlock_stream.vsync),
                self.v_r.eq(self.v),
                self.sof.eq(self.v & ~self.v_r),
            ]
            self.h = Signal()
            self.h_r = Signal()
            self.sol = Signal()
            self.sync += [
                self.h.eq(genlock_stream.hsync),
                self.h_r.eq(self.h),
                self.sol.eq(self.h & ~self.h_r),
            ]
            self.sync += [
                If(self.sol, vsyncpos.eq(0)).Else(vsyncpos.eq(vsyncpos + 1)),
                If(
                    self.sof,
                    self.field.eq(~self.field),
                    If(
                        self.field,
                        odd_loc.eq(vsyncpos),
                    ).Else(even_loc.eq(vsyncpos), ),
                ),
            ]

        if genlock_stream == None:
            fsm.act(
                "IDLE",
                NextValue(offset, 0),
                If(
                    sink.valid,  # if our parameters are valid, start reading
                    NextState("READ")).Else(dram_port.flush.eq(1), ))
            fsm.act(
                "READ",
                self.dma.sink.valid.eq(
                    1
                ),  # tell the DMA reader that we've got a valid address for it
                If(
                    self.dma.sink.
                    ready,  # if the LiteDRAMDMAReader shows it's ready for an address (e.g. taken the current address)
                    NextValue(offset, offset + 1),  # increment the offset
                    If(
                        offset == (length - 1),  # at the end...
                        self.sink.ready.eq(
                            1),  # indicate we're ready for more parameters
                        NextState("IDLE"))))
        else:
            fsm.act(
                "IDLE",
                NextValue(linecount, 0),
                If(
                    self.interlace.storage[0],
                    # interlace
                    If(
                        self.field ^ interlace[1] ^ (
                            odd_loc < vsyncpos
                        ),  # xor against actual odd_loc vs vsyncpos in case we caught the wrong field polarity
                        NextValue(offset, delay_base),
                        NextValue(hcount, 0),
                        NextValue(vcount, 0),
                    ).Else(
                        NextValue(offset, delay_base + hres + 1),
                        NextValue(hcount, 0),
                        NextValue(vcount, 1),
                    )).Else(
                        # non-interlace
                        NextValue(offset, delay_base),
                        NextValue(hcount, 0),
                        NextValue(vcount, 0),
                    ),
                If(
                    sink.valid,  # if our parameters are valid, start reading
                    If(
                        line_align == 0,
                        NextState("READ"),
                    ).Else(NextState("WAIT_LINE"), )).Else(
                        dram_port.flush.eq(1), ))
            fsm.act(
                "WAIT_LINE",  # insert dummy waits until wait_line is done
                squash.eq(1),
                self.dma.sink.valid.eq(
                    1
                ),  # tell the DMA reader that we've got a valid address for it
                If(
                    self.dma.sink.
                    ready,  # if the LiteDRAMDMAReader shows it's ready for an address (e.g. taken the current address)
                    If(
                        linecount < line_align,
                        NextValue(linecount, linecount + 1),
                    ).Else(NextState("READ"), )))
            fsm.act(
                "READ",
                self.dma.sink.valid.eq(
                    1
                ),  # tell the DMA reader that we've got a valid address for it
                If(
                    self.dma.sink.
                    ready,  # if the LiteDRAMDMAReader shows it's ready for an address (e.g. taken the current address)
                    NextValue(hcount, hcount + 1),
                    If(
                        hcount >= hres,
                        If(
                            interlace[0],
                            # interlaced
                            NextValue(offset,
                                      offset + line_skip + 1 + hres + 1),
                            NextValue(hcount, 0),
                            NextValue(vcount, vcount + 2),
                        ).Else(
                            # not interlaced
                            NextValue(offset, offset + line_skip + 1),
                            NextValue(hcount, 0),
                            NextValue(vcount, vcount + 1),
                        )).Else(
                            NextValue(offset,
                                      offset + 1),  # increment the offset
                        ),
                    If(
                        (offset >=
                         (length - 1)) | vcount >= vres,  # at the end...
                        self.sink.ready.eq(
                            1),  # indicate we're ready for more parameters
                        NextState("WAIT_SOF"))))
            fsm.act(
                "WAIT_SOF",  # wait till vsync/start of frame
                If(self.sof, NextState("IDLE")))

        self.comb += [
            self.dma.sink.address.eq(
                base +
                offset),  # input to the DMA is an address of base + offset
            self.dma.source.connect(
                self.source
            )  # connect the DMA's output to the output of this module
        ]
Ejemplo n.º 15
0
                def __init__(self, dram_port, w0_port, w1_port, w2_port,
                             w3_port, adr_port):
                    self.reset = CSRStorage()
                    self.start = CSRStorage()
                    self.done = CSRStatus()

                    self.count = CSRStorage(size=32)
                    self.pointer = CSRStatus(size=32)

                    self.mem_base = CSRStorage(size=32)
                    self.mem_mask = CSRStorage(size=32)
                    self.data_mask = CSRStorage(size=32)  # patterns

                    dma = LiteDRAMDMAReader(dram_port,
                                            fifo_depth=1,
                                            fifo_buffered=False)
                    self.submodules += dma

                    cmd_counter = Signal(32)

                    self.comb += [
                        w0_port.adr.eq(cmd_counter & self.data_mask.storage),
                        w1_port.adr.eq(cmd_counter & self.data_mask.storage),
                        w2_port.adr.eq(cmd_counter & self.data_mask.storage),
                        w3_port.adr.eq(cmd_counter & self.data_mask.storage),
                        adr_port.adr.eq(cmd_counter & self.data_mask.storage),
                    ]

                    data_pattern = Signal(32 * 4)
                    self.comb += [
                        dma.sink.address.eq(self.mem_base.storage +
                                            adr_port.dat_r +
                                            (cmd_counter
                                             & self.mem_mask.storage)),
                        data_pattern.eq(
                            Cat(w0_port.dat_r, w1_port.dat_r, w2_port.dat_r,
                                w3_port.dat_r)),
                    ]

                    fsm = FSM(reset_state="IDLE")
                    self.submodules += fsm
                    fsm.act(
                        "IDLE",
                        If(
                            self.start.storage,
                            NextValue(cmd_counter, 0),
                            NextValue(self.pointer.status, 0xdeadbeef),
                            NextState("WAIT"),
                        ))
                    fsm.act(
                        "WAIT",
                        If(cmd_counter >= self.count.storage,
                           NextState("DONE")).Else(NextState("WR_ADR")))
                    fsm.act("WR_ADR", dma.sink.valid.eq(1),
                            If(dma.sink.ready, NextState("RD_DATA")))
                    fsm.act(
                        "RD_DATA", dma.source.ready.eq(1),
                        If(
                            dma.source.valid,
                            NextValue(cmd_counter, cmd_counter + 1),
                            If(dma.source.data != data_pattern,
                               NextValue(self.pointer.status, cmd_counter)),
                            NextState("WAIT")))
                    fsm.act("DONE", self.done.status.eq(1),
                            If(self.reset.storage, NextState("IDLE")))
Ejemplo n.º 16
0
    def __init__(self, dram_port, pattern_mem):
        super().__init__(pattern_mem)

        self.doc = ModuleDoc("""
DMA DRAM reader.

Allows to check DRAM contents against a predefined pattern using DMA.

Pattern
-------

{common}

Reading errors
--------------

This module allows to check the locations of errors in the memory.
It scans the configured memory area and compares the values read to
the predefined pattern. If `skip_fifo` is 0, this module will stop
after each error encountered, so that it can be examined. Wait until
the `error_ready` CSR is 1. Then use the CSRs `error_offset`,
`error_data` and `error_expected` to examine the errors in the current
transfer. To continue reading, write 1 to `error_continue` CSR.
Setting `skip_fifo` to 1 will disable this behaviour entirely.

The final nubmer of errors can be read from `error_count`.
NOTE: This value represents the number of erroneous *DMA transfers*.

The current progress can be read from the `done` CSR.
        """.format(common=BISTModule.__doc__))

        error_desc = [
            ('offset', 32),
            ('data', dram_port.data_width),
            ('expected', dram_port.data_width),
        ]

        self.error_count = Signal(32)
        self.skip_fifo = Signal()
        self.error = stream.Endpoint(error_desc)

        # FIXME: Increase fifo depth
        dma = LiteDRAMDMAReader(dram_port)
        self.submodules += dma

        # ----------------- Address FSM -----------------
        counter_addr = Signal(32)

        self.comb += [
            self.addr_port.adr.eq(counter_addr & self.data_mask),
            dma.sink.address.eq(self.addr_port.dat_r +
                                (counter_addr & self.mem_mask)),
        ]

        # Using temporary state 'WAIT' to obtain address offset from memory
        self.submodules.fsm_addr = fsm_addr = FSM()
        fsm_addr.act(
            "READY",
            If(
                self.start,
                NextValue(counter_addr, 0),
                NextState("WAIT"),
            ))
        fsm_addr.act(
            "WAIT",  # TODO: we could pipeline the access
            If(counter_addr >= self.count,
               NextState("READY")).Else(NextState("WR_ADDR")))
        fsm_addr.act(
            "WR_ADDR", dma.sink.valid.eq(1),
            If(dma.sink.ready, NextValue(counter_addr, counter_addr + 1),
               NextState("WAIT")))

        # ------------- Pattern FSM ----------------
        counter_gen = Signal(32)

        # Unmatched memory offsets
        error_fifo = stream.SyncFIFO(error_desc, depth=2, buffered=False)
        self.submodules += error_fifo

        self.comb += [
            self.data_port.adr.eq(counter_gen & self.data_mask),
            self.error.offset.eq(error_fifo.source.offset),
            self.error.data.eq(error_fifo.source.data),
            self.error.expected.eq(error_fifo.source.expected),
            self.error.valid.eq(error_fifo.source.valid),
            error_fifo.source.ready.eq(self.error.ready | self.skip_fifo),
            self.done.eq(counter_gen),
        ]

        self.submodules.fsm_pattern = fsm_pattern = FSM()
        fsm_pattern.act(
            "READY", self.ready.eq(1),
            If(
                self.start,
                NextValue(counter_gen, 0),
                NextValue(self.error_count, 0),
                NextState("WAIT"),
            ))
        fsm_pattern.act(
            "WAIT",  # TODO: we could pipeline the access
            If(counter_gen >= self.count,
               NextState("READY")).Else(NextState("RD_DATA")))
        fsm_pattern.act(
            "RD_DATA", dma.source.ready.eq(1),
            If(
                dma.source.valid, NextValue(counter_gen, counter_gen + 1),
                If(
                    dma.source.data != self.data_port.dat_r,
                    NextValue(self.error_count, self.error_count + 1),
                    NextValue(error_fifo.sink.offset, counter_gen),
                    NextValue(error_fifo.sink.data, dma.source.data),
                    NextValue(error_fifo.sink.expected, self.data_port.dat_r),
                    If(self.skip_fifo, NextState("WAIT")).Else(
                        NextState("WR_ERR"))).Else(NextState("WAIT"))))
        fsm_pattern.act(
            "WR_ERR", error_fifo.sink.valid.eq(1),
            If(error_fifo.sink.ready | self.skip_fifo, NextState("WAIT")))
Ejemplo n.º 17
0
    def __init__(self, dram_port):
        ashift, awidth = get_ashift_awidth(dram_port)
        self.start = Signal()
        self.done = Signal()
        self.base = Signal(awidth)
        self.end = Signal(awidth)
        self.length = Signal(awidth)
        self.random_data = Signal()
        self.random_addr = Signal()
        self.ticks = Signal(32)
        self.errors = Signal(32)

        self.run_cascade_in = Signal(reset=1)
        self.run_cascade_out = Signal()

        # # #

        # Data / Address generators ----------------------------------------------------------------
        data_gen = Generator(31, n_state=31, taps=[27, 30])  # PRBS31
        addr_gen = Generator(31, n_state=31, taps=[27, 30])
        self.submodules += data_gen, addr_gen
        self.comb += data_gen.random_enable.eq(self.random_data)
        self.comb += addr_gen.random_enable.eq(self.random_addr)

        # mask random address to the range <base, end), range size must be power of 2
        addr_mask = Signal(awidth)
        self.comb += addr_mask.eq((self.end - self.base) - 1)

        # DMA --------------------------------------------------------------------------------------
        dma = LiteDRAMDMAReader(dram_port)
        self.submodules += dma

        # Address FSM ------------------------------------------------------------------------------
        cmd_counter = Signal(dram_port.address_width, reset_less=True)

        cmd_fsm = FSM(reset_state="IDLE")
        self.submodules += cmd_fsm
        cmd_fsm.act(
            "IDLE", If(self.start, NextValue(cmd_counter, 0),
                       NextState("WAIT")))
        cmd_fsm.act("WAIT", If(self.run_cascade_in, NextState("RUN")))
        cmd_fsm.act(
            "RUN", dma.sink.valid.eq(1),
            If(
                dma.sink.ready, self.run_cascade_out.eq(1), addr_gen.ce.eq(1),
                NextValue(cmd_counter, cmd_counter + 1),
                If(cmd_counter == (self.length[ashift:] - 1),
                   NextState("DONE")).Elif(~self.run_cascade_in,
                                           NextState("WAIT"))))
        cmd_fsm.act("DONE")

        if isinstance(dram_port, LiteDRAMNativePort):  # addressing in dwords
            dma_sink_addr = dma.sink.address
        elif isinstance(dram_port, LiteDRAMAXIPort):  # addressing in bytes
            dma_sink_addr = dma.sink.address[ashift:]
        else:
            raise NotImplementedError

        self.comb += dma_sink_addr.eq(self.base[ashift:] +
                                      (addr_gen.o & addr_mask))

        # Data FSM ---------------------------------------------------------------------------------
        data_counter = Signal(dram_port.address_width, reset_less=True)

        data_fsm = FSM(reset_state="IDLE")
        self.submodules += data_fsm
        data_fsm.act(
            "IDLE",
            If(self.start, NextValue(data_counter, 0),
               NextValue(self.errors, 0), NextState("RUN")),
            NextValue(self.ticks, 0))

        data_fsm.act(
            "RUN", dma.source.ready.eq(1),
            If(
                dma.source.valid, data_gen.ce.eq(1),
                NextValue(data_counter, data_counter + 1),
                If(
                    dma.source.data !=
                    data_gen.o[:min(len(data_gen.o), dram_port.data_width)],
                    NextValue(self.errors, self.errors + 1)),
                If(data_counter == (self.length[ashift:] - 1),
                   NextState("DONE"))), NextValue(self.ticks, self.ticks + 1))
        data_fsm.act("DONE", self.done.eq(1))
Ejemplo n.º 18
0
    def __init__(self, dram_port):
        self.source = source = stream.Endpoint([("data", 128)])
        self.base = CSRStorage(32)
        self.h_width = CSRStorage(16)
        self.v_width = CSRStorage(16)
        self.start = CSR()
        self.done = CSRStatus()

        # # #

        self.submodules.dma = dma = LiteDRAMDMAReader(dram_port)

        pixel_bits = 16 # ycbcr 4:2:2
        burst_pixels = dram_port.dw//pixel_bits
        alignment_bits = bits_for(dram_port.dw//8) - 1

        self.comb += dma.source.connect(source)

        base = Signal(32)
        h_width = self.h_width.storage
        v_width = self.v_width.storage
        start = self.start.r & self.start.re
        done = self.done.status
        self.sync += If(start, base.eq(self.base.storage))

        h_clr = Signal()
        h_clr_lsb = Signal()
        h_inc = Signal()
        h = Signal(16)
        h_next = Signal(16)
        self.comb += h_next.eq(h + burst_pixels)
        self.sync += \
            If(h_clr,
                h.eq(0)
            ).Elif(h_clr_lsb,
                h[:3].eq(0),
                h[3:].eq(h[3:])
            ).Elif(h_inc,
                h.eq(h_next)
            )

        v_clr = Signal()
        v_inc = Signal()
        v_dec7 = Signal()
        v = Signal(16)
        self.sync += \
            If(v_clr,
                v.eq(0)
            ).Elif(v_inc,
                v.eq(v + 1)
            ).Elif(v_dec7,
                v.eq(v - 7)
            )

        self.submodules.fsm = fsm = FSM(reset_state="IDLE")
        fsm.act("IDLE",
            h_clr.eq(1),
            v_clr.eq(1),
            If(start,
                NextState("READ")
            ).Else(
                done.eq(1)
            )
        )
        fsm.act("READ",
            dma.sink.valid.eq(1),
            If(dma.sink.ready,
                # last burst of 8 pixels
                If(h_next[:3] == 0,
                    # last line of a block of 8 pixels
                    If(v[:3] == 7,
                        # last block of a line
                        If(h >= h_width - burst_pixels,
                            h_clr.eq(1),
                            v_inc.eq(1),
                            # last line
                            If(v >= v_width - 1,
                                NextState("IDLE")
                            )
                        ).Else(
                            h_inc.eq(1),
                            v_dec7.eq(1)
                        )
                    ).Else(
                        h_clr_lsb.eq(1),
                        v_inc.eq(1)
                    )
                ).Else(
                    h_inc.eq(1)
                )
             )
        )

        read_address = Signal(dram_port.aw + alignment_bits)
        self.comb += [
            read_address.eq(v * h_width + h),
            dma.sink.address.eq(
                base[alignment_bits:] +
                read_address[alignment_bits - log2_int(pixel_bits//8):])
        ]
Ejemplo n.º 19
0
    def __init__(self, dram_port, init=[]):
        ashift, awidth = get_ashift_awidth(dram_port)
        self.start = Signal()
        self.done = Signal()
        self.ticks = Signal(32)
        self.errors = Signal(32)

        self.run_cascade_in = Signal(reset=1)
        self.run_cascade_out = Signal()

        # # #

        # Data / Address pattern -------------------------------------------------------------------
        addr_init, data_init = zip(*init)
        addr_mem = Memory(dram_port.address_width,
                          len(addr_init),
                          init=addr_init)
        data_mem = Memory(dram_port.data_width, len(data_init), init=data_init)
        addr_port = addr_mem.get_port(async_read=True)
        data_port = data_mem.get_port(async_read=True)
        self.specials += addr_mem, data_mem, addr_port, data_port

        # DMA --------------------------------------------------------------------------------------
        dma = LiteDRAMDMAReader(dram_port)
        self.submodules += dma

        # Address FSM ------------------------------------------------------------------------------
        cmd_counter = Signal(dram_port.address_width, reset_less=True)

        cmd_fsm = FSM(reset_state="IDLE")
        self.submodules += cmd_fsm
        cmd_fsm.act(
            "IDLE",
            If(
                self.start, NextValue(cmd_counter, 0),
                If(self.run_cascade_in,
                   NextState("RUN")).Else(NextState("WAIT"))))
        cmd_fsm.act("WAIT", If(self.run_cascade_in, NextState("RUN")),
                    NextValue(self.ticks, self.ticks + 1))
        cmd_fsm.act(
            "RUN", dma.sink.valid.eq(1),
            If(
                dma.sink.ready, self.run_cascade_out.eq(1),
                NextValue(cmd_counter, cmd_counter + 1),
                If(cmd_counter == (len(init) - 1),
                   NextState("DONE")).Elif(~self.run_cascade_in,
                                           NextState("WAIT"))))
        cmd_fsm.act("DONE")

        if isinstance(dram_port, LiteDRAMNativePort):  # addressing in dwords
            dma_sink_addr = dma.sink.address
        elif isinstance(dram_port, LiteDRAMAXIPort):  # addressing in bytes
            dma_sink_addr = dma.sink.address[ashift:]
        else:
            raise NotImplementedError

        self.comb += [
            addr_port.adr.eq(cmd_counter),
            dma_sink_addr.eq(addr_port.dat_r),
        ]

        # Data FSM ---------------------------------------------------------------------------------
        data_counter = Signal(dram_port.address_width, reset_less=True)

        expected_data = Signal.like(dma.source.data)
        self.comb += [
            data_port.adr.eq(data_counter),
            expected_data.eq(data_port.dat_r),
        ]

        data_fsm = FSM(reset_state="IDLE")
        self.submodules += data_fsm
        data_fsm.act(
            "IDLE",
            If(self.start, NextValue(data_counter, 0),
               NextValue(self.errors, 0), NextState("RUN")),
            NextValue(self.ticks, 0))

        data_fsm.act(
            "RUN", dma.source.ready.eq(1),
            If(
                dma.source.valid, NextValue(data_counter, data_counter + 1),
                If(dma.source.data != expected_data,
                   NextValue(self.errors, self.errors + 1)),
                If(data_counter == (len(init) - 1), NextState("DONE"))),
            NextValue(self.ticks, self.ticks + 1))
        data_fsm.act("DONE", self.done.eq(1))
    def __init__(self, dram_port, fifo_depth=512, genlock_stream=None):
        self.sink = sink = stream.Endpoint(frame_dma_layout)  # "inputs" are the DMA frame parameters
        self.source = source = stream.Endpoint([("data", dram_port.dw)])  # "output" is the data stream

        # # #

        self.submodules.dma = LiteDRAMDMAReader(dram_port, fifo_depth, True)
        self.submodules.fsm = fsm = FSM(reset_state="IDLE")

        shift = log2_int(dram_port.dw//8)
        base = Signal(dram_port.aw)
        length = Signal(dram_port.aw)
        offset = Signal(dram_port.aw)
        self.delay_base = CSRStorage(32)
        self.comb += [
            base.eq(sink.base[shift:]),   # ignore the lower bits of the base + length to match the DMA's expectations
            length.eq(sink.length[shift:]), # need to noodle on what that expectation is, exactly...
        ]

        if genlock_stream != None:
            self.v = Signal()
            self.v_r = Signal()
            self.sof = Signal()
            self.sync += [
                self.v.eq(genlock_stream.vsync),
                self.v_r.eq(self.v),
                self.sof.eq(self.v & ~self.v_r),
            ]

        if genlock_stream == None:
            fsm.act("IDLE",
                NextValue(offset, 0),
                If(sink.valid,  # if our parameters are valid, start reading
                       NextState("READ")
                    ).Else(
                        dram_port.flush.eq(1),
                    )
                )
            fsm.act("READ",
                self.dma.sink.valid.eq(1),  # tell the DMA reader that we've got a valid address for it
                If(self.dma.sink.ready, # if the LiteDRAMDMAReader shows it's ready for an address (e.g. taken the current address)
                    NextValue(offset, offset + 1), # increment the offset
                    If(offset == (length - 1),  # at the end...
                        self.sink.ready.eq(1),  # indicate we're ready for more parameters
                        NextState("IDLE")
                    )
                )
            )
        else:
            fsm.act("IDLE",
                NextValue(offset, self.delay_base.storage),
                If(sink.valid,  # if our parameters are valid, start reading
                       NextState("READ")
                    ).Else(
                        dram_port.flush.eq(1),
                    )
                )
            fsm.act("READ",
                self.dma.sink.valid.eq(1),  # tell the DMA reader that we've got a valid address for it
                If(self.dma.sink.ready, # if the LiteDRAMDMAReader shows it's ready for an address (e.g. taken the current address)
                    NextValue(offset, offset + 1), # increment the offset
                    If(offset == (length - 1),  # at the end...
                        self.sink.ready.eq(1),  # indicate we're ready for more parameters
                        NextState("WAIT_SOF")
                    )
                )
            )
            fsm.act("WAIT_SOF",  # wait till vsync/start of frame
                If(self.sof,
                   NextState("IDLE")
                )
            )

        self.comb += [
            self.dma.sink.address.eq(base + offset),  # input to the DMA is an address of base + offset
            self.dma.source.connect(self.source)      # connect the DMA's output to the output of this module
        ]
    def __init__(self, dram_port):
        ashift, awidth = get_ashift_awidth(dram_port)
        self.start = Signal()
        self.done = Signal()
        self.base = Signal(awidth)
        self.length = Signal(awidth)
        self.random = Signal()
        self.ticks = Signal(32)
        self.errors = Signal(32)

        # # #

        # data / address generators
        data_gen = Generator(31, n_state=31, taps=[27, 30])  # PRBS31
        addr_gen = CEInserter()(Counter(awidth))
        self.submodules += data_gen, addr_gen
        self.comb += data_gen.random_enable.eq(self.random)

        # dma
        dma = LiteDRAMDMAReader(dram_port)
        self.submodules += dma

        # address
        cmd_counter = Signal(dram_port.address_width, reset_less=True)

        cmd_fsm = FSM(reset_state="IDLE")
        self.submodules += cmd_fsm
        cmd_fsm.act(
            "IDLE", If(self.start, NextValue(cmd_counter, 0),
                       NextState("RUN")))
        cmd_fsm.act(
            "RUN", dma.sink.valid.eq(1),
            If(
                dma.sink.ready, addr_gen.ce.eq(1),
                NextValue(cmd_counter, cmd_counter + 1),
                If(cmd_counter == (self.length[ashift:] - 1),
                   NextState("DONE"))))
        cmd_fsm.act("DONE")
        if isinstance(dram_port, LiteDRAMNativePort):  # addressing in dwords
            self.comb += dma.sink.address.eq(self.base[ashift:] + addr_gen.o)
        elif isinstance(dram_port, LiteDRAMAXIPort):  # addressing in bytes
            self.comb += dma.sink.address[ashift:].eq(self.base[ashift:] +
                                                      addr_gen.o)
        else:
            raise NotImplementedError

        # data
        data_counter = Signal(dram_port.address_width, reset_less=True)

        data_fsm = FSM(reset_state="IDLE")
        self.submodules += data_fsm
        data_fsm.act(
            "IDLE",
            If(self.start, NextValue(data_counter, 0),
               NextValue(self.errors, 0), NextState("RUN")),
            NextValue(self.ticks, 0))

        data_fsm.act(
            "RUN", dma.source.ready.eq(1),
            If(
                dma.source.valid, data_gen.ce.eq(1),
                NextValue(data_counter, data_counter + 1),
                If(
                    dma.source.data !=
                    data_gen.o[:min(len(data_gen.o), dram_port.data_width)],
                    NextValue(self.errors, self.errors + 1)),
                If(data_counter == (self.length[ashift:] - 1),
                   NextState("DONE"))), NextValue(self.ticks, self.ticks + 1))
        data_fsm.act("DONE", self.done.eq(1))
Ejemplo n.º 22
0
    def __init__(self, dram_port, random):
        self.start = Signal()
        self.done = Signal()

        self.base = Signal(dram_port.aw)
        self.length = Signal(dram_port.aw)

        self.err_count = Signal(32)

        # # #

        self.submodules.dma = dma = LiteDRAMDMAReader(dram_port)
        gen_cls = LFSR if random else Counter
        self.submodules.gen = gen = gen_cls(dram_port.dw)

        # address
        self.cmd_counter = cmd_counter = Signal(dram_port.aw)
        self.submodules.cmd_fsm = cmd_fsm = FSM(reset_state="IDLE")

        cmd_fsm.act(
            "IDLE",
            If(
                self.start,
                NextValue(cmd_counter, 0),
                NextState("RUN"),
            ),
        )
        cmd_fsm.act(
            "RUN",
            dma.sink.valid.eq(1),
            If(
                dma.sink.ready,
                NextValue(cmd_counter, cmd_counter + 1),
                If(cmd_counter == (self.length - 1), NextState("DONE")),
            ),
        )
        cmd_fsm.act("DONE")
        self.comb += dma.sink.address.eq(self.base + cmd_counter)

        # data
        self.data_counter = data_counter = Signal(dram_port.aw)
        self.submodules.data_fsm = data_fsm = FSM(reset_state="IDLE")

        self.data_error = Signal()
        self.comb += self.data_error.eq(dma.source.data != gen.o)

        data_fsm.act(
            "IDLE",
            If(
                self.start,
                NextValue(data_counter, 0),
                NextValue(self.err_count, 0),
                NextState("RUN"),
            ),
        )
        data_fsm.act(
            "RUN",
            dma.source.ready.eq(1),
            If(
                dma.source.valid,
                gen.ce.eq(1),
                NextValue(data_counter, data_counter + 1),
                If(
                    self.data_error,
                    NextValue(self.err_count, self.err_count + 1),
                ),
                If(
                    data_counter == (self.length - 1),
                    NextState("DONE"),
                ),
            ),
        )
        data_fsm.act("DONE")

        self.comb += self.done.eq(
            cmd_fsm.ongoing("DONE") & data_fsm.ongoing("DONE"))
Ejemplo n.º 23
0
    def __init__(self,
                 dram_port,
                 upd_clut_fifo=None,
                 hres=800,
                 vres=600,
                 base=0x00000000,
                 fifo_depth=65536,
                 clock_domain="sys",
                 clock_faster_than_sys=False,
                 hwcursor=False,
                 upd_overlay_fifo=False,
                 upd_omap_fifo=False):
        clut = Array(
            Array(Signal(8, reset=(255 - i)) for i in range(0, 256))
            for j in range(0, 3))

        upd_clut_fifo_dout = Record(cmap_layout)
        self.comb += upd_clut_fifo_dout.raw_bits().eq(upd_clut_fifo.dout)

        if (hwcursor):
            upd_omap_fifo_dout = Record(omap_layout)
            self.comb += upd_omap_fifo_dout.raw_bits().eq(upd_omap_fifo.dout)

        print(
            f"FRAMEBUFFER: dram_port.data_width = {dram_port.data_width}, {hres}x{vres}, 0x{base:x}, in {clock_domain}, clock_faster_than_sys={clock_faster_than_sys}"
        )

        vga_sync = getattr(self.sync, clock_domain)
        vga_sync += [
            If(
                upd_clut_fifo.readable,
                upd_clut_fifo.re.eq(1),
                clut[upd_clut_fifo_dout.color][upd_clut_fifo_dout.address].eq(
                    upd_clut_fifo_dout.data),
            ).Else(upd_clut_fifo.re.eq(0), )
        ]

        if (hwcursor):
            self.vtg_sink = vtg_sink = stream.Endpoint(
                video_timing_hwcursor_layout)
            overlay = Array(
                Array(
                    Array(Signal(1) for x in range(0, 32))
                    for y in range(0, 32)) for i in range(0, 2))
            omap = Array(
                Array(Signal(8, reset=(255 - i)) for i in range(0, 4))
                for j in range(0, 3))
            vga_sync += [
                If(
                    upd_overlay_fifo.readable,
                    upd_overlay_fifo.re.eq(1),
                    [
                        overlay[upd_overlay_fifo.dout[0]][
                            upd_overlay_fifo.dout[1:6]][x].eq(
                                upd_overlay_fifo.dout[6 + x])
                        for x in range(0, 32)
                    ],
                ).Else(upd_overlay_fifo.re.eq(0), )
            ]
            vga_sync += [
                If(
                    upd_omap_fifo.readable,
                    upd_omap_fifo.re.eq(1),
                    omap[upd_omap_fifo_dout.color]
                    [upd_omap_fifo_dout.address].eq(upd_omap_fifo_dout.data),
                ).Else(upd_omap_fifo.re.eq(0), )
            ]
        else:
            self.vtg_sink = vtg_sink = stream.Endpoint(video_timing_layout)
        self.source = source = stream.Endpoint(video_data_layout)
        self.underflow = Signal()

        #source_buf_ready = Signal()
        source_buf_valid = Signal()
        source_buf_de = Signal()
        source_buf_hsync = Signal()
        source_buf_vsync = Signal()
        data_buf = Signal(8)
        if (hwcursor):
            hwcursor_buf = Signal()
            hwcursorx_buf = Signal(5)
            hwcursory_buf = Signal(5)

        #source_out_ready = Signal()
        source_out_valid = Signal()
        source_out_de = Signal()
        source_out_hsync = Signal()
        source_out_vsync = Signal()
        source_out_r = Signal(8)
        source_out_g = Signal(8)
        source_out_b = Signal(8)

        # # #

        # Video DMA.
        from litedram.frontend.dma import LiteDRAMDMAReader
        self.submodules.dma = LiteDRAMDMAReader(dram_port,
                                                fifo_depth=fifo_depth //
                                                (dram_port.data_width // 8),
                                                fifo_buffered=True)
        self.dma.add_csr(
            default_base=base,
            default_length=hres * vres * 8 // 8,  # 8-bit PseudoColor
            default_enable=0,
            default_loop=1)

        # If DRAM Data Width > 8-bit and Video clock is faster than sys_clk:
        if (dram_port.data_width > 8) and clock_faster_than_sys:
            # Do Clock Domain Crossing first...
            self.submodules.cdc = stream.ClockDomainCrossing(
                [("data", dram_port.data_width)],
                cd_from="sys",
                cd_to=clock_domain)
            self.comb += self.dma.source.connect(self.cdc.sink)
            # ... and then Data-Width Conversion.
            self.submodules.conv = ClockDomainsRenamer({"sys": clock_domain})(
                stream.Converter(dram_port.data_width, 8))
            self.comb += self.cdc.source.connect(self.conv.sink)
            video_pipe_source = self.conv.source
        # Elsif DRAM Data Widt < 8-bit or Video clock is slower than sys_clk:
        else:
            # Do Data-Width Conversion first...
            self.submodules.conv = stream.Converter(dram_port.data_width, 8)
            self.comb += self.dma.source.connect(self.conv.sink)
            # ... and then Clock Domain Crossing.
            self.submodules.cdc = stream.ClockDomainCrossing(
                [("data", 8)], cd_from="sys", cd_to=clock_domain)
            self.comb += self.conv.source.connect(self.cdc.sink)
            video_pipe_source = self.cdc.source

        # Video Generation.
        self.comb += [
            vtg_sink.ready.eq(1),
            If(
                vtg_sink.valid & vtg_sink.de,
                source_buf_valid.eq(video_pipe_source.valid),
                #video_pipe_source.ready.eq(source_buf_ready),# ready flow the other way
                video_pipe_source.connect(
                    source, keep={"ready"}
                ),  # source.ready is set to 1 by the sink anyway, bypass the cycle delay
                #vtg_sink.ready.eq(source_buf_valid & source_buf_ready),
                vtg_sink.ready.eq(source_buf_valid & source.ready),
            ),
            source_buf_de.eq(vtg_sink.de),
            source_buf_hsync.eq(vtg_sink.hsync),
            source_buf_vsync.eq(vtg_sink.vsync),
            data_buf.eq(video_pipe_source.data),
        ]
        if (hwcursor):
            self.comb += [
                hwcursor_buf.eq(vtg_sink.hwcursor),
                hwcursorx_buf.eq(vtg_sink.hwcursorx),
                hwcursory_buf.eq(vtg_sink.hwcursory),
            ]

        if (hwcursor):
            source_mid_valid = Signal()
            source_mid_de = Signal()
            source_mid_hsync = Signal()
            source_mid_vsync = Signal()
            data_mid = Signal(8)

            hwcursor_color_idx = Signal(2)

            # first cycle, buffer everything and look up the cursor overlay color
            vga_sync += [
                source_mid_de.eq(source_buf_de),
                source_mid_hsync.eq(source_buf_hsync),
                source_mid_vsync.eq(source_buf_vsync),
                source_mid_valid.eq(source_buf_valid),
                data_mid.eq(data_buf),
                If(
                    hwcursor_buf,
                    hwcursor_color_idx.eq(
                        Cat(overlay[0][hwcursory_buf][hwcursorx_buf],
                            overlay[1][hwcursory_buf][hwcursorx_buf])),
                ).Else(hwcursor_color_idx.eq(0), )
            ]

            #second cycle, produce the pixel by doing CLUT lookup
            vga_sync += [
                source_out_de.eq(source_mid_de),
                source_out_hsync.eq(source_mid_hsync),
                source_out_vsync.eq(source_mid_vsync),
                source_out_valid.eq(source_mid_valid),
                #source_buf_ready.eq(source_out_ready), # ready flow the other way
                If(
                    hwcursor_color_idx != 0,
                    source_out_r.eq(omap[0][hwcursor_color_idx]),
                    source_out_g.eq(omap[1][hwcursor_color_idx]),
                    source_out_b.eq(omap[2][hwcursor_color_idx]),
                ).Elif(source_mid_de, source_out_r.eq(clut[0][data_mid]),
                       source_out_g.eq(clut[1][data_mid]),
                       source_out_b.eq(clut[2][data_mid])).Else(
                           source_out_r.eq(0), source_out_g.eq(0),
                           source_out_b.eq(0))
            ]
        else:
            vga_sync += [
                source_out_de.eq(source_buf_de),
                source_out_hsync.eq(source_buf_hsync),
                source_out_vsync.eq(source_buf_vsync),
                source_out_valid.eq(source_buf_valid),
                #source_buf_ready.eq(source_out_ready), # ready flow the other way
                If(source_buf_de, source_out_r.eq(clut[0][data_buf]),
                   source_out_g.eq(clut[1][data_buf]),
                   source_out_b.eq(clut[2][data_buf])).Else(
                       source_out_r.eq(0), source_out_g.eq(0),
                       source_out_b.eq(0))
            ]

        self.comb += [
            source.de.eq(source_out_de),
            source.hsync.eq(source_out_hsync),
            source.vsync.eq(source_out_vsync),
            source.valid.eq(source_out_valid),
            #source_out_ready.eq(source.ready), # ready flow the other way
            source.r.eq(source_out_r),
            source.g.eq(source_out_g),
            source.b.eq(source_out_b),
        ]

        # Underflow.
        self.comb += self.underflow.eq(~source.valid)