def __init__(self, platform): self.clock_domains.cd_sys = ClockDomain() self.clock_domains.cd_sys4x = ClockDomain(reset_less=True) self.clock_domains.cd_sys4x_dqs = ClockDomain(reset_less=True) self.clock_domains.cd_clk200 = ClockDomain() self.clock_domains.cd_clk100 = ClockDomain() clk50 = platform.request("clk50") rst = Signal() pll_locked = Signal() pll_fb = Signal() self.pll_sys = Signal() pll_sys4x = Signal() pll_sys4x_dqs = Signal() pll_clk200 = Signal() self.specials += [ Instance("PLLE2_BASE", p_STARTUP_WAIT="FALSE", o_LOCKED=pll_locked, # VCO @ 1600 MHz p_REF_JITTER1=0.01, p_CLKIN1_PERIOD=20.0, p_CLKFBOUT_MULT=32, p_DIVCLK_DIVIDE=1, i_CLKIN1=clk50, i_CLKFBIN=pll_fb, o_CLKFBOUT=pll_fb, # 100 MHz p_CLKOUT0_DIVIDE=16, p_CLKOUT0_PHASE=0.0, o_CLKOUT0=self.pll_sys, # 400 MHz p_CLKOUT1_DIVIDE=4, p_CLKOUT1_PHASE=0.0, o_CLKOUT1=pll_sys4x, # 400 MHz dqs p_CLKOUT2_DIVIDE=4, p_CLKOUT2_PHASE=90.0, o_CLKOUT2=pll_sys4x_dqs, # 200 MHz p_CLKOUT3_DIVIDE=8, p_CLKOUT3_PHASE=0.0, o_CLKOUT3=pll_clk200 ), Instance("BUFG", i_I=self.pll_sys, o_O=self.cd_sys.clk), Instance("BUFG", i_I=self.pll_sys, o_O=self.cd_clk100.clk), Instance("BUFG", i_I=pll_clk200, o_O=self.cd_clk200.clk), Instance("BUFG", i_I=pll_sys4x, o_O=self.cd_sys4x.clk), Instance("BUFG", i_I=pll_sys4x_dqs, o_O=self.cd_sys4x_dqs.clk), AsyncResetSynchronizer(self.cd_sys, ~pll_locked | rst), AsyncResetSynchronizer(self.cd_clk200, ~pll_locked | rst), AsyncResetSynchronizer(self.cd_clk100, ~pll_locked | rst) ] reset_counter = Signal(4, reset=15) ic_reset = Signal(reset=1) self.sync.clk200 += \ If(reset_counter != 0, reset_counter.eq(reset_counter - 1) ).Else( ic_reset.eq(0) ) self.specials += Instance("IDELAYCTRL", i_REFCLK=ClockSignal("clk200"), i_RST=ic_reset)
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() self.comb += [ self.cd_eth_rx.clk.eq(ClockSignal("eth")), self.cd_eth_tx.clk.eq(ClockSignal("eth")) ] self.specials += DDROutput(0, 1, clock_pads.ref_clk, ClockSignal("eth_tx")) 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, clock_pads, pads, with_hw_init_reset): self._reset = CSRStorage() # # # if hasattr(clock_pads, "phy"): self.sync.base50 += clock_pads.phy.eq(~clock_pads.phy) self.clock_domains.cd_eth_rx = ClockDomain() self.clock_domains.cd_eth_tx = ClockDomain() self.comb += self.cd_eth_rx.clk.eq(clock_pads.rx) self.comb += self.cd_eth_tx.clk.eq(clock_pads.tx) 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, 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, platform): self.clock_domains.cd_sys = ClockDomain() self.clock_domains.cd_sys4x = ClockDomain(reset_less=True) self.clock_domains.cd_sys4x_dqs = ClockDomain(reset_less=True) self.clock_domains.cd_clk200 = ClockDomain() clk50 = platform.request("clk50") clk50_bufr = Signal() pll_locked = Signal() pll_fb = Signal() pll_sys = Signal() pll_sys4x = Signal() pll_sys4x_dqs = Signal() pll_clk200 = Signal() self.specials += [ Instance("BUFR", i_I=clk50, o_O=clk50_bufr), Instance("PLLE2_BASE", p_STARTUP_WAIT="FALSE", o_LOCKED=pll_locked, # VCO @ 1GHz p_REF_JITTER1=0.01, p_CLKIN1_PERIOD=20.0, p_CLKFBOUT_MULT=20, p_DIVCLK_DIVIDE=1, i_CLKIN1=clk50_bufr, i_CLKFBIN=pll_fb, o_CLKFBOUT=pll_fb, # 125MHz p_CLKOUT0_DIVIDE=8, p_CLKOUT0_PHASE=0.0, o_CLKOUT0=pll_sys, # 500MHz p_CLKOUT1_DIVIDE=2, p_CLKOUT1_PHASE=0.0, o_CLKOUT1=pll_sys4x, # 500MHz dqs p_CLKOUT2_DIVIDE=2, p_CLKOUT2_PHASE=90.0, o_CLKOUT2=pll_sys4x_dqs, # 200MHz p_CLKOUT3_DIVIDE=5, p_CLKOUT3_PHASE=0.0, o_CLKOUT3=pll_clk200 ), Instance("BUFG", i_I=pll_sys, o_O=self.cd_sys.clk), Instance("BUFG", i_I=pll_sys4x, o_O=self.cd_sys4x.clk), Instance("BUFG", i_I=pll_sys4x_dqs, o_O=self.cd_sys4x_dqs.clk), Instance("BUFG", i_I=pll_clk200, o_O=self.cd_clk200.clk), AsyncResetSynchronizer(self.cd_sys, ~pll_locked), AsyncResetSynchronizer(self.cd_clk200, ~pll_locked), ] platform.add_platform_command("set_property CLOCK_DEDICATED_ROUTE BACKBONE [get_nets crg_clk50_bufr]") reset_counter = Signal(4, reset=15) ic_reset = Signal(reset=1) self.sync.clk200 += \ If(reset_counter != 0, reset_counter.eq(reset_counter - 1) ).Else( ic_reset.eq(0) ) self.specials += Instance("IDELAYCTRL", p_SIM_DEVICE="ULTRASCALE", i_REFCLK=ClockSignal("clk200"), i_RST=ic_reset)
def __init__(self, iwidth, idomain, owidth, odomain): self.i = Signal(iwidth) self.o = Signal(owidth) # # # reset = Signal() cd_write = ClockDomain() cd_read = ClockDomain() self.comb += [ cd_write.clk.eq(ClockSignal(idomain)), cd_read.clk.eq(ClockSignal(odomain)), reset.eq(ResetSignal(idomain) | ResetSignal(odomain)) ] self.specials += [ AsyncResetSynchronizer(cd_write, reset), AsyncResetSynchronizer(cd_read, reset) ] self.clock_domains += cd_write, cd_read storage = Signal(lcm(iwidth, owidth)) wrchunks = len(storage) // iwidth rdchunks = len(storage) // owidth wrpointer = Signal(max=wrchunks, reset=0 if iwidth > owidth else wrchunks - 1) rdpointer = Signal(max=rdchunks, reset=rdchunks - 1 if iwidth > owidth else 0) self.sync.write += \ If(wrpointer == wrchunks-1, wrpointer.eq(0) ).Else( wrpointer.eq(wrpointer + 1) ) cases = {} for i in range(wrchunks): cases[i] = [storage[iwidth * i:iwidth * (i + 1)].eq(self.i)] self.sync.write += Case(wrpointer, cases) self.sync.read += \ If(rdpointer == rdchunks-1, rdpointer.eq(0) ).Else( rdpointer.eq(rdpointer + 1) ) cases = {} for i in range(rdchunks): cases[i] = [self.o.eq(storage[owidth * i:owidth * (i + 1)])] self.sync.read += Case(rdpointer, cases)
def __init__(self, platform): self.clock_domains.cd_sys = ClockDomain() # # # clk100 = platform.request("clk100") rst = ~platform.request("cpu_reset") pll_locked = Signal() pll_fb = Signal() pll_sys = Signal() self.specials += [ Instance( "PLLE2_BASE", p_STARTUP_WAIT="FALSE", o_LOCKED=pll_locked, # VCO @ 1600 MHz p_REF_JITTER1=0.01, p_CLKIN1_PERIOD=10.0, p_CLKFBOUT_MULT=16, p_DIVCLK_DIVIDE=1, i_CLKIN1=clk100, i_CLKFBIN=pll_fb, o_CLKFBOUT=pll_fb, # 100 MHz p_CLKOUT0_DIVIDE=16, p_CLKOUT0_PHASE=0.0, o_CLKOUT0=pll_sys), Instance("BUFG", i_I=pll_sys, o_O=self.cd_sys.clk), AsyncResetSynchronizer(self.cd_sys, ~pll_locked | rst), ]
def __init__(self, clock_pads, pads): self.reset = CSRStorage() # # # reset = self.reset.storage self.clock_domains.cd_eth_rx = ClockDomain() self.clock_domains.cd_eth_tx = ClockDomain() self.comb += self.cd_eth_tx.clk.eq(self.cd_eth_rx.clk) self.comb += pads.rst_n.eq(~reset) self.specials += [ AsyncResetSynchronizer(self.cd_eth_tx, reset), AsyncResetSynchronizer(self.cd_eth_rx, reset) ]
def __init__(self, width, depth, idomain, odomain): self.din = Signal(width) self.dout = Signal(width) # # # reset = Signal() cd_write = ClockDomain() cd_read = ClockDomain() self.comb += [ cd_write.clk.eq(ClockSignal(idomain)), cd_read.clk.eq(ClockSignal(odomain)), reset.eq(ResetSignal(idomain) | ResetSignal(odomain)) ] self.specials += [ AsyncResetSynchronizer(cd_write, reset), AsyncResetSynchronizer(cd_read, reset) ] self.clock_domains += cd_write, cd_read wrpointer = Signal(max=depth, reset=depth // 2) rdpointer = Signal(max=depth) storage = Memory(width, depth) self.specials += storage wrport = storage.get_port(write_capable=True, clock_domain="write") rdport = storage.get_port(clock_domain="read") self.specials += wrport, rdport self.sync.write += wrpointer.eq(wrpointer + 1) self.sync.read += rdpointer.eq(rdpointer + 1) self.comb += [ wrport.we.eq(1), wrport.adr.eq(wrpointer), wrport.dat_w.eq(self.din), rdport.adr.eq(rdpointer), self.dout.eq(rdport.dat_r) ]
def __init__(self, clock_pads, pads, with_hw_init_reset, mii_mode=0): self._reset = CSRStorage() # # # self.clock_domains.cd_eth_rx = ClockDomain() self.clock_domains.cd_eth_tx = ClockDomain() # RX : Let the synthesis tool insert the appropriate clock buffer self.comb += self.cd_eth_rx.clk.eq(clock_pads.rx) # TX : GMII: Drive clock_pads.gtx, clock_pads.tx unused # MII: Use PHY clock_pads.tx as eth_tx_clk, do not drive clock_pads.gtx self.specials += DDROutput(1, mii_mode, clock_pads.gtx, ClockSignal("eth_tx")) if isinstance(mii_mode, int) and (mii_mode == 0): self.comb += self.cd_eth_tx.clk.eq(self.cd_eth_rx.clk) else: # XXX Xilinx specific, replace BUFGMUX with a generic clock buffer? self.specials += Instance("BUFGMUX", i_I0=self.cd_eth_rx.clk, i_I1=clock_pads.tx, i_S=mii_mode, o_O=self.cd_eth_tx.clk) 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, platform): self.clock_domains.cd_sys = ClockDomain("sys") # soft reset generaton self._soft_rst = CSR() soft_rst = Signal() # trigger soft reset 1us after CSR access to terminate # Wishbone access when reseting from PCIe self.sync += [ timeline(self._soft_rst.re & self._soft_rst.r, [(125, [soft_rst.eq(1)])]), ] # sys_clk / sys_rst (from PCIe) self.comb += self.cd_sys.clk.eq(ClockSignal("pcie")) self.specials += AsyncResetSynchronizer(self.cd_sys, ResetSignal("pcie") | soft_rst)
def __init__(self, platform, clk_freq): self.clock_domains.cd_sys = ClockDomain() self.clock_domains.cd_sys_ps = ClockDomain() f0 = 32*1000000 clk32 = platform.request("clk32") clk32a = Signal() self.specials += Instance("IBUFG", i_I=clk32, o_O=clk32a) clk32b = Signal() self.specials += Instance("BUFIO2", p_DIVIDE=1, p_DIVIDE_BYPASS="******", p_I_INVERT="FALSE", i_I=clk32a, o_DIVCLK=clk32b) f = Fraction(int(clk_freq), int(f0)) n, m, p = f.denominator, f.numerator, 8 assert f0/n*m == clk_freq pll_lckd = Signal() pll_fb = Signal() pll = Signal(6) self.specials.pll = Instance("PLL_ADV", p_SIM_DEVICE="SPARTAN6", p_BANDWIDTH="OPTIMIZED", p_COMPENSATION="INTERNAL", p_REF_JITTER=.01, p_CLK_FEEDBACK="CLKFBOUT", i_DADDR=0, i_DCLK=0, i_DEN=0, i_DI=0, i_DWE=0, i_RST=0, i_REL=0, p_DIVCLK_DIVIDE=1, p_CLKFBOUT_MULT=m*p//n, p_CLKFBOUT_PHASE=0., i_CLKIN1=clk32b, i_CLKIN2=0, i_CLKINSEL=1, p_CLKIN1_PERIOD=1000000000/f0, p_CLKIN2_PERIOD=0., i_CLKFBIN=pll_fb, o_CLKFBOUT=pll_fb, o_LOCKED=pll_lckd, o_CLKOUT0=pll[0], p_CLKOUT0_DUTY_CYCLE=.5, o_CLKOUT1=pll[1], p_CLKOUT1_DUTY_CYCLE=.5, o_CLKOUT2=pll[2], p_CLKOUT2_DUTY_CYCLE=.5, o_CLKOUT3=pll[3], p_CLKOUT3_DUTY_CYCLE=.5, o_CLKOUT4=pll[4], p_CLKOUT4_DUTY_CYCLE=.5, o_CLKOUT5=pll[5], p_CLKOUT5_DUTY_CYCLE=.5, p_CLKOUT0_PHASE=0., p_CLKOUT0_DIVIDE=p//1, p_CLKOUT1_PHASE=0., p_CLKOUT1_DIVIDE=p//1, p_CLKOUT2_PHASE=0., p_CLKOUT2_DIVIDE=p//1, p_CLKOUT3_PHASE=0., p_CLKOUT3_DIVIDE=p//1, p_CLKOUT4_PHASE=0., p_CLKOUT4_DIVIDE=p//1, # sys p_CLKOUT5_PHASE=270., p_CLKOUT5_DIVIDE=p//1, # sys_ps ) self.specials += Instance("BUFG", i_I=pll[4], o_O=self.cd_sys.clk) self.specials += Instance("BUFG", i_I=pll[5], o_O=self.cd_sys_ps.clk) self.specials += AsyncResetSynchronizer(self.cd_sys, ~pll_lckd) self.specials += Instance("ODDR2", p_DDR_ALIGNMENT="NONE", p_INIT=0, p_SRTYPE="SYNC", i_D0=0, i_D1=1, i_S=0, i_R=0, i_CE=1, i_C0=self.cd_sys.clk, i_C1=~self.cd_sys.clk, o_Q=platform.request("sdram_clock"))
def __init__(self, platform): self.clock_domains.cd_sys = ClockDomain() clk200 = platform.request("clk200") clk200_se = Signal() self.specials += Instance("IBUFDS", i_I=clk200.p, i_IB=clk200.n, o_O=clk200_se) pll_locked = Signal() pll_fb = Signal() pll_sys = Signal() self.specials += [ Instance( "PLLE2_BASE", p_STARTUP_WAIT="FALSE", o_LOCKED=pll_locked, # VCO @ 1GHz p_REF_JITTER1=0.01, p_CLKIN1_PERIOD=5.0, p_CLKFBOUT_MULT=5, p_DIVCLK_DIVIDE=1, i_CLKIN1=clk200_se, i_CLKFBIN=pll_fb, o_CLKFBOUT=pll_fb, # 200MHz p_CLKOUT0_DIVIDE=5, p_CLKOUT0_PHASE=0.0, o_CLKOUT0=pll_sys, p_CLKOUT1_DIVIDE=2, p_CLKOUT1_PHASE=0.0, #o_CLKOUT1=, p_CLKOUT2_DIVIDE=2, p_CLKOUT2_PHASE=0.0, #o_CLKOUT2=, p_CLKOUT3_DIVIDE=2, p_CLKOUT3_PHASE=0.0, #o_CLKOUT3=, p_CLKOUT4_DIVIDE=2, p_CLKOUT4_PHASE=0.0, #o_CLKOUT4= ), Instance("BUFG", i_I=pll_sys, o_O=self.cd_sys.clk), AsyncResetSynchronizer(self.cd_sys, ~pll_locked | platform.request("cpu_reset")), ]
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, sys_clk_freq=50e6, max_sd_clk_freq=100e6): self._cmd_data = CSRStorage(10) self._send_cmd_data = CSR() self._send_go = CSR() self._status = CSRStatus(4) self._max_sd_clk_freq = CSRConstant(max_sd_clk_freq) self.clock_domains.cd_sd = ClockDomain() self.clock_domains.cd_sd_fb = ClockDomain() # # # clk_sd_unbuffered = Signal() sd_progdata = Signal() sd_progen = Signal() sd_progdone = Signal() sd_locked = Signal() clkfx_md_max = max(2.0 / 4.0, max_sd_clk_freq / sys_clk_freq) self._clkfx_md_max_1000 = CSRConstant(clkfx_md_max * 1000.0) self.specials += Instance( "DCM_CLKGEN", # parameters p_SPREAD_SPECTRUM="NONE", p_STARTUP_WAIT="FALSE", # reset i_FREEZEDCM=0, i_RST=ResetSignal(), # input i_CLKIN=ClockSignal(), p_CLKIN_PERIOD=1e9 / sys_clk_freq, # output p_CLKFXDV_DIVIDE=2, p_CLKFX_MULTIPLY=2, p_CLKFX_DIVIDE=4, p_CLKFX_MD_MAX=clkfx_md_max, o_CLKFX=clk_sd_unbuffered, o_LOCKED=sd_locked, # programming interface i_PROGCLK=ClockSignal(), i_PROGDATA=sd_progdata, i_PROGEN=sd_progen, o_PROGDONE=sd_progdone) remaining_bits = Signal(max=11) transmitting = Signal() self.comb += transmitting.eq(remaining_bits != 0) sr = Signal(10) self.sync += [ If(self._send_cmd_data.re, remaining_bits.eq(10), sr.eq(self._cmd_data.storage)).Elif( transmitting, remaining_bits.eq(remaining_bits - 1), sr.eq(sr[1:])) ] self.comb += [ sd_progdata.eq(transmitting & sr[0]), sd_progen.eq(transmitting | self._send_go.re) ] # enforce gap between commands busy_counter = Signal(max=14) busy = Signal() self.comb += busy.eq(busy_counter != 0) self.sync += If(self._send_cmd_data.re, busy_counter.eq(13)).Elif( busy, busy_counter.eq(busy_counter - 1)) self.comb += self._status.status.eq(Cat(busy, sd_progdone, sd_locked)) self.specials += [ Instance("BUFG", i_I=clk_sd_unbuffered, o_O=self.cd_sd.clk), AsyncResetSynchronizer(self.cd_sd, ~sd_locked) ]
def __init__(self, pll, pads, mode="master"): self.tx_data = Signal(32) self.rx_data = Signal(32) self.tx_idle = Signal() self.tx_comma = Signal() self.rx_idle = Signal() self.rx_comma = Signal() self.rx_bitslip_value = Signal(6) self.rx_delay_rst = Signal() self.rx_delay_inc = Signal() self.rx_delay_ce = Signal() self.rx_delay_en_vtc = Signal() # # # self.submodules.encoder = ClockDomainsRenamer("serwb_serdes")(Encoder( 4, True)) self.decoders = [ ClockDomainsRenamer("serwb_serdes")(Decoder(True)) for _ in range(4) ] self.submodules += self.decoders # clocking: # In master mode: # - linerate/10 pll refclk provided by user # - linerate/10 slave refclk generated on clk_pads # In Slave mode: # - linerate/10 pll refclk provided by clk_pads self.clock_domains.cd_serwb_serdes = ClockDomain() self.clock_domains.cd_serwb_serdes_5x = ClockDomain() self.clock_domains.cd_serwb_serdes_20x = ClockDomain(reset_less=True) self.comb += [ self.cd_serwb_serdes.clk.eq(pll.serwb_serdes_clk), self.cd_serwb_serdes_5x.clk.eq(pll.serwb_serdes_5x_clk), self.cd_serwb_serdes_20x.clk.eq(pll.serwb_serdes_20x_clk) ] self.specials += AsyncResetSynchronizer(self.cd_serwb_serdes, ~pll.lock) self.comb += self.cd_serwb_serdes_5x.rst.eq(self.cd_serwb_serdes.rst) # control/status cdc tx_idle = Signal() tx_comma = Signal() rx_idle = Signal() rx_comma = Signal() rx_bitslip_value = Signal(6) rx_delay_rst = Signal() rx_delay_inc = Signal() rx_delay_en_vtc = Signal() rx_delay_ce = Signal() self.specials += [ MultiReg(self.tx_idle, tx_idle, "serwb_serdes"), MultiReg(self.tx_comma, tx_comma, "serwb_serdes"), MultiReg(rx_idle, self.rx_idle, "sys"), MultiReg(rx_comma, self.rx_comma, "sys"), MultiReg(self.rx_bitslip_value, rx_bitslip_value, "serwb_serdes"), MultiReg(self.rx_delay_inc, rx_delay_inc, "serwb_serdes_5x"), MultiReg(self.rx_delay_en_vtc, rx_delay_en_vtc, "serwb_serdes_5x") ] self.submodules.do_rx_delay_rst = PulseSynchronizer( "sys", "serwb_serdes_5x") self.comb += [ rx_delay_rst.eq(self.do_rx_delay_rst.o), self.do_rx_delay_rst.i.eq(self.rx_delay_rst) ] self.submodules.do_rx_delay_ce = PulseSynchronizer( "sys", "serwb_serdes_5x") self.comb += [ rx_delay_ce.eq(self.do_rx_delay_ce.o), self.do_rx_delay_ce.i.eq(self.rx_delay_ce) ] # tx clock (linerate/10) if mode == "master": self.submodules.tx_clk_gearbox = Gearbox(40, "serwb_serdes", 8, "serwb_serdes_5x") self.comb += self.tx_clk_gearbox.i.eq((0b1111100000 << 30) | (0b1111100000 << 20) | (0b1111100000 << 10) | (0b1111100000 << 0)) clk_o = Signal() self.specials += [ Instance("OSERDESE3", p_DATA_WIDTH=8, p_INIT=0, p_IS_CLK_INVERTED=0, p_IS_CLKDIV_INVERTED=0, p_IS_RST_INVERTED=0, o_OQ=clk_o, i_RST=ResetSignal("serwb_serdes"), i_CLK=ClockSignal("serwb_serdes_20x"), i_CLKDIV=ClockSignal("serwb_serdes_5x"), i_D=self.tx_clk_gearbox.o), Instance("OBUFDS", i_I=clk_o, o_O=pads.clk_p, o_OB=pads.clk_n) ] # tx datapath # tx_data -> encoders -> gearbox -> serdes self.submodules.tx_gearbox = Gearbox(40, "serwb_serdes", 8, "serwb_serdes_5x") self.comb += [ If(tx_comma, self.encoder.k[0].eq(1), self.encoder.d[0].eq(0xbc)).Else( self.encoder.d[0].eq(self.tx_data[0:8]), self.encoder.d[1].eq(self.tx_data[8:16]), self.encoder.d[2].eq(self.tx_data[16:24]), self.encoder.d[3].eq(self.tx_data[24:32])) ] self.sync.serwb_serdes += \ If(tx_idle, self.tx_gearbox.i.eq(0) ).Else( self.tx_gearbox.i.eq(Cat(*[self.encoder.output[i] for i in range(4)])) ) serdes_o = Signal() self.specials += [ Instance("OSERDESE3", p_DATA_WIDTH=8, p_INIT=0, p_IS_CLK_INVERTED=0, p_IS_CLKDIV_INVERTED=0, p_IS_RST_INVERTED=0, o_OQ=serdes_o, i_RST=ResetSignal("serwb_serdes"), i_CLK=ClockSignal("serwb_serdes_20x"), i_CLKDIV=ClockSignal("serwb_serdes_5x"), i_D=self.tx_gearbox.o), Instance("OBUFDS", i_I=serdes_o, o_O=pads.tx_p, o_OB=pads.tx_n) ] # rx clock use_bufr = True if mode == "slave": clk_i = Signal() clk_i_bufg = Signal() self.specials += [ Instance("IBUFDS", i_I=pads.clk_p, i_IB=pads.clk_n, o_O=clk_i) ] if use_bufr: clk_i_bufr = Signal() self.specials += [ Instance("BUFR", i_I=clk_i, o_O=clk_i_bufr), Instance("BUFG", i_I=clk_i_bufr, o_O=clk_i_bufg) ] else: self.specials += Instance("BUFG", i_I=clk_i, o_O=clk_i_bufg) self.comb += pll.refclk.eq(clk_i_bufg) # rx datapath # serdes -> gearbox -> bitslip -> decoders -> rx_data self.submodules.rx_gearbox = Gearbox(8, "serwb_serdes_5x", 40, "serwb_serdes") self.submodules.rx_bitslip = ClockDomainsRenamer("serwb_serdes")( BitSlip(40)) serdes_i_nodelay = Signal() self.specials += [ Instance("IBUFDS_DIFF_OUT", i_I=pads.rx_p, i_IB=pads.rx_n, o_O=serdes_i_nodelay) ] serdes_i_delayed = Signal() serdes_q = Signal(8) self.specials += [ Instance("IDELAYE3", p_CASCADE="NONE", p_UPDATE_MODE="ASYNC", p_REFCLK_FREQUENCY=200.0, p_IS_CLK_INVERTED=0, p_IS_RST_INVERTED=0, p_DELAY_FORMAT="COUNT", p_DELAY_SRC="IDATAIN", p_DELAY_TYPE="VARIABLE", p_DELAY_VALUE=0, i_CLK=ClockSignal("serwb_serdes_5x"), i_RST=rx_delay_rst, i_LOAD=0, i_INC=rx_delay_inc, i_EN_VTC=rx_delay_en_vtc, i_CE=rx_delay_ce, i_IDATAIN=serdes_i_nodelay, o_DATAOUT=serdes_i_delayed), Instance("ISERDESE3", p_DATA_WIDTH=8, i_D=serdes_i_delayed, i_RST=ResetSignal("serwb_serdes"), i_FIFO_RD_CLK=0, i_FIFO_RD_EN=0, i_CLK=ClockSignal("serwb_serdes_20x"), i_CLK_B=~ClockSignal("serwb_serdes_20x"), i_CLKDIV=ClockSignal("serwb_serdes_5x"), o_Q=serdes_q) ] self.comb += [ self.rx_gearbox.i.eq(serdes_q), self.rx_bitslip.value.eq(rx_bitslip_value), self.rx_bitslip.i.eq(self.rx_gearbox.o), self.decoders[0].input.eq(self.rx_bitslip.o[0:10]), self.decoders[1].input.eq(self.rx_bitslip.o[10:20]), self.decoders[2].input.eq(self.rx_bitslip.o[20:30]), self.decoders[3].input.eq(self.rx_bitslip.o[30:40]), self.rx_data.eq(Cat(*[self.decoders[i].d for i in range(4)])), rx_idle.eq(self.rx_bitslip.o == 0), rx_comma.eq( ((self.decoders[0].d == 0xbc) & (self.decoders[0].k == 1)) & ((self.decoders[1].d == 0x00) & (self.decoders[1].k == 0)) & ((self.decoders[2].d == 0x00) & (self.decoders[2].k == 0)) & ((self.decoders[3].d == 0x00) & (self.decoders[3].k == 0))) ]
def __init__(self, pll, pads, mode="master"): self.tx_data = Signal(32) self.rx_data = Signal(32) self.tx_idle = Signal() self.tx_comma = Signal() self.rx_idle = Signal() self.rx_comma = Signal() self.rx_bitslip_value = Signal(6) self.rx_delay_rst = Signal() self.rx_delay_inc = Signal() self.rx_delay_ce = Signal() # # # self.submodules.encoder = ClockDomainsRenamer("serwb_serdes")(Encoder( 4, True)) self.decoders = [ ClockDomainsRenamer("serwb_serdes")(Decoder(True)) for _ in range(4) ] self.submodules += self.decoders # clocking: # In master mode: # - linerate/10 pll refclk provided by user # - linerate/10 slave refclk generated on clk_pads # In Slave mode: # - linerate/10 pll refclk provided by clk_pads self.clock_domains.cd_serwb_serdes = ClockDomain() self.clock_domains.cd_serwb_serdes_5x = ClockDomain() self.clock_domains.cd_serwb_serdes_20x = ClockDomain(reset_less=True) self.comb += [ self.cd_serwb_serdes.clk.eq(pll.serwb_serdes_clk), self.cd_serwb_serdes_5x.clk.eq(pll.serwb_serdes_5x_clk), self.cd_serwb_serdes_20x.clk.eq(pll.serwb_serdes_20x_clk) ] self.specials += AsyncResetSynchronizer(self.cd_serwb_serdes, ~pll.lock) self.comb += self.cd_serwb_serdes_5x.rst.eq(self.cd_serwb_serdes.rst) # control/status cdc tx_idle = Signal() tx_comma = Signal() rx_idle = Signal() rx_comma = Signal() rx_bitslip_value = Signal(6) self.specials += [ MultiReg(self.tx_idle, tx_idle, "serwb_serdes"), MultiReg(self.tx_comma, tx_comma, "serwb_serdes"), MultiReg(rx_idle, self.rx_idle, "sys"), MultiReg(rx_comma, self.rx_comma, "sys") ] self.specials += MultiReg(self.rx_bitslip_value, rx_bitslip_value, "serwb_serdes"), # tx clock (linerate/10) if mode == "master": self.submodules.tx_clk_gearbox = Gearbox(40, "serwb_serdes", 8, "serwb_serdes_5x") self.comb += self.tx_clk_gearbox.i.eq((0b1111100000 << 30) | (0b1111100000 << 20) | (0b1111100000 << 10) | (0b1111100000 << 0)) clk_o = Signal() self.specials += [ Instance("OSERDESE2", p_DATA_WIDTH=8, p_TRISTATE_WIDTH=1, p_DATA_RATE_OQ="DDR", p_DATA_RATE_TQ="BUF", p_SERDES_MODE="MASTER", o_OQ=clk_o, i_OCE=1, i_RST=ResetSignal("serwb_serdes"), i_CLK=ClockSignal("serwb_serdes_20x"), i_CLKDIV=ClockSignal("serwb_serdes_5x"), i_D1=self.tx_clk_gearbox.o[0], i_D2=self.tx_clk_gearbox.o[1], i_D3=self.tx_clk_gearbox.o[2], i_D4=self.tx_clk_gearbox.o[3], i_D5=self.tx_clk_gearbox.o[4], i_D6=self.tx_clk_gearbox.o[5], i_D7=self.tx_clk_gearbox.o[6], i_D8=self.tx_clk_gearbox.o[7]), Instance("OBUFDS", i_I=clk_o, o_O=pads.clk_p, o_OB=pads.clk_n) ] # tx datapath # tx_data -> encoders -> gearbox -> serdes self.submodules.tx_gearbox = Gearbox(40, "serwb_serdes", 8, "serwb_serdes_5x") self.comb += [ If(tx_comma, self.encoder.k[0].eq(1), self.encoder.d[0].eq(0xbc)).Else( self.encoder.d[0].eq(self.tx_data[0:8]), self.encoder.d[1].eq(self.tx_data[8:16]), self.encoder.d[2].eq(self.tx_data[16:24]), self.encoder.d[3].eq(self.tx_data[24:32])) ] self.sync.serwb_serdes += \ If(tx_idle, self.tx_gearbox.i.eq(0) ).Else( self.tx_gearbox.i.eq(Cat(*[self.encoder.output[i] for i in range(4)])) ) serdes_o = Signal() self.specials += [ Instance("OSERDESE2", p_DATA_WIDTH=8, p_TRISTATE_WIDTH=1, p_DATA_RATE_OQ="DDR", p_DATA_RATE_TQ="BUF", p_SERDES_MODE="MASTER", o_OQ=serdes_o, i_OCE=1, i_RST=ResetSignal("serwb_serdes"), i_CLK=ClockSignal("serwb_serdes_20x"), i_CLKDIV=ClockSignal("serwb_serdes_5x"), i_D1=self.tx_gearbox.o[0], i_D2=self.tx_gearbox.o[1], i_D3=self.tx_gearbox.o[2], i_D4=self.tx_gearbox.o[3], i_D5=self.tx_gearbox.o[4], i_D6=self.tx_gearbox.o[5], i_D7=self.tx_gearbox.o[6], i_D8=self.tx_gearbox.o[7]), Instance("OBUFDS", i_I=serdes_o, o_O=pads.tx_p, o_OB=pads.tx_n) ] # rx clock use_bufr = True if mode == "slave": clk_i = Signal() clk_i_bufg = Signal() self.specials += [ Instance("IBUFDS", i_I=pads.clk_p, i_IB=pads.clk_n, o_O=clk_i) ] if use_bufr: clk_i_bufr = Signal() self.specials += [ Instance("BUFR", i_I=clk_i, o_O=clk_i_bufr), Instance("BUFG", i_I=clk_i_bufr, o_O=clk_i_bufg) ] else: self.specials += Instance("BUFG", i_I=clk_i, o_O=clk_i_bufg) self.comb += pll.refclk.eq(clk_i_bufg) # rx datapath # serdes -> gearbox -> bitslip -> decoders -> rx_data self.submodules.rx_gearbox = Gearbox(8, "serwb_serdes_5x", 40, "serwb_serdes") self.submodules.rx_bitslip = ClockDomainsRenamer("serwb_serdes")( BitSlip(40)) serdes_i_nodelay = Signal() self.specials += [ Instance("IBUFDS_DIFF_OUT", i_I=pads.rx_p, i_IB=pads.rx_n, o_O=serdes_i_nodelay) ] serdes_i_delayed = Signal() serdes_q = Signal(8) self.specials += [ Instance("IDELAYE2", p_DELAY_SRC="IDATAIN", p_SIGNAL_PATTERN="DATA", p_CINVCTRL_SEL="FALSE", p_HIGH_PERFORMANCE_MODE="TRUE", p_REFCLK_FREQUENCY=200.0, p_PIPE_SEL="FALSE", p_IDELAY_TYPE="VARIABLE", p_IDELAY_VALUE=0, i_C=ClockSignal(), i_LD=self.rx_delay_rst, i_CE=self.rx_delay_ce, i_LDPIPEEN=0, i_INC=self.rx_delay_inc, i_IDATAIN=serdes_i_nodelay, o_DATAOUT=serdes_i_delayed), Instance("ISERDESE2", p_DATA_WIDTH=8, p_DATA_RATE="DDR", p_SERDES_MODE="MASTER", p_INTERFACE_TYPE="NETWORKING", p_NUM_CE=1, p_IOBDELAY="IFD", i_DDLY=serdes_i_delayed, i_CE1=1, i_RST=ResetSignal("serwb_serdes"), i_CLK=ClockSignal("serwb_serdes_20x"), i_CLKB=~ClockSignal("serwb_serdes_20x"), i_CLKDIV=ClockSignal("serwb_serdes_5x"), i_BITSLIP=0, o_Q8=serdes_q[0], o_Q7=serdes_q[1], o_Q6=serdes_q[2], o_Q5=serdes_q[3], o_Q4=serdes_q[4], o_Q3=serdes_q[5], o_Q2=serdes_q[6], o_Q1=serdes_q[7]) ] self.comb += [ self.rx_gearbox.i.eq(serdes_q), self.rx_bitslip.value.eq(rx_bitslip_value), self.rx_bitslip.i.eq(self.rx_gearbox.o), self.decoders[0].input.eq(self.rx_bitslip.o[0:10]), self.decoders[1].input.eq(self.rx_bitslip.o[10:20]), self.decoders[2].input.eq(self.rx_bitslip.o[20:30]), self.decoders[3].input.eq(self.rx_bitslip.o[30:40]), self.rx_data.eq(Cat(*[self.decoders[i].d for i in range(4)])), rx_idle.eq(self.rx_bitslip.o == 0), rx_comma.eq( ((self.decoders[0].d == 0xbc) & (self.decoders[0].k == 1)) & ((self.decoders[1].d == 0x00) & (self.decoders[1].k == 0)) & ((self.decoders[2].d == 0x00) & (self.decoders[2].k == 0)) & ((self.decoders[3].d == 0x00) & (self.decoders[3].k == 0))) ]
def __init__(self, pads, clkin_freq=None): self._pll_reset = CSRStorage(reset=1) self._locked = CSRStatus() # DRP self._pll_adr = CSRStorage(5) self._pll_dat_r = CSRStatus(16) self._pll_dat_w = CSRStorage(16) self._pll_read = CSR() self._pll_write = CSR() self._pll_drdy = CSRStatus() self.locked = Signal() self.serdesstrobe = Signal() self.clock_domains._cd_pix = ClockDomain() self.clock_domains._cd_pix2x = ClockDomain() self.clock_domains._cd_pix10x = ClockDomain(reset_less=True) # # # self.clk_input = Signal() self.specials += Instance("IBUFDS", name="hdmi_in_ibufds", i_I=pads.clk_p, i_IB=pads.clk_n, o_O=self.clk_input) clkfbout = Signal() pll_locked = Signal() pll_clk0 = Signal() pll_clk1 = Signal() pll_clk2 = Signal() pll_drdy = Signal() self.sync += If(self._pll_read.re | self._pll_write.re, self._pll_drdy.status.eq(0)).Elif( pll_drdy, self._pll_drdy.status.eq(1)) self.specials += [ Instance( "PLL_ADV", name="hdmi_in_pll_adv", p_CLKFBOUT_MULT=10, p_CLKOUT0_DIVIDE=1, # pix10x p_CLKOUT1_DIVIDE=5, # pix2x p_CLKOUT2_DIVIDE=10, # pix p_COMPENSATION="INTERNAL", i_CLKINSEL=1, i_CLKIN1=self.clk_input, o_CLKOUT0=pll_clk0, o_CLKOUT1=pll_clk1, o_CLKOUT2=pll_clk2, o_CLKFBOUT=clkfbout, i_CLKFBIN=clkfbout, o_LOCKED=pll_locked, i_RST=self._pll_reset.storage, i_DADDR=self._pll_adr.storage, o_DO=self._pll_dat_r.status, i_DI=self._pll_dat_w.storage, i_DEN=self._pll_read.re | self._pll_write.re, i_DWE=self._pll_write.re, o_DRDY=pll_drdy, i_DCLK=ClockSignal()) ] locked_async = Signal() self.specials += [ Instance("BUFPLL", name="hdmi_in_bufpll", p_DIVIDE=5, i_PLLIN=pll_clk0, i_GCLK=ClockSignal("pix2x"), i_LOCKED=pll_locked, o_IOCLK=self._cd_pix10x.clk, o_LOCK=locked_async, o_SERDESSTROBE=self.serdesstrobe), Instance("BUFG", name="hdmi_in_pix2x_bufg", i_I=pll_clk1, o_O=self._cd_pix2x.clk), Instance("BUFG", name="hdmi_in_pix_bufg", i_I=pll_clk2, o_O=self._cd_pix.clk), MultiReg(locked_async, self.locked, "sys") ] self.comb += self._locked.status.eq(self.locked) self.specials += [ AsyncResetSynchronizer(self._cd_pix, ~locked_async), AsyncResetSynchronizer(self._cd_pix2x, ~locked_async), ]
def __init__(self, platform, clk_freq): self.clock_domains.cd_sys = ClockDomain() self.clock_domains.cd_sys2x = ClockDomain() self.clock_domains.cd_sdram_half = ClockDomain() self.clock_domains.cd_sdram_full_wr = ClockDomain() self.clock_domains.cd_sdram_full_rd = ClockDomain() self.clock_domains.cd_base50 = ClockDomain() self.clock_domains.cd_encoder = ClockDomain() self.clk8x_wr_strb = Signal() self.clk8x_rd_strb = Signal() self.reset = Signal() f0 = 100 * 1000000 clk100 = platform.request("clk100") clk100a = Signal() self.specials += Instance("IBUFG", i_I=clk100, o_O=clk100a) clk100b = Signal() self.specials += Instance("BUFIO2", p_DIVIDE=1, p_DIVIDE_BYPASS="******", p_I_INVERT="FALSE", i_I=clk100a, o_DIVCLK=clk100b) f = Fraction(int(clk_freq), int(f0)) n, m = f.denominator, f.numerator assert f0 / n * m == clk_freq p = 8 pll_lckd = Signal() pll_fb = Signal() pll = Signal(6) self.specials.pll = [ Instance( "PLL_ADV", p_SIM_DEVICE="SPARTAN6", p_BANDWIDTH="OPTIMIZED", p_COMPENSATION="INTERNAL", p_REF_JITTER=.01, p_CLK_FEEDBACK="CLKFBOUT", i_DADDR=0, i_DCLK=0, i_DEN=0, i_DI=0, i_DWE=0, i_RST=0, i_REL=0, p_DIVCLK_DIVIDE=1, p_CLKFBOUT_MULT=m * p // n, p_CLKFBOUT_PHASE=0., i_CLKIN1=clk100b, i_CLKIN2=0, i_CLKINSEL=1, p_CLKIN1_PERIOD=1e9 / f0, p_CLKIN2_PERIOD=0., i_CLKFBIN=pll_fb, o_CLKFBOUT=pll_fb, o_LOCKED=pll_lckd, o_CLKOUT0=pll[0], p_CLKOUT0_DUTY_CYCLE=.5, o_CLKOUT1=pll[1], p_CLKOUT1_DUTY_CYCLE=.5, o_CLKOUT2=pll[2], p_CLKOUT2_DUTY_CYCLE=.5, o_CLKOUT3=pll[3], p_CLKOUT3_DUTY_CYCLE=.5, o_CLKOUT4=pll[4], p_CLKOUT4_DUTY_CYCLE=.5, o_CLKOUT5=pll[5], p_CLKOUT5_DUTY_CYCLE=.5, p_CLKOUT0_PHASE=0., p_CLKOUT0_DIVIDE=p // 8, # ddr3 wr/rd full clock p_CLKOUT1_PHASE=0., p_CLKOUT1_DIVIDE=6, # encoder (66MHz) p_CLKOUT2_PHASE=230., p_CLKOUT2_DIVIDE=p // 4, # ddr3 dqs adr ctrl off-chip p_CLKOUT3_PHASE=210., p_CLKOUT3_DIVIDE=p // 4, # ddr3 half clock p_CLKOUT4_PHASE=0., p_CLKOUT4_DIVIDE=p // 2, # 2x system clock p_CLKOUT5_PHASE=0., p_CLKOUT5_DIVIDE=p // 1), # system clock Instance("BUFG", i_I=pll[4], o_O=self.cd_sys2x.clk), Instance("BUFG", i_I=pll[5], o_O=self.cd_sys.clk) ] reset = ~platform.request("cpu_reset") | self.reset self.clock_domains.cd_por = ClockDomain() por = Signal(max=1 << 11, reset=(1 << 11) - 1) self.sync.por += If(por != 0, por.eq(por - 1)) self.comb += self.cd_por.clk.eq(self.cd_sys.clk) self.specials += AsyncResetSynchronizer(self.cd_por, reset) self.specials += AsyncResetSynchronizer(self.cd_sys2x, ~pll_lckd | (por > 0)) self.specials += AsyncResetSynchronizer(self.cd_sys, ~pll_lckd | (por > 0)) self.specials += Instance("BUFG", i_I=pll[2], o_O=self.cd_sdram_half.clk) self.specials += Instance("BUFPLL", p_DIVIDE=4, i_PLLIN=pll[0], i_GCLK=self.cd_sys2x.clk, i_LOCKED=pll_lckd, o_IOCLK=self.cd_sdram_full_wr.clk, o_SERDESSTROBE=self.clk8x_wr_strb) self.comb += [ self.cd_sdram_full_rd.clk.eq(self.cd_sdram_full_wr.clk), self.clk8x_rd_strb.eq(self.clk8x_wr_strb), ] clk_sdram_half_shifted = Signal() self.specials += Instance("BUFG", i_I=pll[3], o_O=clk_sdram_half_shifted) output_clk = Signal() clk = platform.request("ddram_clock") self.specials += Instance("ODDR2", p_DDR_ALIGNMENT="NONE", p_INIT=0, p_SRTYPE="SYNC", i_D0=1, i_D1=0, i_S=0, i_R=0, i_CE=1, i_C0=clk_sdram_half_shifted, i_C1=~clk_sdram_half_shifted, o_Q=output_clk) self.specials += Instance("OBUFDS", i_I=output_clk, o_O=clk.p, o_OB=clk.n) dcm_base50_locked = Signal() self.specials += [ Instance("DCM_CLKGEN", p_CLKFXDV_DIVIDE=2, p_CLKFX_DIVIDE=4, p_CLKFX_MD_MAX=1.0, p_CLKFX_MULTIPLY=2, p_CLKIN_PERIOD=10.0, p_SPREAD_SPECTRUM="NONE", p_STARTUP_WAIT="FALSE", i_CLKIN=clk100a, o_CLKFX=self.cd_base50.clk, o_LOCKED=dcm_base50_locked, i_FREEZEDCM=0, i_RST=ResetSignal()), AsyncResetSynchronizer(self.cd_base50, self.cd_sys.rst | ~dcm_base50_locked) ] platform.add_period_constraint(self.cd_base50.clk, 20) self.specials += Instance("BUFG", i_I=pll[1], o_O=self.cd_encoder.clk) # 66 MHz self.specials += AsyncResetSynchronizer(self.cd_encoder, self.cd_sys.rst)
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, pads, clkin_freq=148.5e6): self._mmcm_reset = CSRStorage(reset=1) self._locked = CSRStatus() # DRP self._mmcm_read = CSR() self._mmcm_read_o = CSR() self._mmcm_write = CSR() self._mmcm_write_o = CSR() self._mmcm_drdy = CSRStatus() self._mmcm_drdy_o = CSRStatus() self._mmcm_adr = CSRStorage(7) self._mmcm_dat_w = CSRStorage(16) self._mmcm_dat_r = CSRStatus(16) self._mmcm_dat_o_r = CSRStatus(16) self.locked = Signal() self.clock_domains.cd_pix = ClockDomain() self.clock_domains.cd_pix_o = ClockDomain() self.clock_domains.cd_pix1p25x = ClockDomain() self.clock_domains.cd_pix5x = ClockDomain(reset_less=True) self.clock_domains.cd_pix5x_o = ClockDomain(reset_less=True) # # # assert clkin_freq in [74.25e6, 148.5e6] self.clk_input = Signal() clk_input_bufr = Signal() if hasattr(pads.clk_p, "inverted"): self.specials += Instance("IBUFDS_DIFF_OUT", name="hdmi_in_ibufds", i_I=pads.clk_p, i_IB=pads.clk_n, o_OB=self.clk_input) else: self.specials += Instance("IBUFDS_DIFF_OUT", name="hdmi_in_ibufds", i_I=pads.clk_p, i_IB=pads.clk_n, o_O=self.clk_input) self.specials += Instance("BUFG", i_I=self.clk_input, o_O=clk_input_bufr) mmcm_fb = Signal() mmcm_fb_o = Signal() mmcm_locked = Signal() mmcm_locked_o = Signal() mmcm_clk0 = Signal() mmcm_clk1 = Signal() mmcm_clk2 = Signal() mmcm_clk2_o = Signal() mmcm_drdy = Signal() mmcm_drdy_o = Signal() self.specials += [ Instance( "MMCME2_ADV", p_BANDWIDTH="OPTIMIZED", i_RST=self._mmcm_reset.storage, o_LOCKED=mmcm_locked, # VCO p_REF_JITTER1=0.01, p_CLKIN1_PERIOD=7.2, #6.734 p_CLKFBOUT_MULT_F=5.0, p_CLKFBOUT_PHASE=0.000, p_DIVCLK_DIVIDE=1, i_CLKIN1=clk_input_bufr, i_CLKFBIN=mmcm_fb_o, o_CLKFBOUT=mmcm_fb, # pix clk p_CLKOUT0_DIVIDE_F=5, p_CLKOUT0_PHASE=0.000, o_CLKOUT0=mmcm_clk0, # pix1p25x clk p_CLKOUT1_DIVIDE=4, p_CLKOUT1_PHASE=0.000, o_CLKOUT1=mmcm_clk1, # pix5x clk p_CLKOUT2_DIVIDE=1, p_CLKOUT2_PHASE=0.000, o_CLKOUT2=mmcm_clk2, # DRP i_DCLK=ClockSignal(), i_DWE=self._mmcm_write.re, i_DEN=self._mmcm_read.re | self._mmcm_write.re, o_DRDY=mmcm_drdy, i_DADDR=self._mmcm_adr.storage, i_DI=self._mmcm_dat_w.storage, o_DO=self._mmcm_dat_r.status), Instance("BUFG", i_I=mmcm_clk0, o_O=self.cd_pix.clk), Instance("BUFR", i_I=mmcm_clk1, o_O=self.cd_pix1p25x.clk), Instance("BUFIO", i_I=mmcm_clk2, o_O=self.cd_pix5x.clk), Instance( "BUFG", i_I=mmcm_fb, o_O=mmcm_fb_o ), # compensate this delay to minimize phase offset with slave ] mmcm_fb_o = Signal() mmcm_clk0_o = Signal() self.specials += [ Instance( "MMCME2_ADV", p_BANDWIDTH="LOW", i_RST=self._mmcm_reset.storage, o_LOCKED=mmcm_locked_o, # VCO p_REF_JITTER1=0.01, p_CLKIN1_PERIOD=6.734, p_CLKFBOUT_MULT_F=5.0, p_CLKFBOUT_PHASE=0.000, p_DIVCLK_DIVIDE=1, i_CLKIN1= mmcm_clk0, # uncompesated delay for best phase match between master/slave i_CLKFBIN=mmcm_fb_o, o_CLKFBOUT=mmcm_fb_o, # pix clk p_CLKOUT0_DIVIDE_F=5, p_CLKOUT0_PHASE=0.000, o_CLKOUT0=mmcm_clk0_o, p_CLKOUT2_DIVIDE=1, p_CLKOUT2_PHASE=0.000, o_CLKOUT2=mmcm_clk2_o, # DRP i_DCLK=ClockSignal(), i_DWE=self._mmcm_write_o.re, i_DEN=self._mmcm_read_o.re | self._mmcm_write_o.re, o_DRDY=mmcm_drdy_o, i_DADDR=self._mmcm_adr.storage, i_DI=self._mmcm_dat_w.storage, o_DO=self._mmcm_dat_o_r.status), Instance("BUFG", i_I=mmcm_clk0_o, o_O=self.cd_pix_o.clk), Instance("BUFIO", i_I=mmcm_clk2_o, o_O=self.cd_pix5x_o.clk), ] self.sync += [ If(self._mmcm_read.re | self._mmcm_write.re, self._mmcm_drdy.status.eq(0)).Elif(mmcm_drdy, self._mmcm_drdy.status.eq(1)) ] self.sync += [ If(self._mmcm_read_o.re | self._mmcm_write_o.re, self._mmcm_drdy_o.status.eq(0)).Elif( mmcm_drdy_o, self._mmcm_drdy_o.status.eq(1)) ] self.specials += MultiReg(mmcm_locked, self.locked, "sys") self.comb += self._locked.status.eq(self.locked) self.specials += [ AsyncResetSynchronizer(self.cd_pix, ~mmcm_locked), AsyncResetSynchronizer(self.cd_pix_o, ~mmcm_locked_o), AsyncResetSynchronizer(self.cd_pix1p25x, ~mmcm_locked), ]
def __init__(self, pll, tx_pads, sys_clk_freq, polarity=0): self.prbs_config = Signal(2) self.produce_square_wave = CSRStorage() self.txdiffcttrl = CSRStorage(4, reset=0b1000) self.txmaincursor = CSRStorage(7, reset=80) self.txprecursor = CSRStorage(5) self.txpostcursor = CSRStorage(5) # # # use_cpll = isinstance(pll, GTXChannelPLL) use_qpll = isinstance(pll, GTXQuadPLL) self.submodules.init = GTXInit(sys_clk_freq, False) self.comb += [ self.init.plllock.eq(pll.lock), pll.reset.eq(self.init.pllreset) ] nwords = 40 // 10 txoutclk = Signal() txdata = Signal(40) self.specials += \ Instance("GTXE2_CHANNEL", # PMA Attributes p_PMA_RSV=0x00018480, p_PMA_RSV2=0x2050, p_PMA_RSV3=0, p_PMA_RSV4=0, p_RX_BIAS_CFG=0b100, p_RX_CM_TRIM=0b010, p_RX_OS_CFG=0b10000000, p_RX_CLK25_DIV=5, p_TX_CLK25_DIV=5, # Power-Down Attributes p_PD_TRANS_TIME_FROM_P2=0x3c, p_PD_TRANS_TIME_NONE_P2=0x3c, p_PD_TRANS_TIME_TO_P2=0x64, # CPLL p_CPLL_CFG=0xBC07DC, p_CPLL_FBDIV=1 if use_qpll else pll.config["n2"], p_CPLL_FBDIV_45=4 if use_qpll else pll.config["n1"], p_CPLL_REFCLK_DIV=1 if use_qpll else pll.config["m"], p_RXOUT_DIV=pll.config["d"], p_TXOUT_DIV=pll.config["d"], i_CPLLRESET=0 if use_qpll else pll.reset, o_CPLLLOCK=Signal() if use_qpll else pll.lock, i_CPLLLOCKEN=1, i_CPLLREFCLKSEL=0b001, i_TSTIN=2**20-1, i_GTREFCLK0=0 if use_qpll else pll.refclk, # QPLL i_QPLLCLK=0 if use_cpll else pll.clk, i_QPLLREFCLK=0 if use_cpll else pll.refclk, # TX clock p_TXBUF_EN="FALSE", p_TX_XCLK_SEL="TXUSR", o_TXOUTCLK=txoutclk, i_TXSYSCLKSEL=0b11 if use_qpll else 0b00, i_TXOUTCLKSEL=0b11, # disable RX i_RXPD=0b11, # Startup/Reset i_GTTXRESET=self.init.gtXxreset, o_TXRESETDONE=self.init.Xxresetdone, i_TXDLYSRESET=self.init.Xxdlysreset, o_TXDLYSRESETDONE=self.init.Xxdlysresetdone, o_TXPHALIGNDONE=self.init.Xxphaligndone, i_TXUSERRDY=self.init.Xxuserrdy, # TX data p_TX_DATA_WIDTH=40, p_TX_INT_DATAWIDTH=1, i_TXCHARDISPMODE=Cat(*[txdata[10*i+9] for i in range(nwords)]), i_TXCHARDISPVAL=Cat(*[txdata[10*i+8] for i in range(nwords)]), i_TXDATA=Cat(*[txdata[10*i:10*i+8] for i in range(nwords)]), i_TXUSRCLK=ClockSignal("tx"), i_TXUSRCLK2=ClockSignal("tx"), # TX electrical i_TXBUFDIFFCTRL=0b100, i_TXDIFFCTRL=self.txdiffcttrl.storage, p_TX_MAINCURSOR_SEL=1, i_TXMAINCURSOR=self.txmaincursor.storage, i_TXPRECURSOR=self.txprecursor.storage, i_TXPOSTCURSOR=self.txpostcursor.storage, # Polarity i_TXPOLARITY=polarity, # Pads o_GTXTXP=tx_pads.txp, o_GTXTXN=tx_pads.txn ) self.clock_domains.cd_tx = ClockDomain() self.specials += Instance("BUFH", i_I=txoutclk, o_O=self.cd_tx.clk) self.specials += AsyncResetSynchronizer(self.cd_tx, ~self.init.done) self.submodules.encoder = ClockDomainsRenamer("tx")(Encoder( nwords, True)) self.submodules.prbs = ClockDomainsRenamer("tx")(PRBSTX(40, True)) self.comb += [ self.prbs.config.eq(self.prbs_config), self.prbs.i.eq( Cat(*[self.encoder.output[i] for i in range(nwords)])), If( self.produce_square_wave.storage, # square wave @ linerate/40 for scope observation txdata.eq(0b1111111111111111111100000000000000000000)).Else( txdata.eq(self.prbs.o)) ]
def __init__(self, platform, usb_connector=0, with_usb2=True, with_usb2_analyzer=False, with_usb3=True, with_usb3_analyzer=False): BaseSoC.__init__(self, platform) # usb ios usb_reset_n = platform.request("usb_reset_n", usb_connector) if with_usb2: usb_ulpi = platform.request("usb_ulpi", usb_connector) if with_usb3: usb_pipe_ctrl = platform.request("usb_pipe_ctrl", usb_connector) usb_pipe_status = platform.request("usb_pipe_status", usb_connector) usb_pipe_data = platform.request("usb_pipe_data", usb_connector) usb2_reset_n = Signal(reset=1) usb3_reset_n = Signal(reset=1) self.comb += usb_reset_n.eq(usb2_reset_n & usb3_reset_n) # usb2 core if with_usb2: class USB2Control(Module, AutoCSR): def __init__(self): self._phy_enable = CSRStorage() self._core_enable = CSRStorage() # probably not working but prevent synthesis optimizations self._buf_in_addr = CSRStorage(9) self._buf_in_data = CSRStorage(8) self._buf_in_wren = CSR() self._buf_in_ready = CSRStatus() self._buf_in_commit = CSR() self._buf_in_commit_len = CSRStorage(10) self._buf_in_commit_ack = CSRStatus() self._buf_out_addr = CSRStorage(9) self._buf_out_q = CSRStatus(8) self._buf_out_len = CSRStatus(10) self._buf_out_hasdata = CSRStatus() self._buf_out_arm = CSR() self._buf_out_arm_ack = CSRStatus() # # # self.phy_enable = self._phy_enable.storage self.core_enable = self._core_enable.storage self.buf_in_addr = self._buf_in_addr.storage self.buf_in_data = self._buf_in_data.storage self.buf_in_wren = self._buf_in_wren.re & self._buf_in_wren.r self.buf_in_ready = self._buf_in_ready.status self.buf_in_commit = self._buf_in_commit.re & self._buf_in_commit.r self.buf_in_commit_len = self._buf_in_commit_len.storage self.buf_in_commit_ack = self._buf_in_commit_ack.status self.buf_out_addr = self._buf_out_addr.storage self.buf_out_q = self._buf_out_q.status self.buf_out_len = self._buf_out_len.status self.buf_out_hasdata = self._buf_out_hasdata.status self.buf_out_arm = self._buf_out_arm.re & self._buf_out_arm.r self.buf_out_arm_ack = self._buf_out_arm_ack.status self.submodules.usb2_control = USB2Control() self.clock_domains.cd_ulpi = ClockDomain() self.comb += self.cd_ulpi.clk.eq(usb_ulpi.clk) self.cd_ulpi.clk.attr.add("keep") self.platform.add_period_constraint(self.cd_ulpi.clk, 16.667) self.platform.add_false_path_constraints(self.crg.cd_sys.clk, self.cd_ulpi.clk) stat_connected = Signal() stat_fs = Signal() stat_hs = Signal() stat_configured = Signal() vend_req_act = Signal() vend_req_request = Signal(8) vend_req_val = Signal(16) err_crc_pid = Signal() err_crc_tok = Signal() err_crc_pkt = Signal() err_pid_out_of_seq = Signal() err_setup_pkt = Signal() dbg_frame_num = Signal(11) dbg_linestate = Signal(2) self.comb += usb2_reset_n.eq(self.usb2_control.phy_enable) self.specials += Instance( "usb2_top", i_ext_clk=ClockSignal(), i_reset_n=self.usb2_control.core_enable, #o_reset_n_out=, i_phy_ulpi_clk=usb_ulpi.clk, io_phy_ulpi_d=usb_ulpi.data, i_phy_ulpi_dir=usb_ulpi.dir, o_phy_ulpi_stp=usb_ulpi.stp, i_phy_ulpi_nxt=usb_ulpi.nxt, i_opt_disable_all=0, i_opt_enable_hs=0, i_opt_ignore_vbus=0, o_stat_connected=stat_connected, o_stat_fs=stat_fs, o_stat_hs=stat_hs, o_stat_configured=stat_configured, i_buf_in_addr=self.usb2_control.buf_in_addr, i_buf_in_data=self.usb2_control.buf_in_data, i_buf_in_wren=self.usb2_control.buf_in_wren, o_buf_in_ready=self.usb2_control.buf_in_ready, i_buf_in_commit=self.usb2_control.buf_in_commit, i_buf_in_commit_len=self.usb2_control.buf_in_commit_len, o_buf_in_commit_ack=self.usb2_control.buf_in_commit_ack, i_buf_out_addr=self.usb2_control.buf_out_addr, o_buf_out_q=self.usb2_control.buf_out_q, o_buf_out_len=self.usb2_control.buf_out_len, o_buf_out_hasdata=self.usb2_control.buf_out_hasdata, i_buf_out_arm=self.usb2_control.buf_out_arm, o_buf_out_arm_ack=self.usb2_control.buf_out_arm_ack, o_vend_req_act=vend_req_act, o_vend_req_request=vend_req_request, o_vend_req_val=vend_req_val, o_err_crc_pid=err_crc_pid, o_err_crc_tok=err_crc_tok, o_err_crc_pkt=err_crc_pkt, o_err_pid_out_of_seq=err_pid_out_of_seq, o_err_setup_pkt=err_setup_pkt, o_dbg_frame_num=dbg_frame_num, o_dbg_linestate=dbg_linestate) platform.add_verilog_include_path(os.path.join("core")) platform.add_verilog_include_path(os.path.join("core", "usb2")) platform.add_source_dir(os.path.join("core", "usb2")) # usb2 debug if with_usb2_analyzer: analyzer_signals = [ dbg_frame_num, dbg_linestate, stat_connected, stat_fs, stat_hs, stat_configured, vend_req_act, vend_req_request, vend_req_val, err_crc_pid, err_crc_tok, err_crc_pkt, err_pid_out_of_seq, err_setup_pkt ] self.submodules.analyzer = LiteScopeAnalyzer(analyzer_signals, 2048, cd="ulpi") # usb3 core if with_usb3: class USB3Control(Module, AutoCSR): def __init__(self): self._phy_enable = CSRStorage() self._core_enable = CSRStorage() # probably not working but prevent synthesis optimizations self._buf_in_addr = CSRStorage(9) self._buf_in_data = CSRStorage(32) self._buf_in_wren = CSR() self._buf_in_request = CSRStatus() self._buf_in_ready = CSRStatus() self._buf_in_commit = CSR() self._buf_in_commit_len = CSRStorage(11) self._buf_in_commit_ack = CSRStatus() self._buf_out_addr = CSRStorage(9) self._buf_out_q = CSRStatus(32) self._buf_out_len = CSRStatus(11) self._buf_out_hasdata = CSRStatus() self._buf_out_arm = CSR() self._buf_out_arm_ack = CSRStatus() # # # self.phy_enable = self._phy_enable.storage self.core_enable = self._core_enable.storage self.buf_in_addr = self._buf_in_addr.storage self.buf_in_data = self._buf_in_data.storage self.buf_in_wren = self._buf_in_wren.re & self._buf_in_wren.r self.buf_in_request = self._buf_in_request.status self.buf_in_ready = self._buf_in_ready.status self.buf_in_commit = self._buf_in_commit.re & self._buf_in_commit.r self.buf_in_commit_len = self._buf_in_commit_len.storage self.buf_in_commit_ack = self._buf_in_commit_ack.status self.buf_out_addr = self._buf_out_addr.storage self.buf_out_q = self._buf_out_q.status self.buf_out_len = self._buf_out_len.status self.buf_out_hasdata = self._buf_out_hasdata.status self.buf_out_arm = self._buf_out_arm.re & self._buf_out_arm.r self.buf_out_arm_ack = self._buf_out_arm_ack.status self.submodules.usb3_control = USB3Control() phy_pipe_pll_locked = Signal() phy_pipe_pll_fb = Signal() phy_pipe_half_clk_pll = Signal() phy_pipe_half_clk_phase_pll = Signal() phy_pipe_quarter_clk_pll = Signal() phy_pipe_tx_clk_phase_pll = Signal() phy_pipe_half_clk = Signal() phy_pipe_half_clk_phase = Signal() phy_pipe_quarter_clk = Signal() phy_pipe_tx_clk_phase = Signal() self.specials += [ Instance( "PLLE2_BASE", p_STARTUP_WAIT="FALSE", o_LOCKED=phy_pipe_pll_locked, # VCO @ 1GHz p_REF_JITTER1=0.01, p_CLKIN1_PERIOD=4.0, p_CLKFBOUT_MULT=4, p_DIVCLK_DIVIDE=1, i_CLKIN1=usb_pipe_data.rx_clk, i_CLKFBIN=phy_pipe_pll_fb, o_CLKFBOUT=phy_pipe_pll_fb, # 125MHz: 1/2 PCLK p_CLKOUT0_DIVIDE=8, p_CLKOUT0_PHASE=0.0, o_CLKOUT0=phy_pipe_half_clk_pll, # 125MHz: 1/2 PCLK, phase shift 90 p_CLKOUT1_DIVIDE=8, p_CLKOUT1_PHASE=90.0, o_CLKOUT1=phy_pipe_half_clk_phase_pll, # 62.5MHz: 1/4 PCLK p_CLKOUT2_DIVIDE=16, p_CLKOUT2_PHASE=0.0, o_CLKOUT2=phy_pipe_quarter_clk_pll, # 250Mhz: TX CLK, phase shift 90 p_CLKOUT3_DIVIDE=4, p_CLKOUT3_PHASE=90.0, o_CLKOUT3=phy_pipe_tx_clk_phase_pll), Instance("BUFG", i_I=phy_pipe_half_clk_pll, o_O=phy_pipe_half_clk), Instance("BUFG", i_I=phy_pipe_half_clk_phase_pll, o_O=phy_pipe_half_clk_phase), Instance("BUFG", i_I=phy_pipe_quarter_clk_pll, o_O=phy_pipe_quarter_clk), Instance("BUFG", i_I=phy_pipe_tx_clk_phase_pll, o_O=phy_pipe_tx_clk_phase), ] self.clock_domains.cd_phy_pipe_half = ClockDomain() self.clock_domains.cd_phy_pipe_half_phase = ClockDomain() self.clock_domains.cd_phy_pipe_quarter = ClockDomain() self.clock_domains.cd_phy_pipe_tx_phase = ClockDomain() self.comb += [ self.cd_phy_pipe_half.clk.eq(phy_pipe_half_clk), self.cd_phy_pipe_half_phase.clk.eq(phy_pipe_half_clk_phase), self.cd_phy_pipe_quarter.clk.eq(phy_pipe_quarter_clk), self.cd_phy_pipe_tx_phase.clk.eq(phy_pipe_tx_clk_phase) ] self.specials += [ AsyncResetSynchronizer(self.cd_phy_pipe_half, ~phy_pipe_pll_locked), AsyncResetSynchronizer(self.cd_phy_pipe_half_phase, ~phy_pipe_pll_locked), AsyncResetSynchronizer(self.cd_phy_pipe_quarter, ~phy_pipe_pll_locked), AsyncResetSynchronizer(self.cd_phy_pipe_tx_phase, ~phy_pipe_pll_locked) ] self.cd_phy_pipe_half.clk.attr.add("keep") self.cd_phy_pipe_half_phase.clk.attr.add("keep") self.cd_phy_pipe_quarter.clk.attr.add("keep") self.cd_phy_pipe_tx_phase.clk.attr.add("keep") self.platform.add_period_constraint(self.cd_phy_pipe_half.clk, 8.0) self.platform.add_period_constraint( self.cd_phy_pipe_half_phase.clk, 8.0) self.platform.add_period_constraint(self.cd_phy_pipe_quarter.clk, 16.0) self.platform.add_period_constraint(self.cd_phy_pipe_tx_phase.clk, 4.0) self.platform.add_false_path_constraints( self.crg.cd_sys.clk, self.cd_phy_pipe_half.clk, self.cd_phy_pipe_half_phase.clk, self.cd_phy_pipe_quarter.clk, self.cd_phy_pipe_tx_phase.clk) phy_pipe_rx_data = Signal(32) phy_pipe_rx_datak = Signal(4) phy_pipe_rx_valid = Signal(2) phy_pipe_tx_data = Signal(32) phy_pipe_tx_datak = Signal(4) phy_rx_status = Signal(6) phy_phy_status = Signal(2) dbg_pipe_state = Signal(6) dbg_ltssm_state = Signal(5) usb_pipe_status_phy_status = Signal() self.specials += Tristate(usb_pipe_status.phy_status, 0, ~usb3_reset_n, usb_pipe_status_phy_status) self.comb += usb3_reset_n.eq(self.usb3_control.phy_enable) self.specials += Instance( "usb3_top", i_ext_clk=ClockSignal(), i_reset_n=self.usb3_control.core_enable, i_phy_pipe_half_clk=ClockSignal("phy_pipe_half"), i_phy_pipe_half_clk_phase=ClockSignal("phy_pipe_half_phase"), i_phy_pipe_quarter_clk=ClockSignal("phy_pipe_quarter"), i_phy_pipe_rx_data=phy_pipe_rx_data, i_phy_pipe_rx_datak=phy_pipe_rx_datak, i_phy_pipe_rx_valid=phy_pipe_rx_valid, o_phy_pipe_tx_data=phy_pipe_tx_data, o_phy_pipe_tx_datak=phy_pipe_tx_datak, #o_phy_reset_n=, #o_phy_out_enable=, o_phy_phy_reset_n=usb_pipe_ctrl.phy_reset_n, o_phy_tx_detrx_lpbk=usb_pipe_ctrl.tx_detrx_lpbk, o_phy_tx_elecidle=usb_pipe_ctrl.tx_elecidle, io_phy_rx_elecidle=usb_pipe_status.rx_elecidle, i_phy_rx_status=phy_rx_status, o_phy_power_down=usb_pipe_ctrl.power_down, i_phy_phy_status_i=phy_phy_status, #o_phy_phy_status_o=, i_phy_pwrpresent=usb_pipe_status.pwr_present, o_phy_tx_oneszeros=usb_pipe_ctrl.tx_oneszeros, o_phy_tx_deemph=usb_pipe_ctrl.tx_deemph, o_phy_tx_margin=usb_pipe_ctrl.tx_margin, o_phy_tx_swing=usb_pipe_ctrl.tx_swing, o_phy_rx_polarity=usb_pipe_ctrl.rx_polarity, o_phy_rx_termination=usb_pipe_ctrl.rx_termination, o_phy_rate=usb_pipe_ctrl.rate, o_phy_elas_buf_mode=usb_pipe_ctrl.elas_buf_mode, i_buf_in_addr=self.usb3_control.buf_in_addr, i_buf_in_data=self.usb3_control.buf_in_data, i_buf_in_wren=self.usb3_control.buf_in_wren, o_buf_in_request=self.usb3_control.buf_in_request, o_buf_in_ready=self.usb3_control.buf_in_ready, i_buf_in_commit=self.usb3_control.buf_in_commit, i_buf_in_commit_len=self.usb3_control.buf_in_commit_len, o_buf_in_commit_ack=self.usb3_control.buf_in_commit_ack, i_buf_out_addr=self.usb3_control.buf_out_addr, o_buf_out_q=self.usb3_control.buf_out_q, o_buf_out_len=self.usb3_control.buf_out_len, o_buf_out_hasdata=self.usb3_control.buf_out_hasdata, i_buf_out_arm=self.usb3_control.buf_out_arm, o_buf_out_arm_ack=self.usb3_control.buf_out_arm_ack, #o_vend_req_act=, #o_vend_req_request=, #o_vend_req_val=, o_dbg_pipe_state=dbg_pipe_state, o_dbg_ltssm_state=dbg_ltssm_state) platform.add_verilog_include_path(os.path.join("core")) platform.add_verilog_include_path(os.path.join("core", "usb3")) platform.add_source_dir(os.path.join("core", "usb3")) # ddr inputs self.specials += Instance( "IDDR", p_DDR_CLK_EDGE="SAME_EDGE_PIPELINED", i_C=ClockSignal("phy_pipe_half"), i_CE=1, i_S=0, i_R=0, i_D=usb_pipe_data.rx_valid, o_Q1=phy_pipe_rx_valid[0], o_Q2=phy_pipe_rx_valid[1], ) for i in range(16): self.specials += Instance( "IDDR", p_DDR_CLK_EDGE="SAME_EDGE_PIPELINED", i_C=ClockSignal("phy_pipe_half"), i_CE=1, i_S=0, i_R=0, i_D=usb_pipe_data.rx_data[i], o_Q1=phy_pipe_rx_data[i], o_Q2=phy_pipe_rx_data[16 + i], ) for i in range(2): self.specials += Instance( "IDDR", p_DDR_CLK_EDGE="SAME_EDGE_PIPELINED", i_C=ClockSignal("phy_pipe_half"), i_CE=1, i_S=0, i_R=0, i_D=usb_pipe_data.rx_datak[i], o_Q1=phy_pipe_rx_datak[i], o_Q2=phy_pipe_rx_datak[2 + i], ) for i in range(3): self.specials += Instance( "IDDR", p_DDR_CLK_EDGE="SAME_EDGE_PIPELINED", i_C=ClockSignal("phy_pipe_half"), i_CE=1, i_S=0, i_R=0, i_D=usb_pipe_status.rx_status[i], o_Q1=phy_rx_status[i], o_Q2=phy_rx_status[3 + i], ) self.specials += Instance( "IDDR", p_DDR_CLK_EDGE="SAME_EDGE_PIPELINED", i_C=ClockSignal("phy_pipe_half"), i_CE=1, i_S=0, i_R=0, i_D=usb_pipe_status_phy_status, o_Q1=phy_phy_status[0], o_Q2=phy_phy_status[1], ) # ddr outputs self.specials += Instance( "ODDR", p_DDR_CLK_EDGE="SAME_EDGE", i_C=ClockSignal("phy_pipe_tx_phase"), i_CE=1, i_S=0, i_R=0, i_D1=1, i_D2=0, o_Q=usb_pipe_data.tx_clk, ) for i in range(16): self.specials += Instance( "ODDR", p_DDR_CLK_EDGE="SAME_EDGE", i_C=ClockSignal("phy_pipe_half_phase"), i_CE=1, i_S=0, i_R=0, i_D1=phy_pipe_tx_data[i], i_D2=phy_pipe_tx_data[16 + i], o_Q=usb_pipe_data.tx_data[i], ) for i in range(2): self.specials += Instance( "ODDR", p_DDR_CLK_EDGE="SAME_EDGE", i_C=ClockSignal("phy_pipe_half_phase"), i_CE=1, i_S=0, i_R=0, i_D1=phy_pipe_tx_datak[i], i_D2=phy_pipe_tx_datak[2 + i], o_Q=usb_pipe_data.tx_datak[i], ) # usb3 debug if with_usb3_analyzer: analyzer_signals = [ dbg_pipe_state, dbg_ltssm_state, usb_pipe_ctrl.tx_detrx_lpbk, usb_pipe_ctrl.tx_elecidle, usb_pipe_status.rx_elecidle, usb_pipe_ctrl.power_down, usb_pipe_status.phy_status, usb_pipe_status.pwr_present, usb_pipe_ctrl.tx_oneszeros, usb_pipe_ctrl.tx_deemph, usb_pipe_ctrl.tx_margin, usb_pipe_ctrl.tx_swing, usb_pipe_ctrl.rx_polarity, usb_pipe_ctrl.rx_termination, usb_pipe_ctrl.rate, usb_pipe_ctrl.elas_buf_mode, phy_pipe_rx_valid, phy_pipe_rx_data, phy_pipe_rx_datak, phy_pipe_tx_data, phy_pipe_tx_datak ] self.submodules.analyzer = LiteScopeAnalyzer( analyzer_signals, 2048, cd="phy_pipe_half")
def __init__(self, pll, tx_pads, rx_pads, sys_clk_freq, dw=20, mode="master"): assert (dw == 20) or (dw == 40) assert mode in ["master", "slave"] # # # nwords = dw // 10 use_cpll = isinstance(pll, GTHChannelPLL) use_qpll0 = isinstance(pll, GTHQuadPLL) and pll.config["qpll"] == "qpll0" use_qpll1 = isinstance(pll, GTHQuadPLL) and pll.config["qpll"] == "qpll1" self.submodules.encoder = encoder = ClockDomainsRenamer("rtio_tx")( Encoder(nwords, True)) self.submodules.decoders = decoders = [ ClockDomainsRenamer("rtio_rx")((Decoder(True))) for _ in range(nwords) ] self.rx_ready = Signal() self.rtio_clk_freq = pll.config["linerate"] / dw # transceiver direct clock outputs # useful to specify clock constraints in a way palatable to Vivado self.txoutclk = Signal() self.rxoutclk = Signal() # # # # TX generates RTIO clock, init must be in system domain tx_init = GTHInit(sys_clk_freq, False) # RX receives restart commands from RTIO domain rx_init = ClockDomainsRenamer("rtio_tx")(GTHInit( self.rtio_clk_freq, True)) self.submodules += tx_init, rx_init self.comb += [ tx_init.plllock.eq(pll.lock), rx_init.plllock.eq(pll.lock) ] txdata = Signal(dw) rxdata = Signal(dw) rxphaligndone = Signal() self.specials += \ Instance("GTHE3_CHANNEL", # Reset modes i_GTRESETSEL=0, i_RESETOVRD=0, # PMA Attributes p_PMA_RSV1=0xf800, p_RX_BIAS_CFG0=0x0AB4, p_RX_CM_TRIM=0b1010, p_RX_CLK25_DIV=5, p_TX_CLK25_DIV=5, # Power-Down Attributes p_PD_TRANS_TIME_FROM_P2=0x3c, p_PD_TRANS_TIME_NONE_P2=0x19, p_PD_TRANS_TIME_TO_P2=0x64, # CPLL p_CPLL_CFG0=0x67f8, p_CPLL_CFG1=0xa4ac, p_CPLL_CFG2=0xf007, p_CPLL_CFG3=0x0000, p_CPLL_FBDIV=1 if use_qpll0 or use_qpll1 else pll.config["n2"], p_CPLL_FBDIV_45=4 if use_qpll0 or use_qpll1 else pll.config["n1"], p_CPLL_REFCLK_DIV=1 if use_qpll0 or use_qpll1 else pll.config["m"], p_RXOUT_DIV=pll.config["d"], p_TXOUT_DIV=pll.config["d"], i_CPLLRESET=0, i_CPLLPD=0 if use_qpll0 or use_qpll1 else pll.reset, o_CPLLLOCK=Signal() if use_qpll0 or use_qpll1 else pll.lock, i_CPLLLOCKEN=1, i_CPLLREFCLKSEL=0b001, i_TSTIN=2**20-1, i_GTREFCLK0=0 if use_qpll0 or use_qpll1 else pll.refclk, # QPLL i_QPLL0CLK=0 if use_cpll or use_qpll1 else pll.clk, i_QPLL0REFCLK=0 if use_cpll or use_qpll1 else pll.refclk, i_QPLL1CLK=0 if use_cpll or use_qpll0 else pll.clk, i_QPLL1REFCLK=0 if use_cpll or use_qpll0 else pll.refclk, # TX clock p_TXBUF_EN="FALSE", p_TX_XCLK_SEL="TXUSR", o_TXOUTCLK=self.txoutclk, i_TXSYSCLKSEL=0b00 if use_cpll else 0b10 if use_qpll0 else 0b11, i_TXPLLCLKSEL=0b00 if use_cpll else 0b11 if use_qpll0 else 0b10, i_TXOUTCLKSEL=0b11, # TX Startup/Reset i_GTTXRESET=tx_init.gtXxreset, o_TXRESETDONE=tx_init.Xxresetdone, i_TXDLYSRESET=tx_init.Xxdlysreset, o_TXDLYSRESETDONE=tx_init.Xxdlysresetdone, o_TXPHALIGNDONE=tx_init.Xxphaligndone, i_TXUSERRDY=tx_init.Xxuserrdy, i_TXSYNCMODE=1, # TX data p_TX_DATA_WIDTH=dw, p_TX_INT_DATAWIDTH=dw == 40, i_TXCTRL0=Cat(*[txdata[10*i+8] for i in range(nwords)]), i_TXCTRL1=Cat(*[txdata[10*i+9] for i in range(nwords)]), i_TXDATA=Cat(*[txdata[10*i:10*i+8] for i in range(nwords)]), i_TXUSRCLK=ClockSignal("rtio_tx"), i_TXUSRCLK2=ClockSignal("rtio_tx"), # TX electrical i_TXPD=0b00, p_TX_CLKMUX_EN=1, i_TXBUFDIFFCTRL=0b000, i_TXDIFFCTRL=0b1100, # RX Startup/Reset i_GTRXRESET=rx_init.gtXxreset, o_RXRESETDONE=rx_init.Xxresetdone, i_RXDLYSRESET=rx_init.Xxdlysreset, o_RXPHALIGNDONE=rxphaligndone, i_RXSYNCALLIN=rxphaligndone, i_RXUSERRDY=rx_init.Xxuserrdy, i_RXSYNCIN=0, i_RXSYNCMODE=1, o_RXSYNCDONE=rx_init.Xxsyncdone, # RX AFE i_RXDFEAGCCTRL=1, i_RXDFEXYDEN=1, i_RXLPMEN=1, i_RXOSINTCFG=0xd, i_RXOSINTEN=1, # RX clock i_RXRATE=0, i_RXDLYBYPASS=0, p_RXBUF_EN="FALSE", p_RX_XCLK_SEL="RXUSR", i_RXSYSCLKSEL=0b00, i_RXOUTCLKSEL=0b010, i_RXPLLCLKSEL=0b00, o_RXOUTCLK=self.rxoutclk, i_RXUSRCLK=ClockSignal("rtio_rx"), i_RXUSRCLK2=ClockSignal("rtio_rx"), # RX Clock Correction Attributes p_CLK_CORRECT_USE="FALSE", p_CLK_COR_SEQ_1_1=0b0100000000, p_CLK_COR_SEQ_2_1=0b0100000000, p_CLK_COR_SEQ_1_ENABLE=0b1111, p_CLK_COR_SEQ_2_ENABLE=0b1111, # RX data p_RX_DATA_WIDTH=dw, p_RX_INT_DATAWIDTH=dw == 40, o_RXCTRL0=Cat(*[rxdata[10*i+8] for i in range(nwords)]), o_RXCTRL1=Cat(*[rxdata[10*i+9] for i in range(nwords)]), o_RXDATA=Cat(*[rxdata[10*i:10*i+8] for i in range(nwords)]), # RX electrical i_RXPD=0b00, p_RX_CLKMUX_EN=1, i_RXELECIDLEMODE=0b11, # Pads i_GTHRXP=rx_pads.p, i_GTHRXN=rx_pads.n, o_GTHTXP=tx_pads.p, o_GTHTXN=tx_pads.n ) # tx clocking tx_reset_deglitched = Signal() tx_reset_deglitched.attr.add("no_retiming") self.sync += tx_reset_deglitched.eq(~tx_init.done) self.clock_domains.cd_rtio_tx = ClockDomain() if mode is "master": tx_bufg_div = pll.config["clkin"] / self.rtio_clk_freq assert tx_bufg_div == int(tx_bufg_div) self.specials += \ Instance("BUFG_GT", i_I=self.txoutclk, o_O=self.cd_rtio_tx.clk, i_DIV=int(tx_bufg_div)-1) self.specials += AsyncResetSynchronizer(self.cd_rtio_tx, tx_reset_deglitched) # rx clocking rx_reset_deglitched = Signal() rx_reset_deglitched.attr.add("no_retiming") self.sync.rtio_tx += rx_reset_deglitched.eq(~rx_init.done) self.clock_domains.cd_rtio_rx = ClockDomain() self.specials += [ Instance("BUFG_GT", i_I=self.rxoutclk, o_O=self.cd_rtio_rx.clk), AsyncResetSynchronizer(self.cd_rtio_rx, rx_reset_deglitched) ] # tx data self.comb += txdata.eq(Cat(*[encoder.output[i] for i in range(nwords)])) # rx data for i in range(nwords): self.comb += decoders[i].input.eq(rxdata[10 * i:10 * (i + 1)]) # clock alignment clock_aligner = BruteforceClockAligner(0b0101111100, self.rtio_clk_freq) self.submodules += clock_aligner self.comb += [ clock_aligner.rxdata.eq(rxdata), rx_init.restart.eq(clock_aligner.restart), self.rx_ready.eq(clock_aligner.ready) ]
def __init__(self, platform, clk_freq): # Clock domains for the system (soft CPU and related components run at). self.clock_domains.cd_sys = ClockDomain() self.clock_domains.cd_sys2x = ClockDomain() # Clock domains for the DDR interface. self.clock_domains.cd_sdram_half = ClockDomain() self.clock_domains.cd_sdram_full_wr = ClockDomain() self.clock_domains.cd_sdram_full_rd = ClockDomain() # Clock domain for peripherals (such as HDMI output). self.clock_domains.cd_base50 = ClockDomain() self.clock_domains.cd_encoder = ClockDomain() self.reset = Signal() # Input 100MHz clock f0 = 100 * 1000000 clk100 = platform.request("clk100") clk100a = Signal() # Input 100MHz clock (buffered) self.specials += Instance("IBUFG", i_I=clk100, o_O=clk100a) clk100b = Signal() self.specials += Instance("BUFIO2", p_DIVIDE=1, p_DIVIDE_BYPASS="******", p_I_INVERT="FALSE", i_I=clk100a, o_DIVCLK=clk100b) f = Fraction(int(clk_freq), int(f0)) n, m = f.denominator, f.numerator assert f0 / n * m == clk_freq p = 8 # Unbuffered output signals from the PLL. They need to be buffered # before feeding into the fabric. unbuf_sdram_full = Signal() unbuf_sdram_half_a = Signal() unbuf_sdram_half_b = Signal() unbuf_encoder = Signal() unbuf_sys = Signal() unbuf_sys2x = Signal() # PLL signals pll_lckd = Signal() pll_fb = Signal() self.specials.pll = Instance( "PLL_ADV", name="crg_pll_adv", p_SIM_DEVICE="SPARTAN6", p_BANDWIDTH="OPTIMIZED", p_COMPENSATION="INTERNAL", p_REF_JITTER=.01, i_DADDR=0, i_DCLK=0, i_DEN=0, i_DI=0, i_DWE=0, i_RST=0, i_REL=0, p_DIVCLK_DIVIDE=1, # Input Clocks (100MHz) i_CLKIN1=clk100b, p_CLKIN1_PERIOD=1e9 / f0, i_CLKIN2=0, p_CLKIN2_PERIOD=0., i_CLKINSEL=1, # Feedback i_CLKFBIN=pll_fb, o_CLKFBOUT=pll_fb, o_LOCKED=pll_lckd, p_CLK_FEEDBACK="CLKFBOUT", p_CLKFBOUT_MULT=m * p // n, p_CLKFBOUT_PHASE=0., # (400MHz) ddr3 wr/rd full clock o_CLKOUT0=unbuf_sdram_full, p_CLKOUT0_DUTY_CYCLE=.5, p_CLKOUT0_PHASE=0., p_CLKOUT0_DIVIDE=p // 8, # ( 66MHz) encoder o_CLKOUT1=unbuf_encoder, p_CLKOUT1_DUTY_CYCLE=.5, p_CLKOUT1_PHASE=0., p_CLKOUT1_DIVIDE=6, # (200MHz) sdram_half - ddr3 dqs adr ctrl off-chip o_CLKOUT2=unbuf_sdram_half_a, p_CLKOUT2_DUTY_CYCLE=.5, p_CLKOUT2_PHASE=230., p_CLKOUT2_DIVIDE=p // 4, # (200MHz) off-chip ddr - ddr3 half clock o_CLKOUT3=unbuf_sdram_half_b, p_CLKOUT3_DUTY_CYCLE=.5, p_CLKOUT3_PHASE=210., p_CLKOUT3_DIVIDE=p // 4, # (100MHz) sys2x - 2x system clock o_CLKOUT4=unbuf_sys2x, p_CLKOUT4_DUTY_CYCLE=.5, p_CLKOUT4_PHASE=0., p_CLKOUT4_DIVIDE=p // 2, # ( 50MHz) periph / sys - system clock o_CLKOUT5=unbuf_sys, p_CLKOUT5_DUTY_CYCLE=.5, p_CLKOUT5_PHASE=0., p_CLKOUT5_DIVIDE=p // 1, ) # power on reset? reset = ~platform.request("cpu_reset") | self.reset self.clock_domains.cd_por = ClockDomain() por = Signal(max=1 << 11, reset=(1 << 11) - 1) self.sync.por += If(por != 0, por.eq(por - 1)) self.specials += AsyncResetSynchronizer(self.cd_por, reset) # System clock - 50MHz self.specials += Instance("BUFG", name="sys_bufg", i_I=unbuf_sys, o_O=self.cd_sys.clk) self.comb += self.cd_por.clk.eq(self.cd_sys.clk) self.specials += AsyncResetSynchronizer(self.cd_sys, ~pll_lckd | (por > 0)) # sys2x self.specials += Instance("BUFG", name="sys2x_bufg", i_I=unbuf_sys2x, o_O=self.cd_sys2x.clk) self.specials += AsyncResetSynchronizer(self.cd_sys2x, ~pll_lckd | (por > 0)) # SDRAM clocks # ------------------------------------------------------------------------------ self.clk8x_wr_strb = Signal() self.clk8x_rd_strb = Signal() # sdram_full self.specials += Instance("BUFPLL", name="sdram_full_bufpll", p_DIVIDE=4, i_PLLIN=unbuf_sdram_full, i_GCLK=self.cd_sys2x.clk, i_LOCKED=pll_lckd, o_IOCLK=self.cd_sdram_full_wr.clk, o_SERDESSTROBE=self.clk8x_wr_strb) self.comb += [ self.cd_sdram_full_rd.clk.eq(self.cd_sdram_full_wr.clk), self.clk8x_rd_strb.eq(self.clk8x_wr_strb), ] # sdram_half self.specials += Instance("BUFG", name="sdram_half_a_bufpll", i_I=unbuf_sdram_half_a, o_O=self.cd_sdram_half.clk) clk_sdram_half_shifted = Signal() self.specials += Instance("BUFG", name="sdram_half_b_bufpll", i_I=unbuf_sdram_half_b, o_O=clk_sdram_half_shifted) output_clk = Signal() clk = platform.request("ddram_clock") self.specials += Instance("ODDR2", p_DDR_ALIGNMENT="NONE", p_INIT=0, p_SRTYPE="SYNC", i_D0=1, i_D1=0, i_S=0, i_R=0, i_CE=1, i_C0=clk_sdram_half_shifted, i_C1=~clk_sdram_half_shifted, o_Q=output_clk) self.specials += Instance("OBUFDS", i_I=output_clk, o_O=clk.p, o_OB=clk.n) # Peripheral clock - 50MHz # ------------------------------------------------------------------------------ # The peripheral clock is kept separate from the system clock to allow # the system clock to be increased in the future. dcm_base50_locked = Signal() self.specials += [ Instance( "DCM_CLKGEN", name="crg_periph_dcm_clkgen", p_CLKIN_PERIOD=10.0, p_CLKFX_MULTIPLY=2, p_CLKFX_DIVIDE=4, p_CLKFX_MD_MAX=0.5, # CLKFX_MULTIPLY/CLKFX_DIVIDE p_CLKFXDV_DIVIDE=2, p_SPREAD_SPECTRUM="NONE", p_STARTUP_WAIT="FALSE", i_CLKIN=clk100a, o_CLKFX=self.cd_base50.clk, o_LOCKED=dcm_base50_locked, i_FREEZEDCM=0, i_RST=ResetSignal(), ), AsyncResetSynchronizer(self.cd_base50, self.cd_sys.rst | ~dcm_base50_locked) ] platform.add_period_constraint(self.cd_base50.clk, 20) # Encoder clock - 66 MHz # ------------------------------------------------------------------------------ self.specials += Instance("BUFG", name="encoder_bufg", i_I=unbuf_encoder, o_O=self.cd_encoder.clk) self.specials += AsyncResetSynchronizer(self.cd_encoder, self.cd_sys.rst)
def __init__(self, platform): self.clock_domains.cd_sys = ClockDomain() self.clock_domains.cd_eth = ClockDomain(reset_less=True) clk100 = platform.request("clk100") rst = platform.request("cpu_reset") pll_locked = Signal() pll_fb = Signal() pll_sys = Signal() pll_eth = Signal() self.specials += [ Instance( "PLLE2_BASE", p_STARTUP_WAIT="FALSE", o_LOCKED=pll_locked, # VCO @ 800 MHz p_REF_JITTER1=0.01, p_CLKIN1_PERIOD=10.0, p_CLKFBOUT_MULT=8, p_DIVCLK_DIVIDE=1, i_CLKIN1=clk100, i_CLKFBIN=pll_fb, o_CLKFBOUT=pll_fb, # 100 MHz p_CLKOUT0_DIVIDE=8, p_CLKOUT0_PHASE=0.0, o_CLKOUT0=pll_sys, # 25 MHz p_CLKOUT1_DIVIDE=32, p_CLKOUT1_PHASE=0.0, o_CLKOUT1=pll_eth, # 200 MHz p_CLKOUT2_DIVIDE=4, p_CLKOUT2_PHASE=0.0, #o_CLKOUT2=, # 200 MHz p_CLKOUT3_DIVIDE=4, p_CLKOUT3_PHASE=0.0, #o_CLKOUT3=, # 200MHz p_CLKOUT4_DIVIDE=4, p_CLKOUT4_PHASE=0.0, #o_CLKOUT4= ), Instance("BUFG", i_I=pll_sys, o_O=self.cd_sys.clk), Instance("BUFG", i_I=pll_eth, o_O=self.cd_eth.clk), AsyncResetSynchronizer(self.cd_sys, ~pll_locked | ~rst), ] self.specials += [ Instance("ODDR2", p_DDR_ALIGNMENT="NONE", p_INIT=0, p_SRTYPE="SYNC", i_D0=0, i_D1=1, i_S=0, i_R=0, i_CE=1, i_C0=self.cd_eth.clk, i_C1=~self.cd_eth.clk, o_Q=platform.request("eth_ref_clk")) ]