def __init__(self, platform, *args, **kwargs): BaseSoC.__init__(self, platform, *args, **kwargs) encoder_port = self.sdram.crossbar.get_port() self.submodules.encoder_reader = EncoderDMAReader(encoder_port) self.add_csr("encoder_reader") 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.add_csr("encoder") 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(self.mem_map["encoder"], encoder.bus) self.add_memory_region("encoder", self.mem_map["encoder"], 0x2000, type="io") 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, width, depth): super().__init__(width, depth) ### depth_bits = log2_int(depth, True) produce = ClockDomainsRenamer("write")(GrayCounter(depth_bits + 1)) consume = ClockDomainsRenamer("read")(GrayCounter(depth_bits + 1)) self.submodules += produce, consume self.comb += [ produce.ce.eq(self.writable & self.we), consume.ce.eq(self.readable & self.re) ] produce_rdomain = Signal(depth_bits + 1) produce.q.attr.add("no_retiming") self.specials += MultiReg(produce.q, produce_rdomain, "read") consume_wdomain = Signal(depth_bits + 1) consume.q.attr.add("no_retiming") self.specials += MultiReg(consume.q, consume_wdomain, "write") if depth_bits == 1: self.comb += self.writable.eq( (produce.q[-1] == consume_wdomain[-1]) | (produce.q[-2] == consume_wdomain[-2])) else: self.comb += [ self.writable.eq( (produce.q[-1] == consume_wdomain[-1]) | (produce.q[-2] == consume_wdomain[-2]) | (produce.q[:-2] != consume_wdomain[:-2])) ] self.comb += self.readable.eq(consume.q != produce_rdomain) storage = Memory(self.width, depth) self.specials += storage wrport = storage.get_port(write_capable=True, clock_domain="write") self.specials += wrport self.comb += [ wrport.adr.eq(produce.q_binary[:-1]), wrport.dat_w.eq(self.din), wrport.we.eq(produce.ce) ] rdport = storage.get_port(clock_domain="read") self.specials += rdport self.comb += [ rdport.adr.eq(consume.q_next_binary[:-1]), self.dout.eq(rdport.dat_r) ]
def __init__(self, width, idomain, odomain, timeout=128): self.i = Signal(width) self.o = Signal(width, reset_less=True) if width == 1: self.specials += MultiReg(self.i, self.o, odomain) else: sync_i = getattr(self.sync, idomain) sync_o = getattr(self.sync, odomain) starter = Signal(reset=1) sync_i += starter.eq(0) self.submodules._ping = PulseSynchronizer(idomain, odomain) self.submodules._pong = PulseSynchronizer(odomain, idomain) self.submodules._timeout = ClockDomainsRenamer(idomain)( WaitTimer(timeout)) self.comb += [ self._timeout.wait.eq(~self._ping.i), self._ping.i.eq(starter | self._pong.o | self._timeout.done), self._pong.i.eq(self._ping.i) ] ibuffer = Signal(width, reset_less=True) obuffer = Signal(width) # registered reset_less by MultiReg sync_i += If(self._pong.o, ibuffer.eq(self.i)) ibuffer.attr.add("no_retiming") self.specials += MultiReg(ibuffer, obuffer, odomain) sync_o += If(self._ping.o, self.o.eq(obuffer))
def __init__(self, width, idomain, odomain, timeout=128): self.i = Signal(width) self.o = Signal(width, reset_less=True) if width == 1: self.specials += MultiReg(self.i, self.o, odomain) else: sync_i = getattr(self.sync, idomain) sync_o = getattr(self.sync, odomain) starter = Signal(reset=1) sync_i += starter.eq(0) self.submodules._ping = PulseSynchronizer(idomain, odomain) # Extra flop on i->o to avoid race between data and request # https://github.com/m-labs/nmigen/pull/40#issuecomment-484166790 ping_o = Signal() sync_o += ping_o.eq(self._ping.o) self.submodules._pong = PulseSynchronizer(odomain, idomain) self.submodules._timeout = ClockDomainsRenamer(idomain)( WaitTimer(timeout)) self.comb += [ self._timeout.wait.eq(~self._ping.i), self._ping.i.eq(starter | self._pong.o | self._timeout.done), self._pong.i.eq(ping_o) ] ibuffer = Signal(width, reset_less=True) obuffer = Signal(width) # registered reset_less by MultiReg sync_i += If(self._pong.o, ibuffer.eq(self.i)) ibuffer.attr.add("no_retiming") self.specials += MultiReg(ibuffer, obuffer, odomain) sync_o += If(ping_o, self.o.eq(obuffer))
def add_udp_loopback(self, portnum, dw, depth, name=None): port = self.eth_core.udp.crossbar.get_port(portnum, dw, cd="sys2x_i") buf = ClockDomainsRenamer("sys2x_i")(stream.SyncFIFO(eth_udp_user_description(dw), depth//(dw//8), buffered=True)) if name is None: self.submodules += buf else: setattr(self.submodules, name, buf) self.comb += Port.connect(port, buf)
def __init__(self, sd_linklayer, pins): self._latch = CSRStorage(len(pins)) self.clock_domains.cd_sd = ClockDomain(reset_less=True) self.comb += self.cd_sd.clk.eq(sd_linklayer.cd_sd.clk) sdcd_latch = Signal(len(pins)) self.specials += MultiReg(self._latch.storage, sdcd_latch, odomain="sd", n=3) # Output circuit itself is entirely in SD clock domain self.submodules.drv = ClockDomainsRenamer("sd")( SDTriggerOutputDriver(pins, sdcd_latch, sd_linklayer.data_out_done))
def __init__(self, sys_clk_freq=int(75e6), toolchain="trellis", **kwargs): BaseSoC.__init__(self, toolchain=toolchain, **kwargs) # Ethernet --------------------------------------------------------------------------------- # phy self.submodules.ethphy = ClockDomainsRenamer("sys2x_i")(LiteEthPHYRGMII( self.platform.request("eth_clocks"), self.platform.request("eth"))) self.add_csr("ethphy") self.submodules.eth_core = ClockDomainsRenamer("sys2x_i")(LiteEthUDPIPCore( phy = self.ethphy, mac_address = 0x10e2d5000001, ip_address = "192.168.1.50", clk_freq = int(2*sys_clk_freq), with_icmp = True)) self.add_udp_loopback(8000, 32, 128, "loopback_32") # etherbone - TODO, doesn't work yet # self.submodules.etherbone = LiteEthEtherbone(self.eth_core.udp, 1234) # self.add_wb_master(self.etherbone.wishbone.bus) # litescope - TODO, needs etherbone to work first # analyzer_signals = [ # self.loopback_32.sink # ] # self.submodules.analyzer = LiteScopeAnalyzer(analyzer_signals, 4096, csr_csv="tools/analyzer.csv") # self.add_csr("analyzer") # timing constraints self.platform.add_period_constraint(self.ethphy.crg.cd_eth_rx.clk, 1e9/125e6) self.platform.add_period_constraint(self.ethphy.crg.cd_eth_tx.clk, 1e9/125e6) 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)
def __init__(self, platform, boot_source="rand", debug=None, bios_file=None, use_dsp=False, placer="heap", output_dir="build", pnr_seed=0, warmboot_offsets=None, **kwargs): # Disable integrated RAM as we'll add it later self.integrated_sram_size = 0 self.output_dir = output_dir clk_freq = int(12e6) self.submodules.crg = _CRG(platform) SoCCore.__init__(self, platform, clk_freq, integrated_sram_size=0, with_uart=False, **kwargs) usb_debug = False if debug is not None: if debug == "uart": from litex.soc.cores.uart import UARTWishboneBridge self.submodules.uart_bridge = UARTWishboneBridge(platform.request("serial"), clk_freq, baudrate=115200) self.add_wb_master(self.uart_bridge.wishbone) elif debug == "usb": usb_debug = True elif debug == "spi": import spibone # Add SPI Wishbone bridge debug_device = [ ("spidebug", 0, Subsignal("mosi", Pins("dbg:0")), Subsignal("miso", Pins("dbg:1")), Subsignal("clk", Pins("dbg:2")), Subsignal("cs_n", Pins("dbg:3")), ) ] platform.add_extension(debug_device) spi_pads = platform.request("spidebug") self.submodules.spibone = ClockDomainsRenamer("usb_12")(spibone.SpiWishboneBridge(spi_pads, wires=4)) self.add_wb_master(self.spibone.wishbone) if hasattr(self, "cpu") and not isinstance(self.cpu, CPUNone): self.cpu.use_external_variant("rtl/VexRiscv_Fomu_Debug.v") os.path.join(output_dir, "gateware") self.register_mem("vexriscv_debug", 0xf00f0000, self.cpu.debug_bus, 0x100) else: if hasattr(self, "cpu") and not isinstance(self.cpu, CPUNone): self.cpu.use_external_variant("rtl/VexRiscv_Fomu.v") # SPRAM- UP5K has single port RAM, might as well use it as SRAM to # free up scarce block RAM. spram_size = 128*1024 self.submodules.spram = up5kspram.Up5kSPRAM(size=spram_size) self.register_mem("sram", self.mem_map["sram"], self.spram.bus, spram_size) # Add a Messible for device->host communications self.submodules.messible = Messible() if boot_source == "rand": kwargs['cpu_reset_address'] = 0 bios_size = 0x2000 self.submodules.random_rom = RandomFirmwareROM(bios_size) self.add_constant("ROM_DISABLE", 1) self.register_rom(self.random_rom.bus, bios_size) elif boot_source == "bios": kwargs['cpu_reset_address'] = 0 if bios_file is None: self.integrated_rom_size = bios_size = 0x2000 self.submodules.rom = wishbone.SRAM(bios_size, read_only=True, init=[]) self.register_rom(self.rom.bus, bios_size) else: bios_size = 0x2000 self.submodules.firmware_rom = FirmwareROM(bios_size, bios_file) self.add_constant("ROM_DISABLE", 1) self.register_rom(self.firmware_rom.bus, bios_size) elif boot_source == "spi": kwargs['cpu_reset_address'] = 0 self.integrated_rom_size = bios_size = 0x2000 gateware_size = 0x1a000 self.flash_boot_address = self.mem_map["spiflash"] + gateware_size self.submodules.rom = wishbone.SRAM(bios_size, read_only=True, init=[]) self.register_rom(self.rom.bus, bios_size) else: raise ValueError("unrecognized boot_source: {}".format(boot_source)) # The litex SPI module supports memory-mapped reads, as well as a bit-banged mode # for doing writes. spi_pads = platform.request("spiflash4x") self.submodules.lxspi = spi_flash.SpiFlashDualQuad(spi_pads, dummy=platform.spi_dummy, endianness="little") self.register_mem("spiflash", self.mem_map["spiflash"], self.lxspi.bus, size=platform.spi_size) # Add USB pads, as well as the appropriate USB controller. If no CPU is # present, use the DummyUsb controller. usb_pads = platform.request("usb") usb_iobuf = usbio.IoBuf(usb_pads.d_p, usb_pads.d_n, usb_pads.pullup) if hasattr(self, "cpu") and not isinstance(self.cpu, CPUNone): self.submodules.usb = eptri.TriEndpointInterface(usb_iobuf, debug=usb_debug) else: self.submodules.usb = dummyusb.DummyUsb(usb_iobuf, debug=usb_debug) if usb_debug: self.add_wb_master(self.usb.debug_bridge.wishbone) # For the EVT board, ensure the pulldown pin is tristated as an input if hasattr(usb_pads, "pulldown"): pulldown = TSTriple() self.specials += pulldown.get_tristate(usb_pads.pulldown) self.comb += pulldown.oe.eq(0) # Add GPIO pads for the touch buttons platform.add_extension(TouchPads.touch_device) self.submodules.touch = TouchPads(platform.request("touch_pads")) # Allow the user to reboot the ICE40. Additionally, connect the CPU # RESET line to a register that can be modified, to allow for # us to debug programs even during reset. self.submodules.reboot = SBWarmBoot(self, warmboot_offsets) if hasattr(self, "cpu") and not isinstance(self.cpu, CPUNone): self.cpu.cpu_params.update( i_externalResetVector=self.reboot.addr.storage, ) self.submodules.rgb = SBLED(platform.revision, platform.request("rgb_led")) self.submodules.version = Version(platform.revision, self, pnr_seed, models=[ ("0x45", "E", "Fomu EVT"), ("0x44", "D", "Fomu DVT"), ("0x50", "P", "Fomu PVT (production)"), ("0x48", "H", "Fomu Hacker"), ("0x3f", "?", "Unknown model"), ]) # Override default LiteX's yosys/build templates assert hasattr(platform.toolchain, "yosys_template") assert hasattr(platform.toolchain, "build_template") platform.toolchain.yosys_template = [ "{read_files}", "attrmap -tocase keep -imap keep=\"true\" keep=1 -imap keep=\"false\" keep=0 -remove keep=0", "synth_ice40 -json {build_name}.json -top {build_name}", ] platform.toolchain.build_template = [ "yosys -q -l {build_name}.rpt {build_name}.ys", "nextpnr-ice40 --json {build_name}.json --pcf {build_name}.pcf --asc {build_name}.txt \ --pre-pack {build_name}_pre_pack.py --{architecture} --package {package}", "icepack {build_name}.txt {build_name}.bin" ] # Add "-relut -dffe_min_ce_use 4" to the synth_ice40 command. # The "-reult" adds an additional LUT pass to pack more stuff in, # and the "-dffe_min_ce_use 4" flag prevents Yosys from generating a # Clock Enable signal for a LUT that has fewer than 4 flip-flops. # This increases density, and lets us use the FPGA more efficiently. platform.toolchain.yosys_template[2] += " -relut -abc2 -dffe_min_ce_use 4 -relut" if use_dsp: platform.toolchain.yosys_template[2] += " -dsp" # Disable final deep-sleep power down so firmware words are loaded # onto softcore's address bus. platform.toolchain.build_template[2] = "icepack -s {build_name}.txt {build_name}.bin" # Allow us to set the nextpnr seed platform.toolchain.build_template[1] += " --seed " + str(pnr_seed) if placer is not None: platform.toolchain.build_template[1] += " --placer {}".format(placer)
def __init__(self, usb_iobuf): self.bus = wishbone.Interface() # create a new custom CSR bus self.submodules.csr = WB2CSR(self.bus) csr_cpu = self.csr.csr self.submodules.usb = usb = ClockDomainsRenamer({'sys': 'usb_12'})( eptri.TriEndpointInterface(usb_iobuf, debug=False)) csrs = self.usb.get_csrs() # create a CSRBank for the eptri CSRs self.submodules.csr_bank = ClockDomainsRenamer({'sys': 'usb_12' })(CSRBank(csrs, 0)) csr_usb12 = self.csr_bank.bus if hasattr(usb, 'debug_bridge'): self.debug_bridge = usb.debug_bridge.wishbone # patch these two CSRs together with an Async FIFO _layout = [("adr", 32), ("dat_w", 32), ("we", 1)] self.submodules.fifo = fifo = ClockDomainsRenamer({ 'write': 'sys', 'read': 'usb_12' })(AsyncFIFO(_layout, 64, False)) bus_adr = Signal(32) self.comb += [ # Data into FIFO fifo.sink.adr.eq(csr_cpu.adr), fifo.sink.dat_w.eq(csr_cpu.dat_w), fifo.sink.we.eq(csr_cpu.we), fifo.sink.valid.eq(self.csr.en), # Always clear FIFO on clock cycle fifo.source.ready.eq(1), If( fifo.source.valid, csr_usb12.dat_w.eq(fifo.source.dat_w), csr_usb12.adr.eq(fifo.source.adr), bus_adr.eq(fifo.source.adr), csr_usb12.we.eq(fifo.source.we), ), ] self.submodules.fifo_r = fifo_r = ClockDomainsRenamer({ 'write': 'usb_12', 'read': 'sys' })(AsyncFIFO([("adr", 32), ("dat_r", 32)], 64, False)) valid = Signal() source_adr = Signal(32) self.sync.usb_12 += [ valid.eq(fifo.source.valid & ~csr_usb12.we), source_adr.eq(bus_adr) ] self.comb += [ # Data into FIFO fifo_r.sink.dat_r.eq(csr_usb12.dat_r), fifo_r.sink.adr.eq(source_adr), fifo_r.sink.valid.eq(valid), fifo_r.source.ready.eq(1), ] self.sync += [ self.csr.ack.eq(0), If( fifo_r.source.valid, self.csr.ack.eq(self.bus.adr[:14] == fifo_r.source.adr), csr_cpu.dat_r.eq(fifo_r.source.dat_r), ), ] # Patch interrupt through self.irq = Signal() self.specials += MultiReg(usb.ev.irq, self.irq)
def __init__(self, pads, rd_bitslip, wr_bitslip, dqs_ddr_alignment): half_rate_phy = S6HalfRateDDRPHY(pads, "DDR3", rd_bitslip, wr_bitslip, dqs_ddr_alignment) self.submodules += ClockDomainsRenamer("sys2x")(half_rate_phy) addressbits = len(pads.a) bankbits = len(pads.ba) nranks = 1 if not hasattr(pads, "cs_n") else len(pads.cs_n) databits = len(pads.dq) nphases = 4 self.settings = PhySettings(memtype="DDR3", dfi_databits=2 * databits, nranks=nranks, nphases=nphases, rdphase=0, wrphase=1, rdcmdphase=1, wrcmdphase=0, cl=5, cwl=6, read_latency=6 // 2 + 1, write_latency=2 // 2) self.dfi = Interface(addressbits, bankbits, nranks, 2 * databits, nphases) self.clk8x_wr_strb = half_rate_phy.clk4x_wr_strb self.clk8x_rd_strb = half_rate_phy.clk4x_rd_strb # sys_clk : system clk, used for dfi interface # sys2x_clk : 2x system clk sd_sys = getattr(self.sync, "sys") sd_sys2x = getattr(self.sync, "sys2x") # select active sys2x phase # sys_clk ----____----____ # phase_sel 0 1 0 1 phase_sel = Signal() phase_sys2x = Signal.like(phase_sel) phase_sys = Signal.like(phase_sys2x) sd_sys += phase_sys.eq(phase_sys2x) sd_sys2x += [ If( phase_sys2x == phase_sys, phase_sel.eq(0), ).Else(phase_sel.eq(~phase_sel)), phase_sys2x.eq(~phase_sel) ] # DFI adaptation # Commands and writes dfi_omit = set(["rddata", "rddata_valid", "wrdata_en"]) self.comb += [ If( ~phase_sel, self.dfi.phases[0].connect(half_rate_phy.dfi.phases[0], omit=dfi_omit), self.dfi.phases[1].connect(half_rate_phy.dfi.phases[1], omit=dfi_omit), ).Else( self.dfi.phases[2].connect(half_rate_phy.dfi.phases[0], omit=dfi_omit), self.dfi.phases[3].connect(half_rate_phy.dfi.phases[1], omit=dfi_omit), ), ] wr_data_en = self.dfi.phases[ self.settings.wrphase].wrdata_en & ~phase_sel wr_data_en_d = Signal() sd_sys2x += wr_data_en_d.eq(wr_data_en) self.comb += half_rate_phy.dfi.phases[ half_rate_phy.settings.wrphase].wrdata_en.eq(wr_data_en | wr_data_en_d) # Reads rddata = Array(Signal(2 * databits) for i in range(2)) rddata_valid = Signal(2) for i in range(2): sd_sys2x += [ rddata_valid[i].eq(half_rate_phy.dfi.phases[i].rddata_valid), rddata[i].eq(half_rate_phy.dfi.phases[i].rddata) ] sd_sys += [ self.dfi.phases[0].rddata.eq(rddata[0]), self.dfi.phases[0].rddata_valid.eq(rddata_valid[0]), self.dfi.phases[1].rddata.eq(rddata[1]), self.dfi.phases[1].rddata_valid.eq(rddata_valid[1]), self.dfi.phases[2].rddata.eq(half_rate_phy.dfi.phases[0].rddata), self.dfi.phases[2].rddata_valid.eq( half_rate_phy.dfi.phases[0].rddata_valid), self.dfi.phases[3].rddata.eq(half_rate_phy.dfi.phases[1].rddata), self.dfi.phases[3].rddata_valid.eq( half_rate_phy.dfi.phases[1].rddata_valid) ]
def __init__(self): self.specials += self.data_t self.isRxCmd = Signal() self.rx_data = Signal(8) rx_fifo_we = Signal() self.debug = Signal(8) past_rx_cmd = Signal(8) current_rx_cmd = Signal(8) # ULPI Register Write signals. USB clock domain ulpi_reg_wr_addr = Signal(6) ulpi_reg_wr_data = Signal(8) ulpi_reg_wr_trig = Signal() ulpi_reg_wr_busy = Signal() ulpi_reg_wr_done = Signal() ulpi_reg_wr_queue = Signal() # ULPI Register Read signals. USB clock domain ulpi_reg_rd_addr = Signal(6) ulpi_reg_rd_data = Signal(8) ulpi_reg_rd_trig = Signal() ulpi_reg_rd_busy = Signal() ulpi_reg_rd_done = Signal() ulpi_reg_rd_queue = Signal() self.sync.usb += [ If(ulpi_reg_wr_trig, ulpi_reg_wr_queue.eq(1)), If(ulpi_reg_rd_trig, ulpi_reg_rd_queue.eq(1)), ] fsm = self.fsm = ClockDomainsRenamer("usb")(FSM(reset_state="RESET")) self.submodules += fsm fsm.act( "RESET", If( ~self.dir, NextValue(self.data_t.o, 0x00), NextState("IDLE"), )) fsm.act( "IDLE", If( self.dir, # & self.nxt, NextState("RX")).Elif( ulpi_reg_wr_queue, NextState("REG_WR_CMD"), NextValue( self.data_t.o, Cat(ulpi_reg_wr_addr, Constant(value=2, bits_sign=2))), NextValue(ulpi_reg_wr_queue, 0), NextValue(ulpi_reg_wr_busy, 1), NextValue(ulpi_reg_wr_done, 0), ).Elif( ulpi_reg_rd_queue, NextState("REG_RD_CMD"), NextValue( self.data_t.o, Cat(ulpi_reg_rd_addr, Constant(value=3, bits_sign=2))), NextValue(ulpi_reg_rd_queue, 0), NextValue(ulpi_reg_rd_busy, 1), NextValue(ulpi_reg_rd_done, 0), )) fsm.act( "RX", NextValue(self.isRxCmd, 0x0), If( self.dir & ~self.nxt, NextValue(self.rx_data, self.data_t.i), NextValue(self.isRxCmd, 0x1), ).Elif(self.dir & self.nxt, NextValue(self.rx_data, self.data_t.i)).Elif( ~self.dir & ~self.nxt, NextState("IDLE"), )) fsm.act( "REG_WR_CMD", If( ~self.dir & self.nxt, NextState("REG_WR_DATA"), NextValue(self.data_t.o, ulpi_reg_wr_data), ).Elif( self.dir, # & self.nxt, NextState( "RX"), # Reg write aborted during Reg Write TXCMD cycle NextValue(self.data_t.o, 0x00), )) fsm.act( "REG_WR_DATA", If( ~self.dir & self.nxt, NextState("REG_WR_STP"), NextValue(self.stp, 1), ).Elif( self.dir & self.nxt, NextState("RX"), # Reg write aborted during write data cycle ), NextValue(self.data_t.o, 0x00), ) fsm.act( "REG_WR_STP", If( ~self.dir & ~self.nxt, NextState("IDLE"), ).Elif( self.dir & self.nxt, NextState( "RX" ), # Register write followed immediately by a USB receive during stp assertion ), NextValue(self.data_t.o, 0x00), NextValue(ulpi_reg_wr_busy, 0), NextValue(ulpi_reg_wr_done, 1), ) fsm.act( "REG_RD_CMD", If( self.nxt & ~self.dir, NextState("REG_RD_TURNAROUND"), ).Elif( self.nxt & self. dir, # Reg read aborted by PHY during TX_CMD due to receive NextState("RX"), NextValue(self.data_t.o, 0x00), ), ) fsm.act( "REG_RD_TURNAROUND", If( self.dir & self. nxt, # Reg read aborted by PHY during turnaround due to receive NextState("RX")).Elif( self.dir & ~self.nxt, NextState("REG_RD_DATA"), ), NextValue(self.data_t.o, 0x00), ) fsm.act( "REG_RD_DATA", If( self.dir & ~self.nxt, NextState("RX"), NextValue(ulpi_reg_rd_data, self.data_t.i), NextValue(ulpi_reg_rd_busy, 0), NextValue(ulpi_reg_rd_done, 1), )) self.sync.usb += [ If(self.dir & ~self.nxt & fsm.ongoing("RX"), past_rx_cmd.eq(current_rx_cmd), current_rx_cmd.eq(self.data_t.i)) ] se0 = Signal() j_state = Signal() k_state = Signal() se1 = Signal() squelch = Signal() n_squelch = Signal() FULL_SPEED = 0 HIGH_SPEED = 1 mode = FULL_SPEED # 0: Full Speed, 1: High Speed self.comb += [ se0.eq((current_rx_cmd[0:2] == 0b00) & (mode == FULL_SPEED)), j_state.eq((current_rx_cmd[0:2] == 0b01) & (mode == FULL_SPEED)), k_state.eq((current_rx_cmd[0:2] == 0b10) & (mode == FULL_SPEED)), se1.eq((current_rx_cmd[0:2] == 0b11) & (mode == FULL_SPEED)), squelch.eq((current_rx_cmd[0:2] == 0b00) & (mode == HIGH_SPEED)), n_squelch.eq((current_rx_cmd[0:2] == 0b01) & (mode == HIGH_SPEED)), ] rx_fifo = self.rx_fifo = ClockDomainsRenamer("usb")( SyncFIFO(9, 20480) ) # ClockDomainsRenamer({"write": "usb", "read": "sys"})(AsyncFIFO(9, 2048)) self.submodules += rx_fifo self.sync.usb += [ self.stp.eq( 0 ), # ~rx_fifo.writable) # No need to stop. Always receive unless FIFO full. FIXME stp rx_fifo.we.eq( rx_fifo_we ) # Delay we assertion since we are delaying data too in fsm's NextValue ] self.comb += [ self.data_t.oe.eq(~self.dir), # Tristate output enable rx_fifo_we.eq(fsm.ongoing("RX") & self.dir & rx_fifo.writable), rx_fifo.din.eq(Cat(self.rx_data, self.isRxCmd)), # rx_fifo.we.eq(fsm.ongoing("RX") & self.dir & rx_fifo.writable) ] self.attach_axi_slave(16) self.comb += [ self.axi_reg[0].data_r.eq( Cat(rx_fifo.dout[:8], Constant(0, bits_sign=23), rx_fifo.dout[8])), self.axi_reg[0].readable.eq(rx_fifo.readable), rx_fifo.re.eq(self.axi_reg[0].re), self.axi_reg[1].data_r.eq(rx_fifo.readable), # ULPI Register ulpi_reg_wr_addr.eq(self.axi_reg[2].data_w[0:6]), ulpi_reg_wr_data.eq(self.axi_reg[3].data_w[0:8]), ulpi_reg_wr_trig.eq(self.get_rising_edge( self.axi_reg[4].data_w[0])), self.axi_reg[5].data_r.eq(Cat(ulpi_reg_wr_busy, ulpi_reg_wr_done)), ulpi_reg_rd_addr.eq(self.axi_reg[6].data_w[0:6]), self.axi_reg[7].data_r.eq(ulpi_reg_rd_data), ulpi_reg_rd_trig.eq(self.get_rising_edge( self.axi_reg[8].data_w[0])), self.axi_reg[9].data_r.eq(Cat(ulpi_reg_rd_busy, ulpi_reg_rd_done)), ] self.comb += [self.axi_reg[i].writable.eq(1) for i in range(16)] # self.comb += [ # self.debug.eq(Cat(ulpi_reg_rd_busy, ulpi_reg_rd_done, ulpi_reg_rd_trig, ulpi_reg_rd_queue, ulpi_reg_wr_busy, ulpi_reg_wr_done, ulpi_reg_wr_trig, ulpi_reg_wr_queue)) # ] self.sync.usb += [ If(ulpi_reg_wr_trig, self.debug[0].eq(1)), If(ulpi_reg_rd_trig, self.debug[1].eq(1)), ]
def export_async(config, filename='top'): print("Adding async FIFOs to external network interfaces") m = [ Core( config, i * config.addresslayout.num_pe_per_fpga, min((i + 1) * config.addresslayout.num_pe_per_fpga, config.addresslayout.num_pe)) for i in range(config.addresslayout.num_fpga) ] for core in m: core.clock_domains.cd_sys = ClockDomain(reset_less=True) core.clock_domains.cd_ext = ClockDomain(reset_less=True) core.submodules.asyncfifos_in = [ ClockDomainsRenamer({ "write": "ext", "read": "sys" })(AsyncFIFOBuffered(width=layout_len( core.network.external_network_interface_in[j].layout), depth=16)) for j in range(config.addresslayout.num_channels) ] core.submodules.asyncfifos_out = [ ClockDomainsRenamer({ "write": "sys", "read": "ext" })(AsyncFIFOBuffered(width=layout_len( core.network.external_network_interface_in[j].layout), depth=16)) for j in range(config.addresslayout.num_channels) ] core.external_network_interface_in = [ NetworkInterface(name="ext_network_in", **config.addresslayout.get_params()) for _ in range(config.addresslayout.num_channels) ] core.external_network_interface_out = [ NetworkInterface(name="ext_network_out", **config.addresslayout.get_params()) for _ in range(config.addresslayout.num_channels) ] for j in range(config.addresslayout.num_channels): core.comb += [ core.asyncfifos_in[j].din.eq( core.external_network_interface_in[j].raw_bits()), core.asyncfifos_in[j].we.eq( core.external_network_interface_in[j].valid), core.external_network_interface_in[j].ack.eq( core.asyncfifos_in[j].writable) ] core.comb += [ core.network.external_network_interface_in[j].raw_bits().eq( core.asyncfifos_in[j].dout), core.network.external_network_interface_in[j].valid.eq( core.asyncfifos_in[j].readable), core.asyncfifos_in[j].re.eq( core.network.external_network_interface_in[j].ack) ] core.comb += [ core.asyncfifos_out[j].din.eq( core.network.external_network_interface_out[j].raw_bits()), core.asyncfifos_out[j].we.eq( core.network.external_network_interface_out[j].valid), core.network.external_network_interface_out[j].ack.eq( core.asyncfifos_out[j].writable) ] core.comb += [ core.external_network_interface_out[j].raw_bits().eq( core.asyncfifos_out[j].dout), core.external_network_interface_out[j].valid.eq( core.asyncfifos_out[j].readable), core.asyncfifos_out[j].re.eq( core.external_network_interface_out[j].ack) ] for i in range(config.addresslayout.num_fpga): iname = filename + "_" + str(i) os.makedirs(iname, exist_ok=True) with cd(iname): ios = { m[i].start, m[i].done, m[i].cycle_count, m[i].total_num_messages, m[i].level, m[i].kernel_error, m[i].cd_sys.clk, m[i].cd_ext.clk } for j in range(config.addresslayout.num_channels): ios |= set(m[i].external_network_interface_in[j].flatten()) ios |= set(m[i].external_network_interface_out[j].flatten()) # debug signals for a in m[i].network.arbiter: ios.add(a.barriercounter.all_messages_recvd) ios.add(a.barriercounter.all_barriers_recvd) # ios |= set(a.barriercounter.barrier_from_pe) # ios |= set(a.barriercounter.num_from_pe) # ios |= set(a.barriercounter.num_expected_from_pe) ios.add(m[i].network.local_network_round) verilog.convert(m[i], name="top", ios=ios).write(iname + ".v")