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) 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 = 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) obuffer = Signal(width) sync_i += If(self._pong.o, ibuffer.eq(self.i)) self.specials += MultiReg(ibuffer, obuffer, odomain) sync_o += If(self._ping.o, self.o.eq(obuffer))
def __init__(self, clock_pads, pads, with_hw_init_reset): self._reset = CSRStorage() # # # self.clock_domains.cd_eth_rx = ClockDomain() self.clock_domains.cd_eth_tx = ClockDomain() # RX dcm_reset = Signal() dcm_locked = Signal() timer = WaitTimer(1024) fsm = FSM(reset_state="DCM_RESET") self.submodules += timer, fsm fsm.act("DCM_RESET", dcm_reset.eq(1), timer.wait.eq(1), If(timer.done, timer.wait.eq(0), NextState("DCM_WAIT"))) fsm.act("DCM_WAIT", timer.wait.eq(1), If(timer.done, NextState("DCM_CHECK_LOCK"))) fsm.act("DCM_CHECK_LOCK", If(~dcm_locked, NextState("DCM_RESET"))) clk90_rx = Signal() clk0_rx = Signal() clk0_rx_bufg = Signal() self.specials += Instance("DCM", i_CLKIN=clock_pads.rx, i_CLKFB=clk0_rx_bufg, o_CLK0=clk0_rx, o_CLK90=clk90_rx, o_LOCKED=dcm_locked, i_PSEN=0, i_PSCLK=0, i_PSINCDEC=0, i_RST=dcm_reset) self.specials += Instance("BUFG", i_I=clk0_rx, o_O=clk0_rx_bufg) self.specials += Instance("BUFG", i_I=clk90_rx, o_O=self.cd_eth_rx.clk) # TX self.specials += DDROutput(1, 0, clock_pads.tx, ClockSignal("eth_tx")) self.specials += Instance("BUFG", i_I=self.cd_eth_rx.clk, o_O=self.cd_eth_tx.clk) # Reset reset = Signal() if with_hw_init_reset: self.submodules.hw_reset = LiteEthPHYHWReset() self.comb += reset.eq(self._reset.storage | self.hw_reset.reset) else: self.comb += reset.eq(self._reset.storage) self.comb += pads.rst_n.eq(~reset) self.specials += [ AsyncResetSynchronizer(self.cd_eth_tx, reset), AsyncResetSynchronizer(self.cd_eth_rx, reset), ]
def __init__(self, clk_freq, timeout=10): self.sink = sink = stream.Endpoint(phy_description(32)) self.source = source = stream.Endpoint(user_description(32)) # # # # Packet description # - preamble : 4 bytes # - length : 4 bytes # - payload fsm = FSM(reset_state="IDLE") self.submodules += fsm self.submodules.timer = WaitTimer(clk_freq*timeout) self.comb += self.timer.wait.eq(~fsm.ongoing("IDLE")) fsm.act("IDLE", sink.ready.eq(1), If(sink.valid & (sink.data == 0x5aa55aa5), NextState("RECEIVE_LENGTH") ) ) fsm.act("RECEIVE_LENGTH", sink.ready.eq(1), If(sink.valid, NextValue(source.length, sink.data), NextState("COPY") ) ) last = Signal() cnt = Signal(32) fsm.act("COPY", source.valid.eq(sink.valid), source.last.eq(last), source.data.eq(sink.data), sink.ready.eq(source.ready), If((source.valid & source.ready & last) | self.timer.done, NextState("IDLE") ) ) self.sync += \ If(fsm.ongoing("IDLE"), cnt.eq(0) ).Elif(source.valid & source.ready, cnt.eq(cnt + 1) ) self.comb += last.eq(cnt == source.length[2:] - 1)
def __init__(self): self.sink = sink = stream.Endpoint(phy_description(32)) # # # self.submodules.timer = WaitTimer(256 * 16) charisk_match = sink.charisk == 0b0001 data_match = sink.data == primitives["ALIGN"] self.comb += \ If(sink.valid & (sink.charisk == 0b0001) & (sink.data == primitives["ALIGN"]), self.timer.wait.eq(0) ).Else( self.timer.wait.eq(1), )
def __init__(self, settings): # 1st command 1 cycle after assertion of ready self.cmd = cmd = stream.Endpoint( cmd_request_rw_layout(settings.geom.addressbits, settings.geom.bankbits)) # # # # Refresh sequence generator: # PRECHARGE ALL --(tRP)--> AUTO REFRESH --(tRFC)--> done seq_start = Signal() seq_done = Signal() self.sync += [ cmd.a.eq(2**10), cmd.ba.eq(0), cmd.cas.eq(0), cmd.ras.eq(0), cmd.we.eq(0), seq_done.eq(0) ] self.sync += timeline(seq_start, [ (1, [cmd.ras.eq(1), cmd.we.eq(1)]), (1 + settings.timing.tRP, [cmd.cas.eq(1), cmd.ras.eq(1)]), (1 + settings.timing.tRP + settings.timing.tRFC, [seq_done.eq(1)]) ]) # Periodic refresh counter self.submodules.timer = WaitTimer(settings.timing.tREFI) self.comb += self.timer.wait.eq(settings.with_refresh & ~self.timer.done) # Control FSM self.submodules.fsm = fsm = FSM() fsm.act("IDLE", If(self.timer.done, NextState("WAIT_GRANT"))) fsm.act("WAIT_GRANT", cmd.valid.eq(1), If(cmd.ready, seq_start.eq(1), NextState("WAIT_SEQ"))) fsm.act( "WAIT_SEQ", If(seq_done, cmd.last.eq(1), NextState("IDLE")).Else(cmd.valid.eq(1)))
def __init__(self, platform, clk_freq): switches = Signal(1) leds = Signal(2) self.reset = Signal() # # # self.submodules.switches = GPIOIn(switches) self.submodules.leds = GPIOOut(leds) self.comb += [ switches[0].eq(~platform.request("pwrsw")), platform.request("hdled").eq(~leds[0]), platform.request("pwled").eq(~leds[1]), ] # generate a reset when power switch is pressed for 1 second self.submodules.reset_timer = WaitTimer(clk_freq) self.comb += [ self.reset_timer.wait.eq(switches[0]), self.reset.eq(self.reset_timer.done) ]
def __init__(self, clock_pads_or_refclk, pads, gtx, revision, clk_freq): self.tx_reset = Signal() self.rx_reset = Signal() self.ready = Signal() self.cplllock = Signal() self.clock_domains.cd_sata_tx = ClockDomain() self.clock_domains.cd_sata_rx = ClockDomain() # CPLL # (sata_gen3) 150MHz / VCO @ 3GHz / Line rate @ 6Gbps # (sata_gen2 & sata_gen1) VCO still @ 3 GHz, Line rate is # decreased with output dividers. if isinstance(clock_pads_or_refclk, Signal): self.refclk = clock_pads_or_refclk else: self.refclk = Signal() clock_pads = clock_pads_or_refclk self.specials += Instance("IBUFDS_GTE2", i_CEB=0, i_I=clock_pads.refclk_p, i_IB=clock_pads.refclk_n, o_O=self.refclk ) self.comb += gtx.gtrefclk0.eq(self.refclk) # TX clocking # (sata_gen3) 150MHz from CPLL TXOUTCLK, sata_tx clk @ 300MHz (16-bits) / 150MHz (32-bits) # (sata_gen2) 150MHz from CPLL TXOUTCLK, sata_tx clk @ 150MHz (16-bits) / 75MHz (32-bits) # (sata_gen1) 150MHz from CPLL TXOUTCLK, sata_tx clk @ 75MHz (16-bits) / 37.5MHz (32-bits) mmcm_mult = 8.0 mmcm_div_config = { "sata_gen1": 16.0*gtx.dw/16, "sata_gen2": 8.0*gtx.dw/16, "sata_gen3": 4.0*gtx.dw/16 } mmcm_div = mmcm_div_config[revision] use_mmcm = mmcm_mult/mmcm_div != 1.0 if use_mmcm: mmcm_reset = Signal() mmcm_locked_async = Signal() mmcm_locked = Signal() mmcm_fb = Signal() mmcm_clk_i = Signal() mmcm_clk0_o = Signal() self.specials += [ Instance("BUFG", i_I=gtx.txoutclk, o_O=mmcm_clk_i), Instance("MMCME2_ADV", p_BANDWIDTH="HIGH", p_COMPENSATION="ZHOLD", i_RST=mmcm_reset, o_LOCKED=mmcm_locked_async, # DRP i_DCLK=0, i_DEN=0, i_DWE=0, #o_DRDY=, i_DADDR=0, i_DI=0, #o_DO=, # VCO p_REF_JITTER1=0.01, p_CLKIN1_PERIOD=6.66667, p_CLKFBOUT_MULT_F=mmcm_mult, p_CLKFBOUT_PHASE=0.000, p_DIVCLK_DIVIDE=1, i_CLKIN1=mmcm_clk_i, i_CLKFBIN=mmcm_fb, o_CLKFBOUT=mmcm_fb, # CLK0 p_CLKOUT0_DIVIDE_F=mmcm_div, p_CLKOUT0_PHASE=0.000, o_CLKOUT0=mmcm_clk0_o, ), Instance("BUFG", i_I=mmcm_clk0_o, o_O=self.cd_sata_tx.clk), MultiReg(mmcm_locked_async, mmcm_locked, "sys"), ] else: mmcm_locked = Signal(reset=1) mmcm_reset = Signal() self.specials += Instance("BUFG", i_I=gtx.txoutclk, o_O=self.cd_sata_tx.clk) self.comb += [ gtx.txusrclk.eq(self.cd_sata_tx.clk), gtx.txusrclk2.eq(self.cd_sata_tx.clk) ] # RX clocking # (sata_gen3) sata_rx recovered clk @ @ 300MHz (16-bits) / 150MHz (32-bits) from GTX RXOUTCLK # (sata_gen2) sata_rx recovered clk @ @ 150MHz (16-bits) / 75MHz (32-bits) from GTX RXOUTCLK # (sata_gen1) sata_rx recovered clk @ @ 75MHz (16-bits) / 37.5MHz (32-bits) from GTX RXOUTCLK self.specials += [ Instance("BUFG", i_I=gtx.rxoutclk, o_O=self.cd_sata_rx.clk), ] self.comb += [ gtx.rxusrclk.eq(self.cd_sata_rx.clk), gtx.rxusrclk2.eq(self.cd_sata_rx.clk) ] # Configuration Reset # After configuration, GTX's resets have to stay low for at least 500ns # See AR43482 startup_cycles = ceil(500*clk_freq/1000000000) startup_timer = WaitTimer(startup_cycles) self.submodules += startup_timer self.comb += startup_timer.wait.eq(~(self.tx_reset | self.rx_reset)) # TX Startup FSM self.tx_ready = Signal() self.tx_startup_fsm = tx_startup_fsm = ResetInserter()(FSM(reset_state="IDLE")) self.submodules += tx_startup_fsm txphaligndone = Signal(reset=1) txphaligndone_rising = Signal() self.sync += txphaligndone.eq(gtx.txphaligndone) self.comb += txphaligndone_rising.eq(gtx.txphaligndone & ~txphaligndone) # Wait 500ns of AR43482 tx_startup_fsm.act("IDLE", If(startup_timer.done, NextState("RESET_ALL") ) ) # Reset CPLL, MMCM, GTX tx_startup_fsm.act("RESET_ALL", gtx.cpllreset.eq(1), mmcm_reset.eq(1), gtx.gttxreset.eq(1), If(~self.cplllock, NextState("RELEASE_CPLL") ) ) # Release CPLL reset and wait for lock tx_startup_fsm.act("RELEASE_CPLL", mmcm_reset.eq(1), gtx.gttxreset.eq(1), If(self.cplllock, NextState("RELEASE_MMCM") ) ) # Release MMCM reset and wait for lock tx_startup_fsm.act("RELEASE_MMCM", gtx.gttxreset.eq(1), If(mmcm_locked, NextState("RELEASE_GTX") ) ) # Release GTX reset and wait for GTX resetdone # (from UG476, GTX is reseted on falling edge # of gttxreset) tx_startup_fsm.act("RELEASE_GTX", gtx.txuserrdy.eq(1), If(gtx.txresetdone, NextState("ALIGN") ) ) # Start Delay alignment (Pulse) tx_startup_fsm.act("ALIGN", gtx.txuserrdy.eq(1), gtx.txdlyreset.eq(1), NextState("WAIT_ALIGN") ) # Wait Delay alignment tx_startup_fsm.act("WAIT_ALIGN", gtx.txuserrdy.eq(1), If(gtx.txdlyresetdone, NextState("WAIT_FIRST_ALIGN_DONE") ) ) # Wait 2 rising edges of txphaligndone # (from UG476 in buffer bypass config) tx_startup_fsm.act("WAIT_FIRST_ALIGN_DONE", gtx.txuserrdy.eq(1), If(txphaligndone_rising, NextState("WAIT_SECOND_ALIGN_DONE") ) ) tx_startup_fsm.act("WAIT_SECOND_ALIGN_DONE", gtx.txuserrdy.eq(1), If(txphaligndone_rising, NextState("READY") ) ) tx_startup_fsm.act("READY", gtx.txuserrdy.eq(1), self.tx_ready.eq(1) ) tx_ready_timer = WaitTimer(2*clk_freq//1000) self.submodules += tx_ready_timer self.comb += [ tx_ready_timer.wait.eq(~self.tx_ready & ~tx_startup_fsm.reset), tx_startup_fsm.reset.eq(self.tx_reset | tx_ready_timer.done), ] # RX Startup FSM self.rx_ready = Signal() self.rx_startup_fsm = rx_startup_fsm = ResetInserter()(FSM(reset_state="IDLE")) self.submodules += rx_startup_fsm cdr_stable_timer = WaitTimer(1024) self.submodules += cdr_stable_timer rxphaligndone = Signal(reset=1) rxphaligndone_rising = Signal() self.sync += rxphaligndone.eq(gtx.rxphaligndone) self.comb += rxphaligndone_rising.eq(gtx.rxphaligndone & ~rxphaligndone) # Wait 500ns of AR43482 rx_startup_fsm.act("IDLE", If(startup_timer.done, NextState("RESET_GTX") ) ) # Reset GTX rx_startup_fsm.act("RESET_GTX", gtx.gtrxreset.eq(1), If(~gtx.gttxreset, NextState("WAIT_CPLL") ) ) # Wait for CPLL lock rx_startup_fsm.act("WAIT_CPLL", gtx.gtrxreset.eq(1), If(self.cplllock, NextState("RELEASE_GTX") ) ) # Release GTX reset and wait for GTX resetdone # (from UG476, GTX is reseted on falling edge # of gttxreset) rx_startup_fsm.act("RELEASE_GTX", gtx.rxuserrdy.eq(1), cdr_stable_timer.wait.eq(1), If(gtx.rxresetdone & cdr_stable_timer.done, NextState("ALIGN") ) ) # Start Delay alignment (Pulse) rx_startup_fsm.act("ALIGN", gtx.rxuserrdy.eq(1), gtx.rxdlyreset.eq(1), NextState("WAIT_ALIGN") ) # Wait Delay alignment rx_startup_fsm.act("WAIT_ALIGN", gtx.rxuserrdy.eq(1), If(gtx.rxdlyresetdone, NextState("WAIT_FIRST_ALIGN_DONE") ) ) # Wait 2 rising edges of rxphaligndone # (from UG476 in buffer bypass config) rx_startup_fsm.act("WAIT_FIRST_ALIGN_DONE", gtx.rxuserrdy.eq(1), If(rxphaligndone_rising, NextState("WAIT_SECOND_ALIGN_DONE") ) ) rx_startup_fsm.act("WAIT_SECOND_ALIGN_DONE", gtx.rxuserrdy.eq(1), If(rxphaligndone_rising, NextState("READY") ) ) rx_startup_fsm.act("READY", gtx.rxuserrdy.eq(1), self.rx_ready.eq(1) ) rx_ready_timer = WaitTimer(2*clk_freq//1000) self.submodules += rx_ready_timer self.comb += [ rx_ready_timer.wait.eq(~self.rx_ready & ~rx_startup_fsm.reset), rx_startup_fsm.reset.eq(self.rx_reset | rx_ready_timer.done), ] # Ready self.comb += self.ready.eq(self.tx_ready & self.rx_ready) # Reset for SATA TX/RX clock domains self.specials += [ AsyncResetSynchronizer(self.cd_sata_tx, ~(gtx.cplllock & mmcm_locked) | self.tx_reset), AsyncResetSynchronizer(self.cd_sata_rx, ~gtx.cplllock | self.rx_reset), MultiReg(gtx.cplllock, self.cplllock, "sys"), ]
def __init__(self, phy_settings, geom_settings, timing_settings): if phy_settings.memtype in ["SDR"]: burst_length = phy_settings.nphases * 1 # command multiplication*SDR elif phy_settings.memtype in ["DDR", "LPDDR", "DDR2", "DDR3"]: burst_length = phy_settings.nphases * 2 # command multiplication*DDR burst_width = phy_settings.dfi_databits * phy_settings.nphases address_align = log2_int(burst_length) # # # self.dfi = dfi = dfibus.Interface(geom_settings.addressbits, geom_settings.bankbits, phy_settings.dfi_databits, phy_settings.nphases) self.bus = bus = wishbone.Interface(burst_width) rdphase = phy_settings.rdphase wrphase = phy_settings.wrphase precharge_all = Signal() activate = Signal() refresh = Signal() write = Signal() read = Signal() # Compute current column, bank and row from wishbone address slicer = _AddressSlicer(geom_settings.colbits, geom_settings.bankbits, geom_settings.rowbits, address_align) # Manage banks bank_idle = Signal() bank_hit = Signal() banks = [] for i in range(2**geom_settings.bankbits): bank = _Bank(geom_settings) self.comb += [ bank.open.eq(activate), bank.reset.eq(precharge_all), bank.row.eq(slicer.row(bus.adr)) ] banks.append(bank) self.submodules += banks cases = {} for i, bank in enumerate(banks): cases[i] = [bank.ce.eq(1)] self.comb += Case(slicer.bank(bus.adr), cases) self.comb += [ bank_hit.eq(reduce(or_, [bank.hit & bank.ce for bank in banks])), bank_idle.eq(reduce(or_, [bank.idle & bank.ce for bank in banks])), ] # Timings write2precharge_timer = WaitTimer(2 + timing_settings.tWR - 1) self.submodules += write2precharge_timer self.comb += write2precharge_timer.wait.eq(~write) refresh_timer = WaitTimer(timing_settings.tREFI) self.submodules += refresh_timer self.comb += refresh_timer.wait.eq(~refresh) # Main FSM self.submodules.fsm = fsm = FSM() fsm.act( "IDLE", If(refresh_timer.done, NextState("PRECHARGE-ALL")).Elif( bus.stb & bus.cyc, If(bank_hit, If(bus.we, NextState("WRITE")).Else(NextState("READ"))).Elif( ~bank_idle, If(write2precharge_timer.done, NextState("PRECHARGE"))).Else( NextState("ACTIVATE")))) fsm.act( "READ", read.eq(1), dfi.phases[rdphase].ras_n.eq(1), dfi.phases[rdphase].cas_n.eq(0), dfi.phases[rdphase].we_n.eq(1), dfi.phases[rdphase].rddata_en.eq(1), NextState("WAIT-READ-DONE"), ) fsm.act( "WAIT-READ-DONE", If(dfi.phases[rdphase].rddata_valid, bus.ack.eq(1), NextState("IDLE"))) fsm.act("WRITE", write.eq(1), dfi.phases[wrphase].ras_n.eq(1), dfi.phases[wrphase].cas_n.eq(0), dfi.phases[wrphase].we_n.eq(0), dfi.phases[wrphase].wrdata_en.eq(1), NextState("WRITE-LATENCY")) fsm.act("WRITE-ACK", bus.ack.eq(1), NextState("IDLE")) fsm.act("PRECHARGE-ALL", precharge_all.eq(1), dfi.phases[rdphase].ras_n.eq(0), dfi.phases[rdphase].cas_n.eq(1), dfi.phases[rdphase].we_n.eq(0), NextState("PRE-REFRESH")) fsm.act( "PRECHARGE", # do no reset bank since we are going to re-open it dfi.phases[0].ras_n.eq(0), dfi.phases[0].cas_n.eq(1), dfi.phases[0].we_n.eq(0), NextState("TRP")) fsm.act( "ACTIVATE", activate.eq(1), dfi.phases[0].ras_n.eq(0), dfi.phases[0].cas_n.eq(1), dfi.phases[0].we_n.eq(1), NextState("TRCD"), ) fsm.act("REFRESH", refresh.eq(1), dfi.phases[rdphase].ras_n.eq(0), dfi.phases[rdphase].cas_n.eq(0), dfi.phases[rdphase].we_n.eq(1), NextState("POST-REFRESH")) fsm.delayed_enter("WRITE-LATENCY", "WRITE-ACK", phy_settings.write_latency - 1) fsm.delayed_enter("TRP", "ACTIVATE", timing_settings.tRP - 1) fsm.delayed_enter("TRCD", "IDLE", timing_settings.tRCD - 1) fsm.delayed_enter("PRE-REFRESH", "REFRESH", timing_settings.tRP - 1) fsm.delayed_enter("POST-REFRESH", "IDLE", timing_settings.tRFC - 1) # DFI commands for phase in dfi.phases: if hasattr(phase, "reset_n"): self.comb += phase.reset_n.eq(1) if hasattr(phase, "odt"): self.comb += phase.odt.eq(1) self.comb += [ phase.cke.eq(1), phase.cs_n.eq(0), phase.bank.eq(slicer.bank(bus.adr)), If(precharge_all, phase.address.eq(2**10)).Elif( activate, phase.address.eq(slicer.row(bus.adr))).Elif( write | read, phase.address.eq(slicer.col(bus.adr))) ] # DFI datapath self.comb += [ bus.dat_r.eq(Cat(phase.rddata for phase in dfi.phases)), Cat(phase.wrdata for phase in dfi.phases).eq(bus.dat_w), Cat(phase.wrdata_mask for phase in dfi.phases).eq(~bus.sel), ]
def __init__(self, phy, clk_freq): self.wishbone = wishbone.Interface() # # # byte_counter = Signal(3) byte_counter_reset = Signal() byte_counter_ce = Signal() self.sync += \ If(byte_counter_reset, byte_counter.eq(0) ).Elif(byte_counter_ce, byte_counter.eq(byte_counter + 1) ) word_counter = Signal(3) word_counter_reset = Signal() word_counter_ce = Signal() self.sync += \ If(word_counter_reset, word_counter.eq(0) ).Elif(word_counter_ce, word_counter.eq(word_counter + 1) ) cmd = Signal(8) cmd_ce = Signal() length = Signal(8) length_ce = Signal() address = Signal(32) address_ce = Signal() data = Signal(32) rx_data_ce = Signal() tx_data_ce = Signal() self.sync += [ If(cmd_ce, cmd.eq(phy.source.data)), If(length_ce, length.eq(phy.source.data)), If(address_ce, address.eq(Cat(phy.source.data, address[0:24]))), If(rx_data_ce, data.eq(Cat(phy.source.data, data[0:24]))).Elif(tx_data_ce, data.eq(self.wishbone.dat_r)) ] fsm = ResetInserter()(FSM(reset_state="IDLE")) timer = WaitTimer(clk_freq // 10) self.submodules += fsm, timer self.comb += [fsm.reset.eq(timer.done), phy.source.ready.eq(1)] fsm.act( "IDLE", If( phy.source.valid, cmd_ce.eq(1), If((phy.source.data == self.cmds["write"]) | (phy.source.data == self.cmds["read"]), NextState("RECEIVE_LENGTH")), byte_counter_reset.eq(1), word_counter_reset.eq(1))) fsm.act( "RECEIVE_LENGTH", If(phy.source.valid, length_ce.eq(1), NextState("RECEIVE_ADDRESS"))) fsm.act( "RECEIVE_ADDRESS", If( phy.source.valid, address_ce.eq(1), byte_counter_ce.eq(1), If( byte_counter == 3, If(cmd == self.cmds["write"], NextState("RECEIVE_DATA")).Elif( cmd == self.cmds["read"], NextState("READ_DATA")), byte_counter_reset.eq(1), ))) fsm.act( "RECEIVE_DATA", If( phy.source.valid, rx_data_ce.eq(1), byte_counter_ce.eq(1), If(byte_counter == 3, NextState("WRITE_DATA"), byte_counter_reset.eq(1)))) self.comb += [ self.wishbone.adr.eq(address + word_counter), self.wishbone.dat_w.eq(data), self.wishbone.sel.eq(2**len(self.wishbone.sel) - 1) ] fsm.act( "WRITE_DATA", self.wishbone.stb.eq(1), self.wishbone.we.eq(1), self.wishbone.cyc.eq(1), If( self.wishbone.ack, word_counter_ce.eq(1), If(word_counter == (length - 1), NextState("IDLE")).Else(NextState("RECEIVE_DATA")))) fsm.act( "READ_DATA", self.wishbone.stb.eq(1), self.wishbone.we.eq(0), self.wishbone.cyc.eq(1), If(self.wishbone.ack, tx_data_ce.eq(1), NextState("SEND_DATA"))) self.comb += \ chooser(data, byte_counter, phy.sink.data, n=4, reverse=True) fsm.act( "SEND_DATA", phy.sink.valid.eq(1), If( phy.sink.ready, byte_counter_ce.eq(1), If( byte_counter == 3, word_counter_ce.eq(1), If(word_counter == (length - 1), NextState("IDLE")).Else(NextState("READ_DATA"), byte_counter_reset.eq(1))))) self.comb += timer.wait.eq(~fsm.ongoing("IDLE")) self.comb += phy.sink.last.eq((byte_counter == 3) & (word_counter == length - 1)) if hasattr(phy.sink, "length"): self.comb += phy.sink.length.eq(4 * length)
def __init__(self, clk_freq, timeout=10): self.sink = sink = stream.Endpoint(phy_description(8)) self.source = source = stream.Endpoint(user_description(8)) # # # # Packet description # - preamble : 4 bytes # - dst : 1 byte # - length : 4 bytes # - payload preamble = Array(Signal(8) for i in range(4)) header = [ # dst source.dst, # length source.length[24:32], source.length[16:24], source.length[8:16], source.length[0:8], ] header_pack = ResetInserter()(stream.Pack(phy_description(8), len(header))) self.submodules += header_pack for i, byte in enumerate(header): chunk = getattr(header_pack.source.payload, "chunk" + str(i)) self.comb += byte.eq(chunk.data) fsm = FSM(reset_state="IDLE") self.submodules += fsm self.comb += preamble[0].eq(sink.data) for i in range(1, 4): self.sync += If(sink.valid & sink.ready, preamble[i].eq(preamble[i - 1])) fsm.act( "IDLE", sink.ready.eq(1), If((preamble[3] == 0x5A) & (preamble[2] == 0xA5) & (preamble[1] == 0x5A) & (preamble[0] == 0xA5) & sink.valid, NextState("RECEIVE_HEADER")), header_pack.source.ready.eq(1), ) self.submodules.timer = WaitTimer(clk_freq * timeout) self.comb += self.timer.wait.eq(~fsm.ongoing("IDLE")) fsm.act( "RECEIVE_HEADER", header_pack.sink.valid.eq(sink.valid), header_pack.sink.payload.eq(sink.payload), If(self.timer.done, NextState("IDLE")).Elif( header_pack.source.valid, NextState("COPY")).Else(sink.ready.eq(1))) self.comb += header_pack.reset.eq(self.timer.done) last = Signal() cnt = Signal(32) fsm.act( "COPY", source.valid.eq(sink.valid), source.last.eq(last), source.data.eq(sink.data), sink.ready.eq(source.ready), If((source.valid & source.ready & last) | self.timer.done, NextState("IDLE"))) self.sync += \ If(fsm.ongoing("IDLE"), cnt.eq(0) ).Elif(source.valid & source.ready, cnt.eq(cnt + 1) ) self.comb += last.eq(cnt == source.length - 1)
def __init__(self, trx, crg, clk_freq): self.clk_freq = clk_freq self.ready = Signal() self.sink = sink = stream.Endpoint(phy_description(32)) self.source = source = stream.Endpoint(phy_description(32)) self.misalign = Signal() self.rx_idle = Signal() # # # self.comb += [ source.valid.eq(1), sink.ready.eq(1) ] retry_timer = WaitTimer(self.us(10000)) align_timer = WaitTimer(self.us(873)) self.submodules += align_timer, retry_timer align_det = Signal() misalign_det = Signal() non_align_counter = Signal(4) non_align_counter_reset = Signal() non_align_counter_ce = Signal() self.sync += \ If(non_align_counter_reset, non_align_counter.eq(0) ).Elif(non_align_counter_ce, non_align_counter.eq(non_align_counter + 1) ) self.comb += [ If(sink.valid, align_det.eq((self.sink.charisk == 0b0001) & (self.sink.data == primitives["ALIGN"])) ) ] self.fsm = fsm = ResetInserter()(FSM(reset_state="RESET")) self.submodules += fsm self.comb += fsm.reset.eq(retry_timer.done | align_timer.done) fsm.act("RESET", trx.tx_idle.eq(1), trx.rx_cdrhold.eq(1), crg.rx_reset.eq(1), crg.tx_reset.eq(1), NextState("AWAIT_CRG_RESET") ) fsm.act("AWAIT_CRG_RESET", trx.tx_idle.eq(1), trx.rx_cdrhold.eq(1), non_align_counter_reset.eq(1), If(crg.ready, NextState("COMINIT") ) ) fsm.act("COMINIT", trx.tx_idle.eq(1), trx.rx_cdrhold.eq(1), trx.tx_cominit_stb.eq(1), If(trx.tx_cominit_ack & ~trx.rx_cominit_stb, NextState("AWAIT_COMINIT") ) ) fsm.act("AWAIT_COMINIT", trx.tx_idle.eq(1), trx.rx_cdrhold.eq(1), retry_timer.wait.eq(1), If(trx.rx_cominit_stb, NextState("AWAIT_NO_COMINIT") ) ) fsm.act("AWAIT_NO_COMINIT", trx.tx_idle.eq(1), trx.rx_cdrhold.eq(1), retry_timer.wait.eq(1), If(~trx.rx_cominit_stb, NextState("CALIBRATE") ) ) fsm.act("CALIBRATE", trx.tx_idle.eq(1), trx.rx_cdrhold.eq(1), NextState("COMWAKE"), ) fsm.act("COMWAKE", trx.tx_idle.eq(1), trx.rx_cdrhold.eq(1), trx.tx_comwake_stb.eq(1), If(trx.tx_comwake_ack, NextState("AWAIT_COMWAKE") ) ) fsm.act("AWAIT_COMWAKE", trx.tx_idle.eq(1), trx.rx_cdrhold.eq(1), retry_timer.wait.eq(1), If(trx.rx_comwake_stb, NextState("AWAIT_NO_COMWAKE") ) ) fsm.act("AWAIT_NO_COMWAKE", trx.tx_idle.eq(1), trx.rx_cdrhold.eq(1), If(~trx.rx_comwake_stb, NextState("AWAIT_ALIGN") ) ) fsm.act("AWAIT_ALIGN", trx.rx_cdrhold.eq(1), source.data.eq(0x4A4A4A4A), # D10.2 source.charisk.eq(0b0000), align_timer.wait.eq(1), If(align_det & ~trx.rx_idle, crg.rx_reset.eq(1), NextState("SEND_ALIGN") ) ) fsm.act("SEND_ALIGN", align_timer.wait.eq(1), source.data.eq(primitives["ALIGN"]), source.charisk.eq(0b0001), If(sink.valid & (sink.charisk == 0b0001), If(sink.data[0:8] == 0x7C, non_align_counter_ce.eq(1) ).Else( non_align_counter_reset.eq(1) ) ), If(non_align_counter == 3, NextState("READY") ) ) # wait alignement stability for 5ms before declaring ctrl is ready, # reset the RX part of the transceiver when misalignment is detected. stability_timer = WaitTimer(5*clk_freq//1000) self.submodules += stability_timer fsm.act("READY", source.data.eq(primitives["SYNC"]), source.charisk.eq(0b0001), stability_timer.wait.eq(1), self.ready.eq(stability_timer.done), If(self.rx_idle, NextState("RESET"), ).Elif(self.misalign, crg.rx_reset.eq(1), NextState("RESET_RX") ) ) fsm.act("RESET_RX", If(crg.ready, NextState("READY") ) )
def __init__(self, sys_clk_freq, rx): self.done = Signal() self.restart = Signal() # GTX signals self.plllock = Signal() self.pllreset = Signal() self.gtXxreset = Signal() self.Xxresetdone = Signal() self.Xxdlysreset = Signal() self.Xxdlysresetdone = Signal() self.Xxphaligndone = Signal() self.Xxuserrdy = Signal() # # # # Double-latch transceiver asynch outputs plllock = Signal() Xxresetdone = Signal() Xxdlysresetdone = Signal() Xxphaligndone = Signal() self.specials += [ MultiReg(self.plllock, plllock), MultiReg(self.Xxresetdone, Xxresetdone), MultiReg(self.Xxdlysresetdone, Xxdlysresetdone), MultiReg(self.Xxphaligndone, Xxphaligndone) ] # Deglitch FSM outputs driving transceiver asynch inputs gtXxreset = Signal() Xxdlysreset = Signal() Xxuserrdy = Signal() self.sync += [ self.gtXxreset.eq(gtXxreset), self.Xxdlysreset.eq(Xxdlysreset), self.Xxuserrdy.eq(Xxuserrdy) ] # After configuration, transceiver resets have to stay low for # at least 500ns (see AR43482) startup_cycles = ceil(500 * sys_clk_freq / 1000000000) startup_timer = WaitTimer(startup_cycles) self.submodules += startup_timer startup_fsm = ResetInserter()(FSM(reset_state="RESET_ALL")) self.submodules += startup_fsm ready_timer = WaitTimer(1 * sys_clk_freq // 1000) self.submodules += ready_timer self.comb += [ ready_timer.wait.eq(~self.done & ~startup_fsm.reset), startup_fsm.reset.eq(self.restart | ready_timer.done) ] if rx: cdr_stable_timer = WaitTimer(1024) self.submodules += cdr_stable_timer Xxphaligndone_r = Signal(reset=1) Xxphaligndone_rising = Signal() self.sync += Xxphaligndone_r.eq(Xxphaligndone) self.comb += Xxphaligndone_rising.eq(Xxphaligndone & ~Xxphaligndone_r) startup_fsm.act("RESET_ALL", gtXxreset.eq(1), self.pllreset.eq(1), startup_timer.wait.eq(1), NextState("RELEASE_PLL_RESET")) startup_fsm.act( "RELEASE_PLL_RESET", gtXxreset.eq(1), startup_timer.wait.eq(1), If(plllock & startup_timer.done, NextState("RELEASE_GTX_RESET"))) # Release GTX reset and wait for GTX resetdone # (from UG476, GTX is reset on falling edge # of gtXxreset) if rx: startup_fsm.act( "RELEASE_GTX_RESET", Xxuserrdy.eq(1), cdr_stable_timer.wait.eq(1), If(Xxresetdone & cdr_stable_timer.done, NextState("ALIGN"))) else: startup_fsm.act("RELEASE_GTX_RESET", Xxuserrdy.eq(1), If(Xxresetdone, NextState("ALIGN"))) # Start delay alignment (pulse) startup_fsm.act("ALIGN", Xxuserrdy.eq(1), Xxdlysreset.eq(1), NextState("WAIT_ALIGN")) # Wait for delay alignment startup_fsm.act( "WAIT_ALIGN", Xxuserrdy.eq(1), If(Xxdlysresetdone, NextState("WAIT_FIRST_ALIGN_DONE"))) # Wait 2 rising edges of Xxphaligndone # (from UG476 in buffer bypass config) startup_fsm.act( "WAIT_FIRST_ALIGN_DONE", Xxuserrdy.eq(1), If(Xxphaligndone_rising, NextState("WAIT_SECOND_ALIGN_DONE"))) startup_fsm.act("WAIT_SECOND_ALIGN_DONE", Xxuserrdy.eq(1), If(Xxphaligndone_rising, NextState("READY"))) startup_fsm.act("READY", Xxuserrdy.eq(1), self.done.eq(1))
def __init__(self, platform, pads, data_width=64, bar0_size=1 * MB, cd="sys", pll1=None): self.sink = stream.Endpoint(phy_layout(data_width)) self.source = stream.Endpoint(phy_layout(data_width)) self.msi = stream.Endpoint(msi_layout()) self._lnk_up = CSRStatus() self._msi_enable = CSRStatus() self._bus_master_enable = CSRStatus() self._max_request_size = CSRStatus(16) self._max_payload_size = CSRStatus(16) self.data_width = data_width self.id = Signal(16) self.bar0_size = bar0_size self.bar0_mask = get_bar_mask(bar0_size) self.max_request_size = Signal(16) self.max_payload_size = Signal(16) # # # # clocking pcie_clk = Signal() pcie_rst = Signal() pcie_refclk = Signal() self.specials += Instance("IBUFDS_GTE2", i_CEB=0, i_I=pads.clk_p, i_IB=pads.clk_n, o_O=pcie_refclk) pcie_refclk.attr.add("keep") platform.add_period_constraint(pcie_refclk, 10.0) self.clock_domains.cd_pcie = ClockDomain() self.clock_domains.cd_pcie_reset_less = ClockDomain(reset_less=True) self.cd_pcie.clk.attr.add("keep") platform.add_period_constraint(self.cd_pcie.clk, 8.0) pcie_refclk_present = Signal() pcie_refclk_timer = ClockDomainsRenamer("pcie_reset_less")( WaitTimer(1024)) self.submodules += pcie_refclk_timer self.comb += [ pcie_refclk_timer.wait.eq(1), pcie_refclk_present.eq(pcie_refclk_timer.done) ] self.comb += [ self.cd_pcie.clk.eq(pcie_clk), self.cd_pcie.rst.eq(pcie_rst & pcie_refclk_present), self.cd_pcie_reset_less.clk.eq(pcie_clk), ] # tx cdc (fpga --> host) if cd == "pcie": s_axis_tx = self.sink else: tx_buffer = stream.Buffer(phy_layout(data_width)) tx_buffer = ClockDomainsRenamer(cd)(tx_buffer) tx_cdc = stream.AsyncFIFO(phy_layout(data_width), 4) tx_cdc = ClockDomainsRenamer({"write": cd, "read": "pcie"})(tx_cdc) self.submodules += tx_buffer, tx_cdc self.comb += [ self.sink.connect(tx_buffer.sink), tx_buffer.source.connect(tx_cdc.sink) ] s_axis_tx = tx_cdc.source # rx cdc (host --> fpga) if cd == "pcie": m_axis_rx = self.source else: rx_cdc = stream.AsyncFIFO(phy_layout(data_width), 4) rx_cdc = ClockDomainsRenamer({"write": "pcie", "read": cd})(rx_cdc) rx_buffer = stream.Buffer(phy_layout(data_width)) rx_buffer = ClockDomainsRenamer(cd)(rx_buffer) self.submodules += rx_buffer, rx_cdc self.comb += [ rx_cdc.source.connect(rx_buffer.sink), rx_buffer.source.connect(self.source) ] m_axis_rx = rx_cdc.sink # msi cdc (fpga --> host) if cd == "pcie": cfg_msi = self.msi else: msi_cdc = stream.AsyncFIFO(msi_layout(), 4) msi_cdc = ClockDomainsRenamer({ "write": cd, "read": "pcie" })(msi_cdc) self.submodules += msi_cdc self.comb += self.msi.connect(msi_cdc.sink) cfg_msi = msi_cdc.source # config def convert_size(command, size): cases = {} value = 128 for i in range(6): cases[i] = size.eq(value) value = value * 2 return Case(command, cases) lnk_up = Signal() msienable = Signal() bus_number = Signal(8) device_number = Signal(5) function_number = Signal(3) command = Signal(16) dcommand = Signal(16) self.sync.pcie += [ convert_size(dcommand[12:15], self.max_request_size), convert_size(dcommand[5:8], self.max_payload_size), self.id.eq(Cat(function_number, device_number, bus_number)) ] self.specials += [ MultiReg(lnk_up, self._lnk_up.status), MultiReg(command[2], self._bus_master_enable.status), MultiReg(msienable, self._msi_enable.status), MultiReg(self.max_request_size, self._max_request_size.status), MultiReg(self.max_payload_size, self._max_payload_size.status) ] # hard ip self.specials += Instance( "pcie_phy", p_C_DATA_WIDTH=data_width, p_C_PCIE_GT_DEVICE={ "xc7k": "GTX", "xc7a": "GTP" }[platform.device[:4]], p_C_BAR0=get_bar_mask(bar0_size), i_sys_clk=pcie_refclk, i_sys_rst_n=1 if not hasattr(pads, "rst_n") else pads.rst_n, o_pci_exp_txp=pads.tx_p, o_pci_exp_txn=pads.tx_n, i_pci_exp_rxp=pads.rx_p, i_pci_exp_rxn=pads.rx_n, o_user_clk=pcie_clk, o_user_reset=pcie_rst, o_user_lnk_up=lnk_up, #o_tx_buf_av=, #o_tx_terr_drop=, #o_tx_cfg_req=, i_tx_cfg_gnt=1, i_s_axis_tx_tvalid=s_axis_tx.valid, i_s_axis_tx_tlast=s_axis_tx.last, o_s_axis_tx_tready=s_axis_tx.ready, i_s_axis_tx_tdata=s_axis_tx.dat, i_s_axis_tx_tkeep=s_axis_tx.be, i_s_axis_tx_tuser=0, i_rx_np_ok=1, i_rx_np_req=1, o_m_axis_rx_tvalid=m_axis_rx.valid, o_m_axis_rx_tlast=m_axis_rx.last, i_m_axis_rx_tready=m_axis_rx.ready, o_m_axis_rx_tdata=m_axis_rx.dat, o_m_axis_rx_tkeep=m_axis_rx.be, #o_m_axis_rx_tuser=, #o_cfg_to_turnoff=, o_cfg_bus_number=bus_number, o_cfg_device_number=device_number, o_cfg_function_number=function_number, o_cfg_command=command, o_cfg_dcommand=dcommand, o_cfg_interrupt_msienable=msienable, i_cfg_interrupt=cfg_msi.valid, o_cfg_interrupt_rdy=cfg_msi.ready, i_cfg_interrupt_di=cfg_msi.dat, p_QPLL_PLL1_FBDIV=4 if pll1 is None else pll1.config["n2"], p_QPLL_PLL1_FBDIV_45=4 if pll1 is None else pll1.config["n1"], p_QPLL_PLL1_REFCLK_DIV=1 if pll1 is None else pll1.config["m"], i_QPLL_GTGREFCLK1=0 if pll1 is None else pll1.gtgrefclk, i_QPLL_GTREFCLK1=0 if pll1 is None else pll1.gtrefclk, i_QPLL_PLL1LOCKEN=1, i_QPLL_PLL1PD=1 if pll1 is None else 0, i_QPLL_PLL1REFCLKSEL=0b001 if pll1 is None else pll1.refclksel, i_QPLL_PLL1RESET=1 if pll1 is None else pll1.reset, o_QPLL_PLL1LOCK=Signal() if pll1 is None else pll1.lock, o_QPLL_PLL1OUTCLK=Signal() if pll1 is None else pll1.clk, o_QPLL_PLL1OUTREFCLK=Signal() if pll1 is None else pll1.refclk) litepcie_phy_path = os.path.abspath(os.path.dirname(__file__)) platform.add_source_dir( os.path.join(litepcie_phy_path, "xilinx", "7-series", "common")) if platform.device[:4] == "xc7k": platform.add_source_dir( os.path.join(litepcie_phy_path, "xilinx", "7-series", "kintex7")) elif platform.device[:4] == "xc7a": platform.add_source_dir( os.path.join(litepcie_phy_path, "xilinx", "7-series", "artix7"))
def __init__(self, sys_clk_freq, rx): self.done = Signal() self.restart = Signal() # GTH signals self.plllock = Signal() self.pllreset = Signal() self.gtXxreset = Signal() self.Xxresetdone = Signal() self.Xxdlysreset = Signal() self.Xxdlysresetdone = Signal() self.Xxphaligndone = Signal() self.Xxsyncdone = Signal() self.Xxuserrdy = Signal() # # # # Double-latch transceiver asynch outputs plllock = Signal() Xxresetdone = Signal() Xxdlysresetdone = Signal() Xxphaligndone = Signal() Xxsyncdone = Signal() self.specials += [ MultiReg(self.plllock, plllock), MultiReg(self.Xxresetdone, Xxresetdone), MultiReg(self.Xxdlysresetdone, Xxdlysresetdone), MultiReg(self.Xxphaligndone, Xxphaligndone), MultiReg(self.Xxsyncdone, Xxsyncdone) ] # Deglitch FSM outputs driving transceiver asynch inputs gtXxreset = Signal() Xxdlysreset = Signal() Xxuserrdy = Signal() self.sync += [ self.gtXxreset.eq(gtXxreset), self.Xxdlysreset.eq(Xxdlysreset), self.Xxuserrdy.eq(Xxuserrdy) ] # PLL reset must be at least 2us pll_reset_cycles = ceil(2000 * sys_clk_freq / 1000000000) pll_reset_timer = WaitTimer(pll_reset_cycles) self.submodules += pll_reset_timer startup_fsm = ResetInserter()(FSM(reset_state="RESET_ALL")) self.submodules += startup_fsm ready_timer = WaitTimer(int(sys_clk_freq / 1000)) self.submodules += ready_timer self.comb += [ ready_timer.wait.eq(~self.done & ~startup_fsm.reset), startup_fsm.reset.eq(self.restart | ready_timer.done) ] if rx: cdr_stable_timer = WaitTimer(1024) self.submodules += cdr_stable_timer Xxphaligndone_r = Signal(reset=1) Xxphaligndone_rising = Signal() self.sync += Xxphaligndone_r.eq(Xxphaligndone) self.comb += Xxphaligndone_rising.eq(Xxphaligndone & ~Xxphaligndone_r) startup_fsm.act( "RESET_ALL", gtXxreset.eq(1), self.pllreset.eq(1), pll_reset_timer.wait.eq(1), If(pll_reset_timer.done, NextState("RELEASE_PLL_RESET"))) startup_fsm.act("RELEASE_PLL_RESET", gtXxreset.eq(1), If(plllock, NextState("RELEASE_GTH_RESET"))) # Release GTH reset and wait for GTH resetdone # (from UG476, GTH is reset on falling edge # of gtXxreset) if rx: startup_fsm.act( "RELEASE_GTH_RESET", Xxuserrdy.eq(1), cdr_stable_timer.wait.eq(1), If(Xxresetdone & cdr_stable_timer.done, NextState("ALIGN"))) else: startup_fsm.act("RELEASE_GTH_RESET", Xxuserrdy.eq(1), If(Xxresetdone, NextState("ALIGN"))) # Start delay alignment (pulse) startup_fsm.act("ALIGN", Xxuserrdy.eq(1), Xxdlysreset.eq(1), NextState("WAIT_ALIGN")) if rx: # Wait for delay alignment startup_fsm.act("WAIT_ALIGN", Xxuserrdy.eq(1), If(Xxsyncdone, NextState("READY"))) else: # Wait for delay alignment startup_fsm.act( "WAIT_ALIGN", Xxuserrdy.eq(1), If(Xxdlysresetdone, NextState("WAIT_FIRST_ALIGN_DONE"))) # Wait 2 rising edges of Xxphaligndone # (from UG576 in TX Buffer Bypass in Single-Lane Auto Mode) startup_fsm.act( "WAIT_FIRST_ALIGN_DONE", Xxuserrdy.eq(1), If(Xxphaligndone_rising, NextState("WAIT_SECOND_ALIGN_DONE"))) startup_fsm.act("WAIT_SECOND_ALIGN_DONE", Xxuserrdy.eq(1), If(Xxphaligndone_rising, NextState("READY"))) startup_fsm.act("READY", Xxuserrdy.eq(1), self.done.eq(1), If(self.restart, NextState("RESET_ALL")))
def __init__(self, platform, clk_freq): # Work out how many LEDs this board has user_leds = [] while True: try: user_leds.append(platform.request("user_led", len(user_leds))) except ConstraintError: break if user_leds: leds = Signal(len(user_leds)) self.submodules.leds = GPIOOut(leds) for i in range(0, len(user_leds)): self.comb += [ user_leds[i].eq(leds[i]), ] self._leds_count = CSRConstant(len(user_leds)) # Work out how many switches this board has user_sws = [] while True: try: user_sws.append(platform.request("user_sw", len(user_sws))) except ConstraintError: break if user_sws: switches = Signal(len(user_sws)) self.submodules.switches = GPIOIn(switches) for i in range(0, len(user_sws)): self.comb += [ switches[i].eq(~user_sws[i]), ] self._switches_count = CSRConstant(len(user_sws)) # Work out how many push buttons this board has user_btns = [] while True: try: user_btns.append(platform.request("user_btn", len(user_btns))) except ConstraintError: break if user_btns: self.submodules.buttons_ev = EventManager() _10ms = int(clk_freq*(10e-3)) for i in range(0, len(user_btns)): btn_ev = EventSourceProcess() btn_timer = WaitTimer(_10ms) setattr(self.buttons_ev, "btn_ev{}".format(i), btn_ev) self.comb += [ btn_timer.wait.eq(user_btns[i]), btn_ev.trigger.eq(~btn_timer.done), ] self.submodules += [btn_timer] self.buttons_ev.finalize() self._buttons_count = CSRConstant(len(user_btns))
def __init__(self, serdes, taps, timeout=1024): self.reset = Signal() self.ready = Signal() self.error = Signal() # # # self.delay = delay = Signal(max=taps) self.delay_min = delay_min = Signal(max=taps) self.delay_min_found = delay_min_found = Signal() self.delay_max = delay_max = Signal(max=taps) self.delay_max_found = delay_max_found = Signal() self.bitslip = bitslip = Signal(max=40) timer = WaitTimer(timeout) self.submodules += timer self.submodules.fsm = fsm = ResetInserter()(FSM(reset_state="IDLE")) self.comb += self.fsm.reset.eq(self.reset) fsm.act("IDLE", NextValue(delay, 0), NextValue(delay_min, 0), NextValue(delay_min_found, 0), NextValue(delay_max, 0), NextValue(delay_max_found, 0), serdes.rx_delay_rst.eq(1), NextValue(bitslip, 0), NextState("RESET_SLAVE"), serdes.tx_idle.eq(1)) fsm.act("RESET_SLAVE", timer.wait.eq(1), If(timer.done, timer.wait.eq(0), NextState("SEND_PATTERN")), serdes.tx_idle.eq(1)) fsm.act("SEND_PATTERN", If(~serdes.rx_idle, NextState("WAIT_STABLE")), serdes.tx_comma.eq(1)) fsm.act("WAIT_STABLE", timer.wait.eq(1), If(timer.done, timer.wait.eq(0), NextState("CHECK_PATTERN")), serdes.tx_comma.eq(1)) fsm.act( "CHECK_PATTERN", If( ~delay_min_found, If( serdes.rx_comma, timer.wait.eq(1), If(timer.done, timer.wait.eq(0), NextValue(delay_min, delay), NextValue(delay_min_found, 1))).Else(NextState("INC_DELAY_BITSLIP")), ).Else( If(~serdes.rx_comma, NextValue(delay_max, delay), NextValue(delay_max_found, 1), NextState("CHECK_SAMPLING_WINDOW")).Else( NextState("INC_DELAY_BITSLIP"))), serdes.tx_comma.eq(1)) self.comb += serdes.rx_bitslip_value.eq(bitslip) fsm.act( "INC_DELAY_BITSLIP", NextState("WAIT_STABLE"), If( delay == (taps - 1), If(bitslip == (40 - 1), NextState("ERROR")).Else(NextValue(delay_min_found, 0), NextValue(bitslip, bitslip + 1)), NextValue(delay, 0), serdes.rx_delay_rst.eq(1)).Else(NextValue(delay, delay + 1), serdes.rx_delay_inc.eq(1), serdes.rx_delay_ce.eq(1)), serdes.tx_comma.eq(1)) fsm.act( "CHECK_SAMPLING_WINDOW", If((delay_min == 0) | (delay_max == (taps - 1)) | ((delay_max - delay_min) < taps // 16), NextValue(delay_min_found, 0), NextValue(delay_max_found, 0), NextState("WAIT_STABLE")).Else( NextState("RESET_SAMPLING_WINDOW"))) fsm.act("RESET_SAMPLING_WINDOW", NextValue(delay, 0), serdes.rx_delay_rst.eq(1), NextState("WAIT_SAMPLING_WINDOW"), serdes.tx_comma.eq(1)) fsm.act( "CONFIGURE_SAMPLING_WINDOW", If(delay == (delay_min + (delay_max - delay_min)[1:]), NextState("READY")).Else(NextValue(delay, delay + 1), serdes.rx_delay_inc.eq(1), serdes.rx_delay_ce.eq(1), NextState("WAIT_SAMPLING_WINDOW")), serdes.tx_comma.eq(1)) fsm.act( "WAIT_SAMPLING_WINDOW", timer.wait.eq(1), If(timer.done, timer.wait.eq(0), NextState("CONFIGURE_SAMPLING_WINDOW")), serdes.tx_comma.eq(1)) fsm.act("READY", self.ready.eq(1)) fsm.act("ERROR", self.error.eq(1))
def __init__(self, clk_freq, max_requests=8): self.sink = sink = stream.Endpoint(_arp_table_layout) # from arp_rx self.source = source = stream.Endpoint(_arp_table_layout) # to arp_tx # Request/Response interface self.request = request = stream.Endpoint(arp_table_request_layout) self.response = response = stream.Endpoint(arp_table_response_layout) # # # request_pending = Signal() request_pending_clr = Signal() request_pending_set = Signal() self.sync += \ If(request_pending_clr, request_pending.eq(0) ).Elif(request_pending_set, request_pending.eq(1) ) request_ip_address = Signal(32, reset_less=True) request_ip_address_reset = Signal() request_ip_address_update = Signal() self.sync += \ If(request_ip_address_reset, request_ip_address.eq(0) ).Elif(request_ip_address_update, request_ip_address.eq(request.ip_address) ) request_timer = WaitTimer(clk_freq // 10) self.submodules += request_timer request_counter = Signal(max=max_requests) request_counter_reset = Signal() request_counter_ce = Signal() self.sync += \ If(request_counter_reset, request_counter.eq(0) ).Elif(request_counter_ce, request_counter.eq(request_counter + 1) ) self.comb += request_timer.wait.eq(request_pending & ~request_counter_ce) # Note: Store only 1 IP/MAC couple, can be improved with a real # table in the future to improve performance when packets are # targeting multiple destinations. update = Signal() cached_valid = Signal() cached_ip_address = Signal(32, reset_less=True) cached_mac_address = Signal(48, reset_less=True) cached_timer = WaitTimer(clk_freq * 10) self.submodules += cached_timer self.submodules.fsm = fsm = FSM(reset_state="IDLE") fsm.act( "IDLE", # Note: for simplicicy, if APR table is busy response from arp_rx # is lost. This is compensated by the protocol (retries) If(sink.valid & sink.request, NextState("SEND_REPLY")).Elif( sink.valid & sink.reply & request_pending, NextState("UPDATE_TABLE"), ).Elif(request_counter == max_requests - 1, NextState("PRESENT_RESPONSE")).Elif( request.valid | (request_pending & request_timer.done), NextState("CHECK_TABLE"))) fsm.act("SEND_REPLY", source.valid.eq(1), source.reply.eq(1), source.ip_address.eq(sink.ip_address), source.mac_address.eq(sink.mac_address), If(source.ready, NextState("IDLE"))) fsm.act("UPDATE_TABLE", request_pending_clr.eq(1), update.eq(1), NextState("CHECK_TABLE")) self.sync += \ If(update, cached_valid.eq(1), cached_ip_address.eq(sink.ip_address), cached_mac_address.eq(sink.mac_address), ).Else( If(cached_timer.done, cached_valid.eq(0) ) ) self.comb += cached_timer.wait.eq(~update) fsm.act( "CHECK_TABLE", If( cached_valid, If( request_ip_address == cached_ip_address, request_ip_address_reset.eq(1), NextState("PRESENT_RESPONSE"), ).Elif( request.ip_address == cached_ip_address, request.ready.eq(request.valid), NextState("PRESENT_RESPONSE"), ).Else(request_ip_address_update.eq(request.valid), NextState("SEND_REQUEST"))).Else( request_ip_address_update.eq(request.valid), NextState("SEND_REQUEST"))) fsm.act( "SEND_REQUEST", source.valid.eq(1), source.request.eq(1), source.ip_address.eq(request_ip_address), If(source.ready, request_counter_reset.eq(request.valid), request_counter_ce.eq(1), request_pending_set.eq(1), request.ready.eq(1), NextState("IDLE"))) self.comb += [ If(request_counter == max_requests - 1, response.failed.eq(1), request_counter_reset.eq(1), request_pending_clr.eq(1)), response.mac_address.eq(cached_mac_address) ] fsm.act("PRESENT_RESPONSE", response.valid.eq(1), If(response.ready, NextState("IDLE")))
def __init__(self, n, aw, address_align, settings): self.req = req = Record(cmd_layout(aw)) self.refresh_req = Signal() self.refresh_gnt = Signal() a = settings.geom.addressbits ba = settings.geom.bankbits self.cmd = cmd = stream.Endpoint(cmd_request_rw_layout(a, ba)) # # # # Command buffer cmd_buffer_layout = [("we", 1), ("adr", len(req.adr))] if settings.cmd_buffer_depth < 2: cmd_buffer = stream.Buffer(cmd_buffer_layout) else: cmd_buffer = stream.SyncFIFO(cmd_buffer_layout, settings.cmd_buffer_depth) self.submodules += cmd_buffer self.comb += [ req.connect(cmd_buffer.sink, omit=[ "wdata_valid", "wdata_ready", "rdata_valid", "rdata_ready", "lock" ]), cmd_buffer.source.ready.eq(req.wdata_ready | req.rdata_valid), req.lock.eq(cmd_buffer.source.valid), ] slicer = _AddressSlicer(settings.geom.colbits, address_align) # Row tracking has_openrow = Signal() openrow = Signal(settings.geom.rowbits, reset_less=True) hit = Signal() self.comb += hit.eq(openrow == slicer.row(cmd_buffer.source.adr)) track_open = Signal() track_close = Signal() self.sync += \ If(track_close, has_openrow.eq(0) ).Elif(track_open, has_openrow.eq(1), openrow.eq(slicer.row(cmd_buffer.source.adr)) ) # Address generation sel_row_adr = Signal() self.comb += [ cmd.ba.eq(n), If(sel_row_adr, cmd.a.eq(slicer.row(cmd_buffer.source.adr))).Else( cmd.a.eq(slicer.col(cmd_buffer.source.adr))) ] # Respect write-to-precharge specification precharge_time = 2 + settings.timing.tWR - 1 + 1 self.submodules.precharge_timer = WaitTimer(precharge_time) self.comb += self.precharge_timer.wait.eq(~(cmd.valid & cmd.ready & cmd.is_write)) # Control and command generation FSM self.submodules.fsm = fsm = FSM() fsm.act( "REGULAR", If(self.refresh_req, NextState("REFRESH")).Elif( cmd_buffer.source.valid, If( has_openrow, If( hit, # Note: write-to-read specification is enforced by # multiplexer cmd.valid.eq(1), If( cmd_buffer.source.we, req.wdata_ready.eq(cmd.ready), cmd.is_write.eq(1), cmd.we.eq(1), ).Else(req.rdata_valid.eq(cmd.ready), cmd.is_read.eq(1)), cmd.cas.eq(1)).Else(NextState("PRECHARGE"))).Else( NextState("ACTIVATE")))) fsm.act( "PRECHARGE", # Note: we are presenting the column address, A10 is always low If(self.precharge_timer.done, cmd.valid.eq(1), If(cmd.ready, NextState("TRP")), cmd.ras.eq(1), cmd.we.eq(1), cmd.is_cmd.eq(1)), track_close.eq(1)) fsm.act("ACTIVATE", sel_row_adr.eq(1), track_open.eq(1), cmd.valid.eq(1), cmd.is_cmd.eq(1), If(cmd.ready, NextState("TRCD")), cmd.ras.eq(1)) fsm.act("REFRESH", If( self.precharge_timer.done, self.refresh_gnt.eq(1), ), track_close.eq(1), cmd.is_cmd.eq(1), If(~self.refresh_req, NextState("REGULAR"))) fsm.delayed_enter("TRP", "ACTIVATE", settings.timing.tRP - 1) fsm.delayed_enter("TRCD", "REGULAR", settings.timing.tRCD - 1)