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) ]
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)
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))
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]), ]
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) ]
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)
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)
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")))
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')
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')
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)
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')
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")))
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 ]
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")))
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")))
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))
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):]) ]
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))
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"))
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)