def __init__(self, phy, clk_freq, mode): self.submodules.etherbone = etherbone = Etherbone(mode) depacketizer = Depacketizer(clk_freq) packetizer = Packetizer() self.submodules += depacketizer, packetizer tx_cdc = stream.AsyncFIFO([("data", 32)], 8) tx_cdc = ClockDomainsRenamer({ "write": "sys", "read": "serwb_serdes" })(tx_cdc) self.submodules += tx_cdc rx_cdc = stream.AsyncFIFO([("data", 32)], 8) rx_cdc = ClockDomainsRenamer({ "write": "serwb_serdes", "read": "sys" })(rx_cdc) self.submodules += rx_cdc self.comb += [ # core <--> etherbone depacketizer.source.connect(etherbone.sink), etherbone.source.connect(packetizer.sink), # core --> serdes packetizer.source.connect(tx_cdc.sink), If(tx_cdc.source.valid & phy.init.ready, phy.serdes.tx_data.eq(tx_cdc.source.data)), tx_cdc.source.ready.eq(phy.init.ready), # serdes --> core rx_cdc.sink.valid.eq(phy.init.ready), rx_cdc.sink.data.eq(phy.serdes.rx_data), rx_cdc.source.connect(depacketizer.sink), ]
def __init__(self, pads, cd="ulpi"): self.submodules.ulpi_phy = ClockDomainsRenamer(cd)(ULPIPHYS7(pads)) fifo_sink = stream.AsyncFIFO(self.ulpi_phy.sink.description, 4) self.submodules.fifo_sink = ClockDomainsRenamer({ "write": "sys", "read": cd })(fifo_sink) fifo_source = stream.AsyncFIFO(self.ulpi_phy.source.description, 4) self.submodules.fifo_source = ClockDomainsRenamer({ "write": cd, "read": "sys" })(fifo_source) self.sink = self.fifo_sink.sink self.source = self.fifo_source.source # # # self.rx_fifo = self.ulpi_phy.rx_fifo self.comb += [ self.fifo_sink.source.connect(self.ulpi_phy.sink), self.ulpi_phy.source.connect(self.fifo_source.sink), ]
def __init__(self, port_from, port_to, cmd_depth=4, wdata_depth=16, rdata_depth=16): assert port_from.address_width == port_to.address_width assert port_from.data_width == port_to.data_width assert port_from.mode == port_to.mode address_width = port_from.address_width data_width = port_from.data_width mode = port_from.mode clock_domain_from = port_from.clock_domain clock_domain_to = port_to.clock_domain # # # cmd_fifo = stream.AsyncFIFO([("we", 1), ("addr", address_width)], cmd_depth) cmd_fifo = ClockDomainsRenamer({ "write": clock_domain_from, "read": clock_domain_to })(cmd_fifo) self.submodules += cmd_fifo self.submodules += stream.Pipeline(port_from.cmd, cmd_fifo, port_to.cmd) if mode == "write" or mode == "both": wdata_fifo = stream.AsyncFIFO([("data", data_width), ("we", data_width // 8)], wdata_depth) wdata_fifo = ClockDomainsRenamer({ "write": clock_domain_from, "read": clock_domain_to })(wdata_fifo) self.submodules += wdata_fifo self.submodules += stream.Pipeline(port_from.wdata, wdata_fifo, port_to.wdata) if mode == "read" or mode == "both": rdata_fifo = stream.AsyncFIFO([("data", data_width)], rdata_depth) rdata_fifo = ClockDomainsRenamer({ "write": clock_domain_to, "read": clock_domain_from })(rdata_fifo) self.submodules += rdata_fifo self.submodules += stream.Pipeline(port_to.rdata, rdata_fifo, port_from.rdata)
def __init__(self, clock_domain="sys", phy_dw=16): self.sink = stream.Endpoint([("data", phy_dw), ("ctrl", phy_dw//8)]) self.source = stream.Endpoint([("data", 32), ("ctrl", 4)]) # # # converter = stream.StrideConverter( [("data", phy_dw), ("ctrl", phy_dw//8)], [("data", 32), ("ctrl", 4)], reverse=False) converter = stream.BufferizeEndpoints({"sink": stream.DIR_SINK})(converter) converter = ClockDomainsRenamer(clock_domain)(converter) self.submodules.converter = converter cdc = stream.AsyncFIFO([("data", 32), ("ctrl", 4)], 8, buffered=True) cdc = ClockDomainsRenamer({"write": clock_domain, "read": "sys"})(cdc) self.submodules.cdc = cdc skip_remover = RXSKPRemover() self.submodules.skip_remover = skip_remover word_aligner = RXWordAligner() word_aligner = stream.BufferizeEndpoints({"source": stream.DIR_SOURCE})(word_aligner) self.submodules.word_aligner = word_aligner self.comb += [ self.sink.connect(converter.sink), converter.source.connect(cdc.sink), cdc.source.connect(skip_remover.sink), skip_remover.source.connect(word_aligner.sink), word_aligner.source.connect(self.source), ]
def __init__(self, phy, phy_cd): assert len(phy.source.data) in [16, 32] self.sink = sink = stream.Endpoint([("data", len(phy.source.data)), ("ctrl", len(phy.source.ctrl))]) self.source = source = stream.Endpoint([("data", 32), ("ctrl", 4)]) # # # use_ebuf = (len(phy.source.data) == 32) if use_ebuf: ebuf = ElasticBuffer(len(phy.source.data) + len(phy.source.ctrl), 4, phy_cd, "jesd") self.submodules.ebuf = ebuf self.comb += [ sink.ready.eq(1), ebuf.din[:32].eq(sink.data), ebuf.din[32:].eq(sink.ctrl), source.valid.eq(1), source.data.eq(ebuf.dout[:32]), source.ctrl.eq(ebuf.dout[32:]) ] else: converter = stream.StrideConverter( [("data", len(phy.source.data)), ("ctrl", len(phy.source.ctrl))], [("data", 32), ("ctrl", 4)], reverse=False) converter = ClockDomainsRenamer(phy_cd)(converter) self.submodules += converter cdc = stream.AsyncFIFO([("data", 32), ("ctrl", 4)], 4) cdc = ClockDomainsRenamer({"write": phy_cd, "read": "jesd"})(cdc) self.submodules += cdc self.comb += [ sink.connect(converter.sink), converter.source.connect(cdc.sink), cdc.source.connect(source) ]
def __init__(self, platform, *args, **kwargs): BaseSoC.__init__(self, platform, *args, **kwargs) encoder_port = self.sdram.crossbar.get_port(mode="read", dw=128) self.submodules.encoder_reader = EncoderDMAReader(encoder_port) encoder_cdc = stream.AsyncFIFO([("data", 128)], 4) encoder_cdc = ClockDomainsRenamer({ "write": "sys", "read": "encoder" })(encoder_cdc) encoder_buffer = ClockDomainsRenamer("encoder")(EncoderBuffer()) encoder = Encoder(platform) encoder_streamer = USBStreamer(platform, platform.request("fx2")) self.submodules += encoder_cdc, encoder_buffer, encoder, encoder_streamer self.comb += [ self.encoder_reader.source.connect(encoder_cdc.sink), encoder_cdc.source.connect(encoder_buffer.sink), encoder_buffer.source.connect(encoder.sink), encoder.source.connect(encoder_streamer.sink) ] self.add_wb_slave(mem_decoder(self.mem_map["encoder"]), encoder.bus) self.add_memory_region("encoder", self.mem_map["encoder"] + self.shadow_base, 0x2000) self.platform.add_period_constraint(encoder_streamer.cd_usb.clk, 10.0) encoder_streamer.cd_usb.clk.attr.add("keep") self.crg.cd_encoder.clk.attr.add("keep") self.platform.add_false_path_constraints(self.crg.cd_sys.clk, self.crg.cd_encoder.clk, encoder_streamer.cd_usb.clk)
def __init__(self, clock_domain="sys", phy_dw=16): self.sink = stream.Endpoint([("data", 32), ("ctrl", 4)]) self.source = stream.Endpoint([("data", phy_dw), ("ctrl", phy_dw // 8)]) # # # # Clock compensation skip_inserter = TXSKPInserter() self.submodules += skip_inserter # Clock domain crossing cdc = stream.AsyncFIFO([("data", 32), ("ctrl", 4)], 8, buffered=True) cdc = ClockDomainsRenamer({"write": "sys", "read": clock_domain})(cdc) self.submodules.cdc = cdc # Data-width adaptation converter = stream.StrideConverter([("data", 32), ("ctrl", 4)], [("data", phy_dw), ("ctrl", phy_dw // 8)], reverse=False) converter = stream.BufferizeEndpoints({"source": stream.DIR_SOURCE})(converter) converter = ClockDomainsRenamer(clock_domain)(converter) self.submodules.converter = converter # Flow self.comb += [ self.sink.connect(skip_inserter.sink), skip_inserter.source.connect(cdc.sink), cdc.source.connect(converter.sink), converter.source.connect(self.source) ]
def __init__(self, port_from, port_to, cmd_depth=4, wdata_depth=16, rdata_depth=16): assert port_from.aw == port_to.aw assert port_from.dw == port_to.dw assert port_from.mode == port_to.mode aw = port_from.aw dw = port_from.dw mode = port_from.mode cd_from = port_from.cd cd_to = port_to.cd # # # cmd_fifo = stream.AsyncFIFO([("we", 1), ("adr", aw)], cmd_depth) cmd_fifo = ClockDomainsRenamer({ "write": cd_from, "read": cd_to })(cmd_fifo) self.submodules += cmd_fifo self.submodules += stream.Pipeline(port_from.cmd, cmd_fifo, port_to.cmd) if mode == "write" or mode == "both": wdata_fifo = stream.AsyncFIFO([("data", dw), ("we", dw // 8)], wdata_depth) wdata_fifo = ClockDomainsRenamer({ "write": cd_from, "read": cd_to })(wdata_fifo) self.submodules += wdata_fifo self.submodules += stream.Pipeline(port_from.wdata, wdata_fifo, port_to.wdata) if mode == "read" or mode == "both": rdata_fifo = stream.AsyncFIFO([("data", dw)], rdata_depth) rdata_fifo = ClockDomainsRenamer({ "write": cd_to, "read": cd_from })(rdata_fifo) self.submodules += rdata_fifo self.submodules += stream.Pipeline(port_to.rdata, rdata_fifo, port_from.rdata)
def __init__(self, fifo_depth=8, simulation=False): self.sink_data = CSRStorage(32) self.sink_ready = CSRStatus() self.start = CSR() self.done = CSRStatus() # # # _run = Signal() _csib = Signal(reset=1) _i = Signal(32, reset=0xffffffff) # Create slow icap clk (sys_clk/4) --------------------------------------------------------- self.clock_domains.cd_icap = ClockDomain() icap_clk_counter = Signal(4) self.sync += icap_clk_counter.eq(icap_clk_counter + 1) self.sync += self.cd_icap.clk.eq(icap_clk_counter[1]) # FIFO fifo = stream.AsyncFIFO([("data", 32)], fifo_depth) fifo = ClockDomainsRenamer({"write": "sys", "read": "icap"})(fifo) self.submodules += fifo self.comb += [ fifo.sink.valid.eq(self.sink_data.re), fifo.sink.data.eq(self.sink_data.storage), self.sink_ready.status.eq(fifo.sink.ready), ] # Generate ICAP commands self.sync.icap += [ If(self.start.re, _run.eq(1), ).Elif(~fifo.source.valid, _run.eq(0) ) ] self.comb += [ self.done.status.eq(~_run), If(_run, _i.eq(fifo.source.data), _csib.eq(0), fifo.source.ready.eq(1) ) ] self._csib = _csib self._i = _i # ICAP instance if not simulation: self.specials += [ Instance("ICAPE2", p_ICAP_WIDTH="X32", i_CLK=ClockSignal("icap"), i_CSIB=_csib, i_RDWRB=0, i_I=Cat(*[_i[8*i:8*(i+1)][::-1] for i in range(4)]), ) ]
def get_port(self, udp_port, dw=8, cd="sys"): if udp_port in self.users.keys(): raise ValueError("Port {0:#x} already assigned".format(udp_port)) user_port = LiteEthUDPUserPort(dw) internal_port = LiteEthUDPUserPort(8) # tx tx_stream = user_port.sink if cd is not "sys": tx_cdc = stream.AsyncFIFO(eth_udp_user_description(user_port.dw), 4) tx_cdc = ClockDomainsRenamer({"write": cd, "read": "sys"})(tx_cdc) self.submodules += tx_cdc self.comb += tx_stream.connect(tx_cdc.sink) tx_stream = tx_cdc.source if dw != 8: tx_converter = stream.StrideConverter( eth_udp_user_description(user_port.dw), eth_udp_user_description(8)) self.submodules += tx_converter self.comb += tx_stream.connect(tx_converter.sink) tx_stream = tx_converter.source self.comb += tx_stream.connect(internal_port.sink) # rx rx_stream = internal_port.source if dw != 8: rx_converter = stream.StrideConverter( eth_udp_user_description(8), eth_udp_user_description(user_port.dw)) self.submodules += rx_converter self.comb += rx_stream.connect(rx_converter.sink) rx_stream = rx_converter.source if cd is not "sys": rx_cdc = stream.AsyncFIFO(eth_udp_user_description(user_port.dw), 4) rx_cdc = ClockDomainsRenamer({"write": "sys", "read": cd})(rx_cdc) self.submodules += rx_cdc self.comb += rx_stream.connect(rx_cdc.sink) rx_stream = rx_cdc.source self.comb += rx_stream.connect(user_port.source) self.users[udp_port] = internal_port return user_port
def __init__(self, data_width, depth=16): self.sink = sink = stream.Endpoint(core_layout(data_width)) self.source = source = stream.Endpoint(core_layout(data_width)) self.enable = CSRStorage() self.done = CSRStatus() self.mem_write = CSR() self.mem_mask = CSRStorage(data_width) self.mem_value = CSRStorage(data_width) self.mem_full = CSRStatus() # # # # Control re-synchronization enable = Signal() enable_d = Signal() self.specials += MultiReg(self.enable.storage, enable, "scope") self.sync.scope += enable_d.eq(enable) # Status re-synchronization done = Signal() self.specials += MultiReg(done, self.done.status) # Memory and configuration mem = stream.AsyncFIFO([("mask", data_width), ("value", data_width)], depth) mem = ClockDomainsRenamer({"write": "sys", "read": "scope"})(mem) self.submodules += mem self.comb += [ mem.sink.valid.eq(self.mem_write.re), mem.sink.mask.eq(self.mem_mask.storage), mem.sink.value.eq(self.mem_value.storage), self.mem_full.status.eq(~mem.sink.ready) ] # Hit and memory read/flush hit = Signal() flush = WaitTimer(2 * depth) flush = ClockDomainsRenamer("scope")(flush) self.submodules += flush self.comb += [ flush.wait.eq(~(~enable & enable_d)), # flush when disabling hit.eq((sink.data & mem.source.mask) == (mem.source.value & mem.source.mask)), mem.source.ready.eq((enable & hit) | ~flush.done), ] # Output self.comb += [ sink.connect(source), # Done when all triggers have been consumed done.eq(~mem.source.valid), source.hit.eq(done) ]
def __init__(self, cd): self.cd = cd self.users = [] self.master = LiteSPIMasterPort() if cd != "sys": rx_cdc = stream.AsyncFIFO(spi_phy2core_layout, 32, buffered=True) tx_cdc = stream.AsyncFIFO(spi_core2phy_layout, 32, buffered=True) self.submodules.rx_cdc = ClockDomainsRenamer({ "write": cd, "read": "sys" })(rx_cdc) self.submodules.tx_cdc = ClockDomainsRenamer({ "write": "sys", "read": cd })(tx_cdc) self.comb += [ self.rx_cdc.source.connect(self.master.sink), self.master.source.connect(self.tx_cdc.sink), ] self.cs = Signal() self.user_cs = [] self.user_request = []
def __init__(self, rx_mux, cd): self.cd = cd self.users = OrderedDict() self.rx_mux = rx_mux self.master = LiteSPIMasterPort() if cd is not "sys": rx_cdc = stream.AsyncFIFO(spi_phy_data_layout, 32, buffered=True) tx_cdc = stream.AsyncFIFO(spi_phy_ctl_layout, 32, buffered=True) self.submodules.rx_cdc = ClockDomainsRenamer({ "write": "litespi", "read": "sys" })(rx_cdc) self.submodules.tx_cdc = ClockDomainsRenamer({ "write": "sys", "read": "litespi" })(tx_cdc) self.comb += [ self.rx_cdc.source.connect(self.master.sink), self.master.source.connect(self.tx_cdc.sink), ] self.cs_n = Signal() self.user_cs = {}
def __init__(self, cd): # CD is the clock domain of the dram port self.source = stream.Endpoint(frame_parameter_layout + frame_dma_layout) # outputs are a cd-synchronized set of parameter from CSRs # # # cdc = stream.AsyncFIFO(self.source.description, 2) cdc = ClockDomainsRenamer({"write": "sys", "read": cd})(cdc) self.submodules += cdc self.enable = CSRStorage() for name, width in frame_parameter_layout + frame_dma_layout: setattr(self, name, CSRStorage(width, name=name, atomic_write=True)) # builds the CSR list self.comb += getattr(cdc.sink, name).eq(getattr(self, name).storage) # assigns them to the sink self.comb += cdc.sink.valid.eq(self.enable.storage) # I don't quite get this line, seems source.valid should be assigned here?? self.comb += cdc.source.connect(self.source) # FIFO's output ("source") is now our output
def __init__(self, cd): self.source = stream.Endpoint(frame_parameter_layout + frame_dma_layout) # # # cdc = stream.AsyncFIFO(self.source.description, 2) cdc = ClockDomainsRenamer({"write": "sys", "read": cd})(cdc) self.submodules += cdc self.enable = CSRStorage() for name, width in frame_parameter_layout + frame_dma_layout: setattr(self, name, CSRStorage(width, name=name, atomic_write=True)) self.comb += getattr(cdc.sink, name).eq(getattr(self, name).storage) self.comb += cdc.sink.valid.eq(self.enable.storage) self.comb += cdc.source.connect(self.source)
def __init__(self, fifo_depth=8, icap_clk_div=4, simulation=False): self.sink_data = CSRStorage(32, reset_less=True) self.sink_ready = CSRStatus() # # # # Create slow icap_clk (sys_clk/4) --------------------------------------------------------- icap_clk_counter = Signal(log2_int(icap_clk_div)) self.clock_domains.cd_icap = ClockDomain() self.sync += icap_clk_counter.eq(icap_clk_counter + 1) self.sync += self.cd_icap.clk.eq(icap_clk_counter[-1]) # FIFO (sys_clk to icap_clk) --------------------------------------------------------------- fifo = stream.AsyncFIFO([("data", 32)], fifo_depth) fifo = ClockDomainsRenamer({"write": "sys", "read": "icap"})(fifo) self.submodules += fifo self.comb += [ fifo.sink.valid.eq(self.sink_data.re), fifo.sink.data.eq(self.sink_data.storage), self.sink_ready.status.eq(fifo.sink.ready), ] # Generate ICAP commands ------------------------------------------------------------------- self._csib = _csib = Signal(reset=1) self._i = _i = Signal(32, reset=0xffffffff) self.comb += [ fifo.source.ready.eq(1), If(fifo.source.valid, _csib.eq(0), _i.eq(fifo.source.data) ) ] # ICAP instance ---------------------------------------------------------------------------- if not simulation: self.specials += [ Instance("ICAPE2", p_ICAP_WIDTH="X32", i_CLK=ClockSignal("icap"), i_CSIB=_csib, i_RDWRB=0, i_I=Cat(*[_i[8*i:8*(i+1)][::-1] for i in range(4)]), ) ]
def __init__(self, dw, cd_ratio): self.sink = stream.Endpoint(core_layout(dw)) self.source = stream.Endpoint(core_layout(dw * cd_ratio)) # # # self.submodules.buffer = stream.Buffer(core_layout(dw)) self.submodules.trigger = FrontendTrigger(dw) self.submodules.subsampler = FrontendSubSampler(dw) self.submodules.converter = stream.StrideConverter( core_layout(dw, 1), core_layout(dw * cd_ratio, cd_ratio)) self.submodules.fifo = ClockDomainsRenamer({ "write": "sys", "read": "new_sys" })(stream.AsyncFIFO(core_layout(dw * cd_ratio, cd_ratio), 8)) self.submodules.pipeline = stream.Pipeline(self.sink, self.buffer, self.trigger, self.subsampler, self.converter, self.fifo, self.source)
def __init__(self, platform, pads): self.sink = sink = stream.Endpoint([("data", 8)]) # # # self.clock_domains.cd_usb = ClockDomain() self.specials += [ Instance("IBUFG", i_I=pads.ifclk, o_O=self.cd_usb.clk), ] self.specials += AsyncResetSynchronizer(self.cd_usb, ResetSignal()) fifo = stream.AsyncFIFO([("data", 8)], 4) fifo = ClockDomainsRenamer({"write": "encoder", "read": "usb"})(fifo) self.submodules.fifo = fifo self.comb += Record.connect(sink, fifo.sink) self.specials += Instance( "fx2_jpeg_streamer", # clk, rst i_rst=ResetSignal("usb"), i_clk=ClockSignal("usb"), # jpeg encoder interface i_sink_stb=fifo.source.valid, i_sink_data=fifo.source.data, o_sink_ack=fifo.source.ready, # cypress fx2 slave fifo interface io_fx2_data=pads.data, i_fx2_full_n=pads.flagb, i_fx2_empty_n=pads.flagc, o_fx2_addr=pads.addr, o_fx2_cs_n=pads.cs_n, o_fx2_wr_n=pads.wr_n, o_fx2_rd_n=pads.rd_n, o_fx2_oe_n=pads.oe_n, o_fx2_pktend_n=pads.pktend_n) # add vhdl sources platform.add_source_dir(os.path.join("gateware", "streamer", "vhdl"))
def __init__(self, jtag=None, device=None, data_width=8, clock_domain="sys"): """JTAG PHY Provides a simple JTAG to LiteX stream module to easily stream data to/from the FPGA over JTAG. Wire format: data_width + 2 bits, LSB first. Host to Target: - TX ready : bit 0 - RX data: : bit 1 to data_width - RX valid : bit data_width + 1 Target to Host: - RX ready : bit 0 - TX data : bit 1 to data_width - TX valid : bit data_width + 1 """ self.sink = sink = stream.Endpoint([("data", data_width)]) self.source = source = stream.Endpoint([("data", data_width)]) # # # valid = Signal() data = Signal(data_width) count = Signal(max=data_width) # JTAG TAP --------------------------------------------------------------------------------- if jtag is None: if device[:3] == "xc6": jtag = S6JTAG() elif device[:3] == "xc7": jtag = S7JTAG() elif device[:4] in ["xcku", "xcvu"]: jtag = USJTAG() else: raise NotImplementedError self.submodules += jtag # JTAG clock domain ------------------------------------------------------------------------ self.clock_domains.cd_jtag = ClockDomain() self.comb += ClockSignal("jtag").eq(jtag.tck) self.specials += AsyncResetSynchronizer(self.cd_jtag, ResetSignal("sys")) # JTAG clock domain crossing --------------------------------------------------------------- if clock_domain != "jtag": tx_cdc = stream.AsyncFIFO([("data", data_width)], 4) tx_cdc = ClockDomainsRenamer({ "write": clock_domain, "read": "jtag" })(tx_cdc) rx_cdc = stream.AsyncFIFO([("data", data_width)], 4) rx_cdc = ClockDomainsRenamer({ "write": "jtag", "read": clock_domain })(rx_cdc) self.submodules += tx_cdc, rx_cdc self.comb += [ sink.connect(tx_cdc.sink), rx_cdc.source.connect(source) ] sink, source = tx_cdc.source, rx_cdc.sink # JTAG Xfer FSM ---------------------------------------------------------------------------- fsm = FSM(reset_state="XFER-READY") fsm = ClockDomainsRenamer("jtag")(fsm) fsm = ResetInserter()(fsm) self.submodules += fsm self.comb += fsm.reset.eq(jtag.reset | jtag.capture) fsm.act( "XFER-READY", jtag.tdo.eq(source.ready), If(jtag.shift, sink.ready.eq(jtag.tdi), NextValue(valid, sink.valid), NextValue(data, sink.data), NextValue(count, 0), NextState("XFER-DATA"))) fsm.act( "XFER-DATA", jtag.tdo.eq(data), If(jtag.shift, NextValue(count, count + 1), NextValue(data, Cat(data[1:], jtag.tdi)), If(count == (data_width - 1), NextState("XFER-VALID")))) fsm.act( "XFER-VALID", jtag.tdo.eq(valid), If(jtag.shift, source.valid.eq(jtag.tdi), NextState("XFER-READY"))) self.comb += source.data.eq(data)
def __init__(self, platform, with_cpu=True, with_sdram=True, with_etherbone=True, with_gtp=True, gtp_connector="pcie", gtp_refclk="pcie", gtp_linerate=5e9, with_gtp_bist=True, with_gtp_freqmeter=True, with_record=True): sys_clk_freq = int(100e6) # SoCSDRAM --------------------------------------------------------------------------------- SoCSDRAM.__init__( self, platform, sys_clk_freq, cpu_type="vexriscv" if with_cpu else None, csr_data_width=32, with_uart=with_cpu, uart_name="crossover", integrated_rom_size=0x8000 if with_cpu else 0x0000, integrated_main_ram_size=0x1000 if not with_sdram else 0x0000, ident="PCIe Analyzer LiteX SoC", ident_version=True) # CRG -------------------------------------------------------------------------------------- self.submodules.crg = _CRG(platform, sys_clk_freq) # DDR3 SDRAM ------------------------------------------------------------------------------- if not self.integrated_main_ram_size: self.submodules.ddrphy = s7ddrphy.A7DDRPHY( platform.request("ddram"), memtype="DDR3", nphases=4, sys_clk_freq=sys_clk_freq) self.add_csr("ddrphy") sdram_module = K4B2G1646F(sys_clk_freq, "1:4") self.register_sdram(self.ddrphy, geom_settings=sdram_module.geom_settings, timing_settings=sdram_module.timing_settings) # Etherbone -------------------------------------------------------------------------------- if with_etherbone: # ethphy self.submodules.ethphy = LiteEthPHYRMII( clock_pads=self.platform.request("eth_clocks"), pads=self.platform.request("eth")) self.add_csr("ethphy") # ethcore self.submodules.ethcore = LiteEthUDPIPCore( phy=self.ethphy, mac_address=0x10e2d5000000, ip_address="192.168.1.50", clk_freq=self.clk_freq) # etherbone self.submodules.etherbone = LiteEthEtherbone( self.ethcore.udp, 1234) self.add_wb_master(self.etherbone.wishbone.bus) # timing constraints self.platform.add_period_constraint(self.ethphy.crg.cd_eth_rx.clk, 1e9 / 50e6) self.platform.add_period_constraint(self.ethphy.crg.cd_eth_tx.clk, 1e9 / 50e6) self.platform.add_false_path_constraints( self.crg.cd_sys.clk, self.ethphy.crg.cd_eth_rx.clk, self.ethphy.crg.cd_eth_tx.clk) # GTP RefClk ------------------------------------------------------------------------------- if with_gtp: assert gtp_refclk in ["pcie", "internal"] if gtp_refclk == "pcie": refclk = Signal() refclk_freq = 100e6 refclk_pads = platform.request("pcie_refclk") self.specials += Instance("IBUFDS_GTE2", i_CEB=0, i_I=refclk_pads.p, i_IB=refclk_pads.n, o_O=refclk) else: refclk = Signal() refclk_freq = 100e6 self.comb += refclk.eq(ClockSignal("clk100")) platform.add_platform_command( "set_property SEVERITY {{Warning}} [get_drc_checks REQP-49]" ) # GTP PLL ---------------------------------------------------------------------------------- if with_gtp: qpll = GTPQuadPLL(refclk, refclk_freq, gtp_linerate) print(qpll) self.submodules += qpll # GTPs ------------------------------------------------------------------------------------- if with_gtp: for i in range(2): tx_pads = platform.request(gtp_connector + "_tx", i) rx_pads = platform.request(gtp_connector + "_rx", i) gtp = GTP(qpll, tx_pads, rx_pads, sys_clk_freq, data_width=20, clock_aligner=False, tx_buffer_enable=True, rx_buffer_enable=True) gtp.add_stream_endpoints() setattr(self.submodules, "gtp" + str(i), gtp) platform.add_period_constraint(gtp.cd_tx.clk, 1e9 / gtp.tx_clk_freq) platform.add_period_constraint(gtp.cd_rx.clk, 1e9 / gtp.rx_clk_freq) self.platform.add_false_path_constraints( self.crg.cd_sys.clk, gtp.cd_tx.clk, gtp.cd_rx.clk) # GTPs FreqMeters -------------------------------------------------------------------------- if with_gtp_freqmeter: self.submodules.gtp0_tx_freq = FreqMeter(ClockSignal("gtp0_tx")) self.submodules.gtp0_rx_freq = FreqMeter(ClockSignal("gtp0_rx")) self.submodules.gtp1_tx_freq = FreqMeter(ClockSignal("gtp1_tx")) self.submodules.gtp1_rx_freq = FreqMeter(ClockSignal("gtp1_rx")) self.add_csr("gtp0_tx_freq") self.add_csr("gtp0_rx_freq") self.add_csr("gtp1_tx_freq") self.add_csr("gtp1_rx_freq") # GTPs BIST -------------------------------------------------------------------------------- if with_gtp_bist: self.submodules.gtp0_tx_bist = GTPTXBIST(self.gtp0, "gtp0_tx") self.submodules.gtp0_rx_bist = GTPRXBIST(self.gtp0, "gtp0_rx") self.submodules.gtp1_tx_bist = GTPTXBIST(self.gtp1, "gtp1_tx") self.submodules.gtp1_rx_bist = GTPRXBIST(self.gtp1, "gtp1_rx") self.add_csr("gtp0_tx_bist") self.add_csr("gtp0_rx_bist") self.add_csr("gtp1_tx_bist") self.add_csr("gtp1_rx_bist") # Record ----------------------------------------------------------------------------------- # FIXME: use better data/ctrl packing (or separate recorders) if with_record: # Convert RX stream from 16-bit@250MHz to 64-bit@sys_clk rx_converter = stream.StrideConverter([("data", 16), ("ctrl", 2)], [("data", 96), ("ctrl", 12)], reverse=False) rx_converter = ClockDomainsRenamer("gtp0_rx")(rx_converter) self.submodules.rx_converter = rx_converter rx_cdc = stream.AsyncFIFO([("data", 96), ("ctrl", 12)], 8, buffered=True) rx_cdc = ClockDomainsRenamer({ "write": "gtp0_rx", "read": "sys" })(rx_cdc) self.submodules.rx_cdc = rx_cdc # RX DMA Recorder self.submodules.rx_dma_recorder = LiteDRAMDMAWriter( self.sdram.crossbar.get_port("write", 128)) self.rx_dma_recorder.add_csr() self.add_csr("rx_dma_recorder") self.comb += [ gtp.source.connect(rx_converter.sink), rx_converter.source.connect(rx_cdc.sink), self.rx_dma_recorder.sink.valid.eq(rx_cdc.source.valid), self.rx_dma_recorder.sink.data[0:96].eq(rx_cdc.source.data), self.rx_dma_recorder.sink.data[96:108].eq(rx_cdc.source.ctrl), ]
def __init__(self, jtag=None, device=None, data_width=8, clock_domain="sys", chain=1, platform=None): """JTAG PHY Provides a simple JTAG to LiteX stream module to easily stream data to/from the FPGA over JTAG. Wire format: data_width + 2 bits, LSB first. Host to Target: - TX ready : bit 0 - RX data: : bit 1 to data_width - RX valid : bit data_width + 1 Target to Host: - RX ready : bit 0 - TX data : bit 1 to data_width - TX valid : bit data_width + 1 """ self.sink = sink = stream.Endpoint([("data", data_width)]) self.source = source = stream.Endpoint([("data", data_width)]) # # # # JTAG TAP --------------------------------------------------------------------------------- if jtag is None: jtag_tdi_delay = 0 # Xilinx. if XilinxJTAG.get_primitive(device) is not None: jtag = XilinxJTAG(primitive=XilinxJTAG.get_primitive(device), chain=chain) jtag_tdi_delay = XilinxJTAG.get_tdi_delay(device) # Lattice. elif device[:5] == "LFE5U": jtag = ECP5JTAG() # Altera/Intel. elif AlteraJTAG.get_primitive(device) is not None: platform.add_reserved_jtag_decls() jtag = AlteraJTAG(primitive=AlteraJTAG.get_primitive(device), pads=platform.get_reserved_jtag_pads()) else: print(device) raise NotImplementedError self.submodules.jtag = jtag # JTAG clock domain ------------------------------------------------------------------------ self.clock_domains.cd_jtag = ClockDomain() self.comb += ClockSignal("jtag").eq(jtag.tck) self.specials += AsyncResetSynchronizer(self.cd_jtag, ResetSignal(clock_domain)) # JTAG clock domain crossing --------------------------------------------------------------- if clock_domain != "jtag": tx_cdc = stream.AsyncFIFO([("data", data_width)], 4) tx_cdc = ClockDomainsRenamer({ "write": clock_domain, "read": "jtag" })(tx_cdc) rx_cdc = stream.AsyncFIFO([("data", data_width)], 4) rx_cdc = ClockDomainsRenamer({ "write": "jtag", "read": clock_domain })(rx_cdc) self.submodules.tx_cdc = tx_cdc self.submodules.rx_cdc = rx_cdc self.comb += [ sink.connect(tx_cdc.sink), rx_cdc.source.connect(source) ] sink, source = tx_cdc.source, rx_cdc.sink # JTAG TDI/TDO Delay ----------------------------------------------------------------------- jtag_tdi = jtag.tdi jtag_tdo = jtag.tdo if jtag_tdi_delay: jtag_tdi_sr = Signal(data_width + 2 - jtag_tdi_delay) self.sync.jtag += If(jtag.shift, jtag_tdi_sr.eq(Cat(jtag.tdi, jtag_tdi_sr))) jtag_tdi = jtag_tdi_sr[-1] # JTAG Xfer FSM ---------------------------------------------------------------------------- valid = Signal() ready = Signal() data = Signal(data_width) count = Signal(max=data_width) fsm = FSM(reset_state="XFER-READY") fsm = ClockDomainsRenamer("jtag")(fsm) fsm = ResetInserter()(fsm) self.submodules += fsm self.comb += fsm.reset.eq(jtag.reset | jtag.capture) fsm.act( "XFER-READY", jtag_tdo.eq(ready), If(jtag.shift, sink.ready.eq(jtag_tdi), NextValue(valid, sink.valid), NextValue(data, sink.data), NextValue(count, 0), NextState("XFER-DATA"))) fsm.act( "XFER-DATA", jtag_tdo.eq(data), If(jtag.shift, NextValue(count, count + 1), NextValue(data, Cat(data[1:], jtag_tdi)), If(count == (data_width - 1), NextState("XFER-VALID")))) fsm.act( "XFER-VALID", jtag_tdo.eq(valid), If(jtag.shift, source.valid.eq(jtag_tdi), source.data.eq(data), NextValue(ready, source.ready), NextState("XFER-READY")))
def __init__(self, layout, depth=16, sync_fifo=True, sync_stages=2, buffered=False, xpm=True, reset="sink"): cd_sink = "write" cd_source = "read" self.sink = stream.Endpoint(layout) self.source = stream.Endpoint(layout) if xpm == False: if sync_fifo is True: fifo = stream.AsyncFIFO(layout, depth=depth, buffered=buffered) else: fifo = stream.SyncFIFO(layout, depth, buffered=buffered) self.submodules.fifo = fifo self.comb += [ self.sink.connect(fifo.sink), fifo.source.connect(self.source) ] else: desc = self.sink.description data_layout = [ ("payload", desc.payload_layout), ("param", desc.param_layout), ] self._fifo_in = fifo_in = Record(data_layout) self._fifo_out = fifo_out = Record(data_layout) self.comb += [ fifo_in.payload.eq(self.sink.payload), fifo_in.param.eq(self.sink.param), self.source.payload.eq(fifo_out.payload), self.source.param.eq(fifo_out.param), ] _tdata_len = ((len(fifo_in.raw_bits()) + 7) // 8) * 8 _padding_len = _tdata_len - len(fifo_in.raw_bits()) self.xpm_params = dict( p_CASCADE_HEIGHT=0, # 0 = auto p_CDC_SYNC_STAGES=2 if sync_fifo else sync_stages, p_CLOCKING_MODE="common_clock" if sync_fifo else "independent_clock", p_ECC_MODE="no_ecc", p_FIFO_DEPTH=depth, p_FIFO_MEMORY_TYPE="auto", p_PROG_EMPTY_THRESH=10, p_SIM_ASSERT_CHK=1, p_TDATA_WIDTH=_tdata_len, p_TDEST_WIDTH=1, p_TID_WIDTH=1, p_TUSER_WIDTH=1, p_USE_ADV_FEATURES="1000", o_almost_empty_axis=Signal(), o_almost_full_axis=Signal(), o_dbiterr_axis=Signal(), i_m_aclk=0b0 if sync_fifo else ClockSignal(cd_source), o_m_axis_tdata=Cat(fifo_out.raw_bits(), Signal(_padding_len)) if _padding_len != 0 else fifo_out.raw_bits(), o_m_axis_tdest=Signal(), o_m_axis_tid=Signal(), o_m_axis_tkeep=Signal(_tdata_len // 8), o_m_axis_tlast=self.source.last, o_m_axis_tstrb=Signal(_tdata_len // 8), o_m_axis_tuser=self.source.first, o_m_axis_tvalid=self.source.valid, i_m_axis_tready=self.source.ready, o_prog_empty_axis=Signal(), o_prog_full_axis=Signal(), o_rd_data_count_axis=Signal(), o_sbiterr_axis=Signal(), o_wr_data_count_axis=Signal(), i_injectdbiterr_axis=0b0, i_injectsbiterr_axis=0b0, i_s_aclk=ClockSignal() if sync_fifo else ClockSignal(cd_sink), i_s_aresetn=(~ResetSignal(cd_sink)) if reset == "sink" else (~ResetSignal(cd_source)), i_s_axis_tdata=Cat(fifo_in.raw_bits(), Replicate(C(0b0), _padding_len)), i_s_axis_tdest=0b0, i_s_axis_tid=0b0, i_s_axis_tkeep=Replicate(C(0b1), _tdata_len // 8), i_s_axis_tlast=self.sink.last, i_s_axis_tstrb=Replicate(C(0b1), _tdata_len // 8), i_s_axis_tuser=self.sink.first, i_s_axis_tvalid=self.sink.valid, o_s_axis_tready=self.sink.ready, )
def _get_uart_fifo(depth, sink_cd="sys", source_cd="sys"): if sink_cd != source_cd: fifo = stream.AsyncFIFO([("data", 8)], depth) return ClockDomainsRenamer({"write": sink_cd, "read": source_cd})(fifo) else: return stream.SyncFIFO([("data", 8)], depth, buffered=True)
def __init__(self, word_width, fifo_depth): # in pix clock domain self.valid_i = Signal() self.vsync = Signal() self.de = Signal() self.r = Signal(8) self.g = Signal(8) self.b = Signal(8) # in sys clock domain word_layout = [("sof", 1), ("pixels", word_width)] self.frame = stream.Endpoint(word_layout) self.busy = Signal() self._overflow = CSR() # # # de_r = Signal() self.sync.pix += de_r.eq(self.de) rgb2ycbcr = RGB2YCbCr() self.submodules += ClockDomainsRenamer("pix")(rgb2ycbcr) chroma_downsampler = YCbCr444to422() self.submodules += ClockDomainsRenamer("pix")(chroma_downsampler) self.comb += [ rgb2ycbcr.sink.valid.eq(self.valid_i), rgb2ycbcr.sink.r.eq(self.r), rgb2ycbcr.sink.g.eq(self.g), rgb2ycbcr.sink.b.eq(self.b), rgb2ycbcr.source.connect(chroma_downsampler.sink), chroma_downsampler.source.ready.eq(1), chroma_downsampler.datapath.first.eq(self.de & ~de_r) # XXX need clean up ] # XXX need clean up de = self.de vsync = self.vsync for i in range(rgb2ycbcr.latency + chroma_downsampler.latency): next_de = Signal() next_vsync = Signal() self.sync.pix += [ next_de.eq(de), next_vsync.eq(vsync) ] de = next_de vsync = next_vsync # start of frame detection vsync_r = Signal() new_frame = Signal() self.comb += new_frame.eq(vsync & ~vsync_r) self.sync.pix += vsync_r.eq(vsync) # pack pixels into words cur_word = Signal(word_width) cur_word_valid = Signal() encoded_pixel = Signal(16) self.comb += encoded_pixel.eq(Cat(chroma_downsampler.source.y, chroma_downsampler.source.cb_cr)), pack_factor = word_width//16 assert(pack_factor & (pack_factor - 1) == 0) # only support powers of 2 pack_counter = Signal(max=pack_factor) self.sync.pix += [ cur_word_valid.eq(0), If(new_frame, cur_word_valid.eq(pack_counter == (pack_factor - 1)), pack_counter.eq(0), ).Elif(chroma_downsampler.source.valid & de, [If(pack_counter == (pack_factor-i-1), cur_word[16*i:16*(i+1)].eq(encoded_pixel)) for i in range(pack_factor)], cur_word_valid.eq(pack_counter == (pack_factor - 1)), pack_counter.eq(pack_counter + 1) ) ] # FIFO fifo = stream.AsyncFIFO(word_layout, fifo_depth) fifo = ClockDomainsRenamer({"write": "pix", "read": "sys"})(fifo) self.submodules += fifo self.comb += [ fifo.sink.pixels.eq(cur_word), fifo.sink.valid.eq(cur_word_valid) ] self.sync.pix += \ If(new_frame, fifo.sink.sof.eq(1) ).Elif(cur_word_valid, fifo.sink.sof.eq(0) ) self.comb += [ fifo.source.connect(self.frame), self.busy.eq(0) ] # overflow detection pix_overflow = Signal() pix_overflow_reset = Signal() self.sync.pix += [ If(fifo.sink.valid & ~fifo.sink.ready, pix_overflow.eq(1) ).Elif(pix_overflow_reset, pix_overflow.eq(0) ) ] sys_overflow = Signal() self.specials += MultiReg(pix_overflow, sys_overflow) self.submodules.overflow_reset = PulseSynchronizer("sys", "pix") self.submodules.overflow_reset_ack = PulseSynchronizer("pix", "sys") self.comb += [ pix_overflow_reset.eq(self.overflow_reset.o), self.overflow_reset_ack.i.eq(pix_overflow_reset) ] overflow_mask = Signal() self.comb += [ self._overflow.w.eq(sys_overflow & ~overflow_mask), self.overflow_reset.i.eq(self._overflow.re) ] self.sync += \ If(self._overflow.re, overflow_mask.eq(1) ).Elif(self.overflow_reset_ack.o, overflow_mask.eq(0) )
def __init__(self, phy): self.sink = stream.Endpoint([("data", 32)]) self.source = stream.Endpoint([("data", 32)]) self.argument = CSRStorage(32) self.command = CSRStorage(32) self.send = CSR() self.response = CSRStatus(128) self.cmdevt = CSRStatus(4) self.dataevt = CSRStatus(4) self.blocksize = CSRStorage(16) self.blockcount = CSRStorage(32) self.timeout = CSRStorage(32, reset=2**16) # # # argument = Signal(32) command = Signal(32) response = Signal(136) cmdevt = Signal(4) dataevt = Signal(4) blocksize = Signal(16) blockcount = Signal(32) timeout = Signal(32) # sys to sd cdc self.specials += [ MultiReg(self.argument.storage, argument, "sd"), MultiReg(self.command.storage, command, "sd"), MultiReg(self.blocksize.storage, blocksize, "sd"), MultiReg(self.blockcount.storage, blockcount, "sd"), MultiReg(self.timeout.storage, timeout, "sd"), ] # sd to sys cdc response_cdc = BusSynchronizer(136, "sd", "sys") cmdevt_cdc = BusSynchronizer(4, "sd", "sys") dataevt_cdc = BusSynchronizer(4, "sd", "sys") self.submodules += response_cdc, cmdevt_cdc, dataevt_cdc self.comb += [ response_cdc.i.eq(response), self.response.status.eq(response_cdc.o[:128]), cmdevt_cdc.i.eq(cmdevt), self.cmdevt.status.eq(cmdevt_cdc.o), dataevt_cdc.i.eq(dataevt), self.dataevt.status.eq(dataevt_cdc.o) ] self.submodules.new_command = PulseSynchronizer("sys", "sd") self.comb += self.new_command.i.eq(self.send.re) self.comb += phy.cfg.timeout.eq(timeout) self.comb += phy.cfg.blocksize.eq(blocksize) self.submodules.crc7_inserter = crc7_inserter = ClockDomainsRenamer( "sd")(CRC(9, 7, 40)) self.submodules.crc16_inserter = crc16_inserter = ClockDomainsRenamer( "sd")(CRCUpstreamInserter()) self.submodules.crc16_checker = crc16_checker = ClockDomainsRenamer( "sd")(CRCDownstreamChecker()) self.submodules.upstream_cdc = ClockDomainsRenamer({ "write": "sys", "read": "sd" })(stream.AsyncFIFO(self.sink.description, 4)) self.submodules.downstream_cdc = ClockDomainsRenamer({ "write": "sd", "read": "sys" })(stream.AsyncFIFO(self.source.description, 4)) self.submodules.upstream_converter = ClockDomainsRenamer("sd")( stream.StrideConverter([('data', 32)], [('data', 8)], reverse=True)) self.submodules.downstream_converter = ClockDomainsRenamer("sd")( stream.StrideConverter([('data', 8)], [('data', 32)], reverse=True)) self.comb += [ self.sink.connect(self.upstream_cdc.sink), self.upstream_cdc.source.connect(self.upstream_converter.sink), self.upstream_converter.source.connect(crc16_inserter.sink), crc16_checker.source.connect(self.downstream_converter.sink), self.downstream_converter.source.connect(self.downstream_cdc.sink), self.downstream_cdc.source.connect(self.source) ] cmd_type = Signal(2) cmd_count = Signal(3) cmd_done = Signal() cmd_error = Signal() cmd_timeout = Signal() data_type = Signal(2) data_count = Signal(32) data_done = Signal() data_error = Signal() data_timeout = Signal() self.comb += [ cmd_type.eq(command[0:2]), data_type.eq(command[5:7]), cmdevt.eq(Cat(cmd_done, cmd_error, cmd_timeout, 0)), # FIXME cmd response CRC. dataevt.eq( Cat(data_done, data_error, data_timeout, ~crc16_checker.valid)), crc7_inserter.val.eq(Cat(argument, command[8:14], 1, 0)), crc7_inserter.clr.eq(1), crc7_inserter.enable.eq(1), ] self.submodules.fsm = fsm = ClockDomainsRenamer("sd")(FSM()) fsm.act( "IDLE", NextValue(cmd_done, 1), NextValue(data_done, 1), NextValue(cmd_count, 0), NextValue(data_count, 0), If(self.new_command.o, NextValue(cmd_done, 0), NextValue(cmd_error, 0), NextValue(cmd_timeout, 0), NextValue(data_done, 0), NextValue(data_error, 0), NextValue(data_timeout, 0), NextState("CMD"))) fsm.act( "CMD", phy.cmdw.sink.valid.eq(1), Case( cmd_count, { 0: phy.cmdw.sink.data.eq(Cat(command[8:14], 1, 0)), 1: phy.cmdw.sink.data.eq(argument[24:32]), 2: phy.cmdw.sink.data.eq(argument[16:24]), 3: phy.cmdw.sink.data.eq(argument[8:16]), 4: phy.cmdw.sink.data.eq(argument[0:8]), 5: [ phy.cmdw.sink.data.eq(Cat(1, crc7_inserter.crc)), phy.cmdw.sink.last.eq( cmd_type == SDCARD_CTRL_RESPONSE_NONE) ] }), If( phy.cmdw.sink.valid & phy.cmdw.sink.ready, NextValue(cmd_count, cmd_count + 1), If( cmd_count == (6 - 1), If(cmd_type == SDCARD_CTRL_RESPONSE_NONE, NextValue(cmd_done, 1), NextState("IDLE")).Else(NextState("CMD-RESPONSE"))))) fsm.act( "CMD-RESPONSE", phy.cmdr.sink.valid.eq(1), phy.cmdr.sink.last.eq(data_type == SDCARD_CTRL_DATA_TRANSFER_NONE), If( cmd_type == SDCARD_CTRL_RESPONSE_LONG, phy.cmdr.sink.length.eq(17) # 136bits ).Else(phy.cmdr.sink.length.eq(6) # 48bits ), If( phy.cmdr.source.valid, phy.cmdr.source.ready.eq(1), If(phy.cmdr.source.status == SDCARD_STREAM_STATUS_TIMEOUT, NextValue(cmd_timeout, 1), NextState("IDLE")).Elif( phy.cmdr.source.last, If(data_type == SDCARD_CTRL_DATA_TRANSFER_WRITE, NextState("DATA-WRITE")).Elif( data_type == SDCARD_CTRL_DATA_TRANSFER_READ, NextState("DATA-READ")).Else(NextState("IDLE")), ).Else( NextValue(response, Cat(phy.cmdr.source.data, response))))) fsm.act( "DATA-WRITE", crc16_inserter.source.connect(phy.dataw.sink), If( phy.dataw.sink.valid & phy.dataw.sink.last & phy.dataw.sink.ready, NextValue(data_count, data_count + 1), If(data_count == (blockcount - 1), NextState("IDLE"))), phy.datar.source.ready.eq(1), If( phy.datar.source.valid, If( phy.datar.source.status != SDCARD_STREAM_STATUS_DATAACCEPTED, NextValue(data_error, 1)))) fsm.act( "DATA-READ", phy.datar.sink.valid.eq(1), phy.datar.sink.last.eq(data_count == (blockcount - 1)), phy.datar.source.ready.eq(1), If( phy.datar.source.valid, If( phy.datar.source.status == SDCARD_STREAM_STATUS_OK, phy.datar.source.connect(crc16_checker.sink, omit={"status"}), If(phy.datar.source.last & phy.datar.source.ready, NextValue(data_count, data_count + 1), If(data_count == (blockcount - 1), NextState("IDLE")))).Elif( phy.datar.source.status == SDCARD_STREAM_STATUS_TIMEOUT, NextValue(data_timeout, 1), NextValue(data_count, 0), phy.datar.source.ready.eq(1), NextState("IDLE"))))
def __init__(self, phy): self.sink = stream.Endpoint([("data", 32)]) self.source = stream.Endpoint([("data", 32)]) self.argument = CSRStorage(32) self.command = CSRStorage(32) self.response = CSRStatus(120) self.cmdevt = CSRStatus(32) self.dataevt = CSRStatus(32) self.blocksize = CSRStorage(16) self.blockcount = CSRStorage(32) self.datatimeout = CSRStorage(32, reset=2**16) self.cmdtimeout = CSRStorage(32, reset=2**16) self.datawcrcclear = CSRStorage() self.datawcrcvalids = CSRStatus(32) self.datawcrcerrors = CSRStatus(32) # # # argument = Signal(32) command = Signal(32) response = Signal(120) cmdevt = Signal(32) dataevt = Signal(32) blocksize = Signal(16) blockcount = Signal(32) datatimeout = Signal(32) cmdtimeout = Signal(32) # sys to sd cdc self.specials += [ MultiReg(self.argument.storage, argument, "sd"), MultiReg(self.command.storage, command, "sd"), MultiReg(self.blocksize.storage, blocksize, "sd"), MultiReg(self.blockcount.storage, blockcount, "sd"), MultiReg(self.datatimeout.storage, datatimeout, "sd"), MultiReg(self.cmdtimeout.storage, cmdtimeout, "sd") ] # sd to sys cdc response_cdc = BusSynchronizer(120, "sd", "sys") cmdevt_cdc = BusSynchronizer(32, "sd", "sys") dataevt_cdc = BusSynchronizer(32, "sd", "sys") self.submodules += response_cdc, cmdevt_cdc, dataevt_cdc self.comb += [ response_cdc.i.eq(response), self.response.status.eq(response_cdc.o), cmdevt_cdc.i.eq(cmdevt), self.cmdevt.status.eq(cmdevt_cdc.o), dataevt_cdc.i.eq(dataevt), self.dataevt.status.eq(dataevt_cdc.o) ] self.submodules.new_command = PulseSynchronizer("sys", "sd") self.comb += self.new_command.i.eq(self.command.re) self.comb += [ phy.cfg.blocksize.eq(blocksize), phy.cfg.datatimeout.eq(datatimeout), phy.cfg.cmdtimeout.eq(cmdtimeout), phy.dataw.crc_clear.eq(self.datawcrcclear.storage), self.datawcrcvalids.status.eq(phy.dataw.crc_valids), self.datawcrcerrors.status.eq(phy.dataw.crc_errors) ] self.submodules.crc7inserter = ClockDomainsRenamer("sd")(CRC(9, 7, 40)) self.submodules.crc7checker = ClockDomainsRenamer("sd")(CRCChecker( 9, 7, 120)) self.submodules.crc16inserter = ClockDomainsRenamer("sd")( CRCUpstreamInserter()) self.submodules.crc16checker = ClockDomainsRenamer("sd")( CRCDownstreamChecker()) self.submodules.upstream_cdc = ClockDomainsRenamer({ "write": "sys", "read": "sd" })(stream.AsyncFIFO(self.sink.description, 4)) self.submodules.downstream_cdc = ClockDomainsRenamer({ "write": "sd", "read": "sys" })(stream.AsyncFIFO(self.source.description, 4)) self.submodules.upstream_converter = ClockDomainsRenamer("sd")( stream.StrideConverter([('data', 32)], [('data', 8)], reverse=True)) self.submodules.downstream_converter = ClockDomainsRenamer("sd")( stream.StrideConverter([('data', 8)], [('data', 32)], reverse=True)) self.comb += [ self.sink.connect(self.upstream_cdc.sink), self.upstream_cdc.source.connect(self.upstream_converter.sink), self.upstream_converter.source.connect(self.crc16inserter.sink), self.crc16checker.source.connect(self.downstream_converter.sink), self.downstream_converter.source.connect(self.downstream_cdc.sink), self.downstream_cdc.source.connect(self.source) ] self.submodules.fsm = fsm = ClockDomainsRenamer("sd")(FSM()) csel = Signal(max=6) waitresp = Signal(2) dataxfer = Signal(2) cmddone = Signal(reset=1) datadone = Signal(reset=1) blkcnt = Signal(32) pos = Signal(2) cerrtimeout = Signal() cerrcrc_en = Signal() derrtimeout = Signal() derrwrite = Signal() derrread_en = Signal() self.comb += [ waitresp.eq(command[0:2]), dataxfer.eq(command[5:7]), cmdevt.eq( Cat(cmddone, C(0, 1), cerrtimeout, cerrcrc_en & ~self.crc7checker.valid)), dataevt.eq( Cat(datadone, derrwrite, derrtimeout, derrread_en & ~self.crc16checker.valid)), self.crc7inserter.val.eq(Cat(argument, command[8:14], 1, 0)), self.crc7inserter.clr.eq(1), self.crc7inserter.enable.eq(1), self.crc7checker.val.eq(response) ] ccases = {} # To send command and CRC ccases[0] = phy.sink.data.eq(Cat(command[8:14], 1, 0)) for i in range(4): ccases[i + 1] = phy.sink.data.eq(argument[24 - 8 * i:32 - 8 * i]) ccases[5] = [ phy.sink.data.eq(Cat(1, self.crc7inserter.crc)), phy.sink.last.eq(waitresp == SDCARD_CTRL_RESPONSE_NONE) ] fsm.act( "IDLE", NextValue(pos, 0), If(self.new_command.o, NextValue(cmddone, 0), NextValue(cerrtimeout, 0), NextValue(cerrcrc_en, 0), NextValue(datadone, 0), NextValue(derrtimeout, 0), NextValue(derrwrite, 0), NextValue(derrread_en, 0), NextValue(response, 0), NextState("SEND_CMD"))) fsm.act( "SEND_CMD", phy.sink.valid.eq(1), phy.sink.cmd_data_n.eq(1), phy.sink.rd_wr_n.eq(0), Case(csel, ccases), If( phy.sink.valid & phy.sink.ready, If(csel < 5, NextValue(csel, csel + 1)).Else( NextValue(csel, 0), If(waitresp == SDCARD_CTRL_RESPONSE_NONE, NextValue(cmddone, 1), NextState("IDLE")).Else(NextValue(cerrcrc_en, 1), NextState("RECV_RESP"))))) fsm.act( "RECV_RESP", phy.sink.valid.eq(1), phy.sink.cmd_data_n.eq(1), phy.sink.rd_wr_n.eq(1), phy.sink.last.eq(dataxfer == SDCARD_CTRL_DATA_TRANSFER_NONE), If( waitresp == SDCARD_CTRL_RESPONSE_SHORT, phy.sink.data.eq(5) # (5+1)*8 == 48bits ).Elif( waitresp == SDCARD_CTRL_RESPONSE_LONG, phy.sink.data.eq(16) # (16+1)*8 == 136bits ), If( phy.source.valid, # Wait for resp or timeout coming from phy phy.source.ready.eq(1), If(phy.source.status == SDCARD_STREAM_STATUS_TIMEOUT, NextValue(cerrtimeout, 1), NextValue(cmddone, 1), NextValue(datadone, 1), NextState("IDLE")).Elif( phy.source.last, # Check response CRC NextValue(self.crc7checker.check, phy.source.data[1:8]), NextValue(cmddone, 1), If(dataxfer == SDCARD_CTRL_DATA_TRANSFER_READ, NextValue(derrread_en, 1), NextState("RECV_DATA")).Elif( dataxfer == SDCARD_CTRL_DATA_TRANSFER_WRITE, NextState("SEND_DATA")).Else( NextValue(datadone, 1), NextState("IDLE")), ).Else( NextValue(response, Cat(phy.source.data, response[0:112]))))) fsm.act( "RECV_DATA", phy.sink.valid.eq(1), phy.sink.cmd_data_n.eq(0), phy.sink.rd_wr_n.eq(1), phy.sink.last.eq(blkcnt == (blockcount - 1)), phy.sink.data.eq(0), # Read 1 block If( phy.source.valid, phy.source.ready.eq(1), If( phy.source.status == SDCARD_STREAM_STATUS_OK, self.crc16checker.sink.data.eq( phy.source.data), # Manual connect streams except ctrl self.crc16checker.sink.valid.eq(phy.source.valid), self.crc16checker.sink.last.eq(phy.source.last), phy.source.ready.eq(self.crc16checker.sink.ready), If( phy.source.last & phy.source.ready, # End of block If(blkcnt < (blockcount - 1), NextValue(blkcnt, blkcnt + 1), NextState("RECV_DATA")).Else( NextValue(blkcnt, 0), NextValue(datadone, 1), NextState("IDLE")))).Elif( phy.source.status == SDCARD_STREAM_STATUS_TIMEOUT, NextValue(derrtimeout, 1), NextValue(blkcnt, 0), NextValue(datadone, 1), phy.source.ready.eq(1), NextState("IDLE")))) fsm.act( "SEND_DATA", phy.sink.valid.eq(self.crc16inserter.source.valid), phy.sink.cmd_data_n.eq(0), phy.sink.rd_wr_n.eq(0), phy.sink.last.eq(self.crc16inserter.source.last), phy.sink.data.eq(self.crc16inserter.source.data), self.crc16inserter.source.ready.eq(phy.sink.ready), If( self.crc16inserter.source.valid & self.crc16inserter.source.last & self.crc16inserter.source.ready, If(blkcnt < (blockcount - 1), NextValue(blkcnt, blkcnt + 1)).Else(NextValue(blkcnt, 0), NextValue(datadone, 1), NextState("IDLE"))), If( phy.source.valid, phy.source.ready.eq(1), If(phy.source.status != SDCARD_STREAM_STATUS_DATAACCEPTED, NextValue(derrwrite, 1))))
def __init__(self, pads, clk_freq, fifo_depth=32, read_time=128, write_time=128): dw = len(pads.data) # read fifo (FTDI --> SoC) read_fifo = ClockDomainsRenamer({ "write": "usb", "read": "sys" })(stream.AsyncFIFO(phy_description(8), fifo_depth)) read_buffer = ClockDomainsRenamer("usb")(stream.SyncFIFO( phy_description(8), 4)) self.comb += read_buffer.source.connect(read_fifo.sink) # write fifo (SoC --> FTDI) write_fifo = ClockDomainsRenamer({ "write": "sys", "read": "usb" })(stream.AsyncFIFO(phy_description(8), fifo_depth)) self.submodules += read_fifo, read_buffer, write_fifo # sink / source interfaces self.sink = write_fifo.sink self.source = read_fifo.source # read / write arbitration wants_write = Signal() wants_read = Signal() txe_n = Signal() rxf_n = Signal() self.comb += [ txe_n.eq(pads.txe_n), rxf_n.eq(pads.rxf_n), wants_write.eq(~txe_n & write_fifo.source.valid), wants_read.eq(~rxf_n & read_fifo.sink.ready), ] read_time_en, max_read_time = anti_starvation(self, read_time) write_time_en, max_write_time = anti_starvation(self, write_time) data_w_accepted = Signal(reset=1) fsm = FSM(reset_state="READ") self.submodules += ClockDomainsRenamer("usb")(fsm) fsm.act( "READ", read_time_en.eq(1), If(wants_write, If(~wants_read | max_read_time, NextState("RTW")))) fsm.act("RTW", NextState("WRITE")) fsm.act( "WRITE", write_time_en.eq(1), If(wants_read, If(~wants_write | max_write_time, NextState("WTR"))), write_fifo.source.ready.eq(wants_write & data_w_accepted)) fsm.act("WTR", NextState("READ")) # databus tristate data_w = Signal(dw) data_r = Signal(dw) data_oe = Signal() self.specials += Tristate(pads.data, data_w, data_oe, data_r) # read / write actions pads.oe_n.reset = 1 pads.rd_n.reset = 1 pads.wr_n.reset = 1 self.sync.usb += [ If(fsm.ongoing("READ"), data_oe.eq(0), pads.oe_n.eq(0), pads.rd_n.eq(~wants_read), pads.wr_n.eq(1)).Elif(fsm.ongoing("WRITE"), data_oe.eq(1), pads.oe_n.eq(1), pads.rd_n.eq(1), pads.wr_n.eq(~wants_write), data_w_accepted.eq(~txe_n)).Else( data_oe.eq(1), pads.oe_n.eq(~fsm.ongoing("WTR")), pads.rd_n.eq(1), pads.wr_n.eq(1)), read_buffer.sink.valid.eq(~pads.rd_n & ~rxf_n), read_buffer.sink.data.eq(data_r), If(~txe_n & data_w_accepted, data_w.eq(write_fifo.source.data)) ]
def __init__(self, cfg): self.pads = pads = _sdpads() self.sink = sink = stream.Endpoint([("data", 8)]) self.source = source = stream.Endpoint([("data", 8), ("status", 3)]) # # # cmdrfb_reset = Signal() self.submodules.cmdrfb = SDPHYRFB(pads.cmd.i, False) self.submodules.fifo = ClockDomainsRenamer({"write": "sd_fb", "read": "sd"})( stream.AsyncFIFO(self.cmdrfb.source.description, 4) ) self.comb += self.cmdrfb.source.connect(self.fifo.sink) ctimeout = Signal(32) cread = Signal(10) ctoread = Signal(10) cnt = Signal(8) self.submodules.fsm = fsm = ClockDomainsRenamer("sd")(FSM(reset_state="IDLE")) fsm.act("IDLE", If(sink.valid, NextValue(ctimeout, 0), NextValue(cread, 0), NextValue(ctoread, sink.data), NextState("CMD_READSTART") ).Else( cmdrfb_reset.eq(1), self.fifo.source.ready.eq(1), ) ) self.specials += MultiReg(cmdrfb_reset, self.cmdrfb.reset, "sd_fb") fsm.act("CMD_READSTART", pads.cmd.oe.eq(0), pads.clk.eq(1), NextValue(ctimeout, ctimeout + 1), If(self.fifo.source.valid, NextState("CMD_READ") ).Elif(ctimeout > cfg.cmdtimeout, NextState("TIMEOUT") ) ) fsm.act("CMD_READ", pads.cmd.oe.eq(0), pads.clk.eq(1), source.valid.eq(self.fifo.source.valid), source.data.eq(self.fifo.source.data), source.status.eq(SDCARD_STREAM_STATUS_OK), source.last.eq(cread == ctoread), self.fifo.source.ready.eq(source.ready), If(source.valid & source.ready, NextValue(cread, cread + 1), If(cread == ctoread, If(sink.last, NextState("CMD_CLK8") ).Else( sink.ready.eq(1), NextState("IDLE") ) ) ) ) fsm.act("CMD_CLK8", If(cnt < 7, NextValue(cnt, cnt + 1), pads.clk.eq(1) ).Else( NextValue(cnt, 0), sink.ready.eq(1), NextState("IDLE") ) ) fsm.act("TIMEOUT", source.valid.eq(1), source.data.eq(0), source.status.eq(SDCARD_STREAM_STATUS_TIMEOUT), source.last.eq(1), If(source.valid & source.ready, sink.ready.eq(1), NextState("IDLE") ) )
def __init__(self, pads, dw=32, timeout=1024): read_fifo = ClockDomainsRenamer({ "write": "usb", "read": "sys" })(stream.AsyncFIFO(phy_description(dw), 128)) write_fifo = ClockDomainsRenamer({ "write": "sys", "read": "usb" })(stream.AsyncFIFO(phy_description(dw), 128)) read_buffer = ClockDomainsRenamer("usb")(stream.SyncFIFO( phy_description(dw), 4)) self.comb += read_buffer.source.connect(read_fifo.sink) self.submodules += read_fifo self.submodules += read_buffer self.submodules += write_fifo self.read_buffer = read_buffer self.sink = write_fifo.sink self.source = read_fifo.source self.tdata_w = tdata_w = Signal(dw) self.data_r = data_r = Signal(dw) self.data_oe = data_oe = Signal() self.specials += Tristate(pads.data, tdata_w, data_oe, data_r) data_w = Signal(dw) _data_w = Signal(dw) self.sync.usb += [_data_w.eq(data_w)] for i in range(dw): self.specials += [ Instance("ODDR", p_DDR_CLK_EDGE="SAME_EDGE", i_C=ClockSignal("usb"), i_CE=1, i_S=0, i_R=0, i_D1=_data_w[i], i_D2=data_w[i], o_Q=tdata_w[i]) ] self.rd_n = rd_n = Signal() _rd_n = Signal(reset=1) self.wr_n = wr_n = Signal() _wr_n = Signal(reset=1) self.oe_n = oe_n = Signal() _oe_n = Signal(reset=1) self.sync.usb += [ _rd_n.eq(rd_n), _wr_n.eq(wr_n), _oe_n.eq(oe_n), ] self.specials += [ Instance("ODDR", p_DDR_CLK_EDGE="SAME_EDGE", i_C=ClockSignal("usb"), i_CE=1, i_S=0, i_R=0, i_D1=_rd_n, i_D2=rd_n, o_Q=pads.rd_n), Instance("ODDR", p_DDR_CLK_EDGE="SAME_EDGE", i_C=ClockSignal("usb"), i_CE=1, i_S=0, i_R=0, i_D1=_wr_n, i_D2=wr_n, o_Q=pads.wr_n), Instance("ODDR", p_DDR_CLK_EDGE="SAME_EDGE", i_C=ClockSignal("usb"), i_CE=1, i_S=0, i_R=0, i_D1=_oe_n, i_D2=oe_n, o_Q=pads.oe_n) ] self.comb += [ pads.rst.eq(~ResetSignal("usb")), pads.be.eq(0xf), pads.siwua.eq(1), data_oe.eq(oe_n), ] fsm = FSM() self.submodules.fsm = ClockDomainsRenamer("usb")(fsm) self.tempsendval = tempsendval = Signal(dw) self.temptosend = temptosend = Signal() self.tempreadval = tempreadval = Signal(dw) self.temptoread = temptoread = Signal() self.wants_read = wants_read = Signal() self.wants_write = wants_write = Signal() self.cnt_write = cnt_write = Signal(max=timeout + 1) self.cnt_read = cnt_read = Signal(max=timeout + 1) first_write = Signal() self.comb += [ wants_read.eq(~temptoread & ~pads.rxf_n), wants_write.eq((temptosend | write_fifo.source.valid) & (pads.txe_n == 0)), ] self.fsmstate = Signal(4) self.comb += [ self.fsmstate.eq( Cat(fsm.ongoing("IDLE"), fsm.ongoing("WRITE"), fsm.ongoing("RDWAIT"), fsm.ongoing("READ"))) ] self.sync.usb += [ If(~fsm.ongoing("READ"), If(temptoread, If(read_buffer.sink.ready, temptoread.eq(0)))) ] self.comb += [ If( ~fsm.ongoing("READ"), If( temptoread, read_buffer.sink.data.eq(tempreadval), read_buffer.sink.valid.eq(1), )) ] fsm.act( "IDLE", rd_n.eq(1), wr_n.eq(1), If( wants_write, oe_n.eq(1), NextValue(cnt_write, 0), NextValue(first_write, 1), NextState("WRITE"), ).Elif(wants_read, oe_n.eq(0), NextState("RDWAIT")).Else(oe_n.eq(1), )) fsm.act( "WRITE", If( wants_read, NextValue(cnt_write, cnt_write + 1), ), NextValue(first_write, 0), rd_n.eq(1), If( pads.txe_n, oe_n.eq(1), wr_n.eq(1), write_fifo.source.ready.eq(0), If(write_fifo.source.valid & ~first_write, NextValue(temptosend, 1)), NextState("IDLE")).Elif( temptosend, oe_n.eq(1), data_w.eq(tempsendval), wr_n.eq(0), NextValue(temptosend, 0)).Elif(cnt_write > timeout, oe_n.eq(0), NextState("RDWAIT")).Elif( write_fifo.source.valid, oe_n.eq(1), data_w.eq(write_fifo.source.data), write_fifo.source.ready.eq(1), NextValue(tempsendval, write_fifo.source.data), NextValue(temptosend, 0), wr_n.eq(0), ).Else(oe_n.eq(1), wr_n.eq(1), NextValue(temptosend, 0), NextState("IDLE"))) fsm.act("RDWAIT", rd_n.eq(0), oe_n.eq(0), wr_n.eq(1), NextValue(cnt_read, 0), NextState("READ")) fsm.act( "READ", If( wants_write, NextValue(cnt_read, cnt_read + 1), ), wr_n.eq(1), If( pads.rxf_n, oe_n.eq(0), rd_n.eq(1), NextState("IDLE"), ).Elif( cnt_read > timeout, NextValue(cnt_write, 0), NextValue(first_write, 1), NextState("WRITE"), oe_n.eq(1), ).Else( oe_n.eq(0), read_buffer.sink.valid.eq(1), read_buffer.sink.data.eq(data_r), NextValue(tempreadval, data_r), If(read_buffer.sink.ready, rd_n.eq(0)).Else(NextValue(temptoread, 1), NextState("IDLE"), rd_n.eq(1))))
def __init__(self, data_width, depth): self.sink = sink = stream.Endpoint(core_layout(data_width)) self.enable = CSRStorage() self.done = CSRStatus() self.length = CSRStorage(bits_for(depth)) self.offset = CSRStorage(bits_for(depth)) self.mem_valid = CSRStatus() self.mem_ready = CSR() self.mem_data = CSRStatus(data_width) # # # # control re-synchronization enable = Signal() enable_d = Signal() enable = Signal() enable_d = Signal() self.specials += MultiReg(self.enable.storage, enable, "scope") self.sync.scope += enable_d.eq(enable) length = Signal(max=depth) offset = Signal(max=depth) self.specials += [ MultiReg(self.length.storage, length, "scope"), MultiReg(self.offset.storage, offset, "scope") ] # status re-synchronization done = Signal() self.specials += MultiReg(done, self.done.status) # memory mem = stream.SyncFIFO([("data", data_width)], depth, buffered=True) mem = ClockDomainsRenamer("scope")(mem) cdc = stream.AsyncFIFO([("data", data_width)], 4) cdc = ClockDomainsRenamer({"write": "scope", "read": "sys"})(cdc) self.submodules += mem, cdc # flush mem_flush = WaitTimer(depth) mem_flush = ClockDomainsRenamer("scope")(mem_flush) self.submodules += mem_flush # fsm fsm = FSM(reset_state="IDLE") fsm = ClockDomainsRenamer("scope")(fsm) self.submodules += fsm fsm.act("IDLE", done.eq(1), If(enable & ~enable_d, NextState("FLUSH")), sink.ready.eq(1), mem.source.connect(cdc.sink)) fsm.act("FLUSH", sink.ready.eq(1), mem_flush.wait.eq(1), mem.source.ready.eq(1), If(mem_flush.done, NextState("WAIT"))) fsm.act("WAIT", sink.connect(mem.sink, omit={"hit"}), If(sink.valid & sink.hit, NextState("RUN")), mem.source.ready.eq(mem.level >= self.offset.storage)) fsm.act("RUN", sink.connect(mem.sink, omit={"hit"}), If( mem.level >= self.length.storage, NextState("IDLE"), )) # memory read self.comb += [ self.mem_valid.status.eq(cdc.source.valid), cdc.source.ready.eq(self.mem_ready.re | ~self.enable.storage), self.mem_data.status.eq(cdc.source.data) ]