def __init__(self, clk_freq, rd_data): self.clk_freq = clk_freq self.rd_data = [0] + rd_data self.rd_idx = 0 # timings self.tRDInactive = self.ns(49) # RXF# inactive after RD# cycle self.tWRInactive = self.ns(49) # TXE# inactive after WR# cycle # pads self.data = Signal(8) self.rxf_n = Signal(reset=1) self.txe_n = Signal(reset=1) self.rd_n = Signal(reset=1) self.wr_n = Signal(reset=1) self.init = True self.wr_data = [] self.wait_wr_n = False self.rd_done = 0 self.data_w = Signal(8) self.data_r = Signal(8) self.specials += Tristate(self.data, self.data_r, ~self.rd_n, self.data_w) self.last_wr_n = 1 self.last_rd_n = 1 self.wr_delay = 0 self.rd_delay = 0
def __init__(self, rd_data): RandRun.__init__(self, 10) self.rd_data = [0] + rd_data self.rd_idx = 0 # pads self.data = Signal(8) self.rxf_n = Signal(reset=1) self.txe_n = Signal(reset=1) self.rd_n = Signal(reset=1) self.wr_n = Signal(reset=1) self.oe_n = Signal(reset=1) self.siwua = Signal() self.pwren_n = Signal(reset=1) self.init = True self.wr_data = [] self.wait_wr_n = False self.rd_done = 0 self.data_w = Signal(8) self.data_r = Signal(8) self.specials += Tristate(self.data, self.data_r, ~self.oe_n, self.data_w)
def __init__(self, pads): self._w = CSRStorage(3, name="w") self._r = CSRStatus(1, name="r") # # # data_w = Signal() data_oe = Signal() data_r = Signal() self.comb += [ pads.mdc.eq(self._w.storage[0]), data_oe.eq(self._w.storage[1]), data_w.eq(self._w.storage[2]) ] self.specials += [ MultiReg(data_r, self._r.status[0]), Tristate(pads.mdio, data_w, data_oe, data_r) ]
def __init__(self, pads, clk_freq, fifo_depth=32, read_time=128, write_time=128): dw = len(pads.data) # read fifo (FTDI --> SoC) read_fifo = ClockDomainsRenamer({ "write": "usb", "read": "sys" })(stream.AsyncFIFO(phy_description(8), fifo_depth)) read_buffer = ClockDomainsRenamer("usb")(stream.SyncFIFO( phy_description(8), 4)) self.comb += read_buffer.source.connect(read_fifo.sink) # write fifo (SoC --> FTDI) write_fifo = ClockDomainsRenamer({ "write": "sys", "read": "usb" })(stream.AsyncFIFO(phy_description(8), fifo_depth)) self.submodules += read_fifo, read_buffer, write_fifo # sink / source interfaces self.sink = write_fifo.sink self.source = read_fifo.source # read / write arbitration wants_write = Signal() wants_read = Signal() txe_n = Signal() rxf_n = Signal() self.comb += [ txe_n.eq(pads.txe_n), rxf_n.eq(pads.rxf_n), wants_write.eq(~txe_n & write_fifo.source.valid), wants_read.eq(~rxf_n & read_fifo.sink.ready), ] read_time_en, max_read_time = anti_starvation(self, read_time) write_time_en, max_write_time = anti_starvation(self, write_time) data_w_accepted = Signal(reset=1) fsm = FSM(reset_state="READ") self.submodules += ClockDomainsRenamer("usb")(fsm) fsm.act( "READ", read_time_en.eq(1), If(wants_write, If(~wants_read | max_read_time, NextState("RTW")))) fsm.act("RTW", NextState("WRITE")) fsm.act( "WRITE", write_time_en.eq(1), If(wants_read, If(~wants_write | max_write_time, NextState("WTR"))), write_fifo.source.ready.eq(wants_write & data_w_accepted)) fsm.act("WTR", NextState("READ")) # databus tristate data_w = Signal(dw) data_r = Signal(dw) data_oe = Signal() self.specials += Tristate(pads.data, data_w, data_oe, data_r) # read / write actions pads.oe_n.reset = 1 pads.rd_n.reset = 1 pads.wr_n.reset = 1 self.sync.usb += [ If(fsm.ongoing("READ"), data_oe.eq(0), pads.oe_n.eq(0), pads.rd_n.eq(~wants_read), pads.wr_n.eq(1)).Elif(fsm.ongoing("WRITE"), data_oe.eq(1), pads.oe_n.eq(1), pads.rd_n.eq(1), pads.wr_n.eq(~wants_write), data_w_accepted.eq(~txe_n)).Else( data_oe.eq(1), pads.oe_n.eq(~fsm.ongoing("WTR")), pads.rd_n.eq(1), pads.wr_n.eq(1)), read_buffer.sink.valid.eq(~pads.rd_n & ~rxf_n), read_buffer.sink.data.eq(data_r), If(~txe_n & data_w_accepted, data_w.eq(write_fifo.source.data)) ]
def __init__(self, pads, clk_freq, fifo_depth=32, read_time=128, write_time=128): dw = len(pads.data) self.clk_freq = clk_freq # timings tRD = self.ns(30) # RD# active pulse width (t4) tRDDataSetup = self.ns(14) # RD# to DATA (t3) tWRDataSetup = self.ns(5) # DATA to WR# active setup time (t8) tWR = self.ns(30) # WR# active pulse width (t10) tMultiReg = 2 # read fifo (FTDI --> SoC) read_fifo = stream.SyncFIFO(phy_description(8), fifo_depth) # write fifo (SoC --> FTDI) write_fifo = stream.SyncFIFO(phy_description(8), fifo_depth) self.submodules += read_fifo, write_fifo # sink / source interfaces self.sink = write_fifo.sink self.source = read_fifo.source # read / write arbitration wants_write = Signal() wants_read = Signal() txe_n = Signal() rxf_n = Signal() self.specials += [ MultiReg(pads.txe_n, txe_n), MultiReg(pads.rxf_n, rxf_n) ] self.comb += [ wants_write.eq(~txe_n & write_fifo.source.valid), wants_read.eq(~rxf_n & read_fifo.sink.ready), ] read_time_en, max_read_time = anti_starvation(self, read_time) write_time_en, max_write_time = anti_starvation(self, write_time) fsm = FSM(reset_state="READ") self.submodules += fsm read_done = Signal() write_done = Signal() commuting = Signal() fsm.act( "READ", read_time_en.eq(1), If( wants_write & read_done, If(~wants_read | max_read_time, commuting.eq(1), NextState("RTW")))) fsm.act("RTW", NextState("WRITE")) fsm.act( "WRITE", write_time_en.eq(1), If( wants_read & write_done, If(~wants_write | max_write_time, commuting.eq(1), NextState("WTR")))) fsm.act("WTR", NextState("READ")) # databus tristate data_w = Signal(dw) data_r_async = Signal(dw) data_r = Signal(dw) data_oe = Signal() self.specials += [ Tristate(pads.data, data_w, data_oe, data_r_async), MultiReg(data_r_async, data_r) ] # read actions pads.rd_n.reset = 1 read_fsm = FSM(reset_state="IDLE") self.submodules += read_fsm read_counter = Signal(8) read_counter_reset = Signal() read_counter_ce = Signal() self.sync += \ If(read_counter_reset, read_counter.eq(0) ).Elif(read_counter_ce, read_counter.eq(read_counter + 1) ) read_fsm.act( "IDLE", read_done.eq(1), read_counter_reset.eq(1), If( fsm.ongoing("READ") & wants_read, If(~commuting, NextState("PULSE_RD_N")))) read_fsm.act( "PULSE_RD_N", pads.rd_n.eq(0), read_counter_ce.eq(1), If(read_counter == max((tRD - 1), (tRDDataSetup + tMultiReg - 1)), NextState("ACQUIRE_DATA"))) read_fsm.act("ACQUIRE_DATA", read_fifo.sink.valid.eq(1), read_fifo.sink.data.eq(data_r), NextState("WAIT_RXF_N")) read_fsm.act("WAIT_RXF_N", If(rxf_n, NextState("IDLE"))) # write actions pads.wr_n.reset = 1 write_fsm = FSM(reset_state="IDLE") self.submodules += write_fsm write_counter = Signal(8) write_counter_reset = Signal() write_counter_ce = Signal() self.sync += \ If(write_counter_reset, write_counter.eq(0) ).Elif(write_counter_ce, write_counter.eq(write_counter + 1) ) write_fsm.act( "IDLE", write_done.eq(1), write_counter_reset.eq(1), If( fsm.ongoing("WRITE") & wants_write, If(~commuting, NextState("SET_DATA")))) write_fsm.act( "SET_DATA", data_oe.eq(1), data_w.eq(write_fifo.source.data), write_counter_ce.eq(1), If(write_counter == (tWRDataSetup - 1), write_counter_reset.eq(1), NextState("PULSE_WR_N"))) write_fsm.act("PULSE_WR_N", data_oe.eq(1), data_w.eq(write_fifo.source.data), pads.wr_n.eq(0), write_counter_ce.eq(1), If(write_counter == (tWR - 1), NextState("WAIT_TXE_N"))) write_fsm.act( "WAIT_TXE_N", If(txe_n, write_fifo.source.ready.eq(1), NextState("IDLE")))
def __init__(self, pads): addressbits = len(pads.a) bankbits = len(pads.ba) databits = len(pads.dq) self.settings = sdram_settings.PhySettings( memtype="SDR", dfi_databits=databits, nphases=1, rdphase=0, wrphase=0, rdcmdphase=0, wrcmdphase=0, cl=2, read_latency=4, write_latency=0 ) self.dfi = Interface(addressbits, bankbits, databits) ### # # Command/address # self.sync += [ pads.a.eq(self.dfi.p0.address), pads.ba.eq(self.dfi.p0.bank), pads.cke.eq(self.dfi.p0.cke), pads.cas_n.eq(self.dfi.p0.cas_n), pads.ras_n.eq(self.dfi.p0.ras_n), pads.we_n.eq(self.dfi.p0.we_n) ] if hasattr(pads, "cs_n"): self.sync += pads.cs_n.eq(self.dfi.p0.cs_n) # # DQ/DQS/DM data # sd_dq_out = Signal(databits) drive_dq = Signal() self.sync += sd_dq_out.eq(self.dfi.p0.wrdata) self.specials += Tristate(pads.dq, sd_dq_out, drive_dq) self.sync += \ If(self.dfi.p0.wrdata_en, pads.dm.eq(self.dfi.p0.wrdata_mask) ).Else( pads.dm.eq(0) ) sd_dq_in_ps = Signal(databits) self.sync.sys_ps += sd_dq_in_ps.eq(pads.dq) self.sync += self.dfi.p0.rddata.eq(sd_dq_in_ps) # # DQ/DM control # d_dfi_wrdata_en = Signal() self.sync += d_dfi_wrdata_en.eq(self.dfi.p0.wrdata_en) self.comb += drive_dq.eq(d_dfi_wrdata_en) rddata_sr = Signal(4) self.comb += self.dfi.p0.rddata_valid.eq(rddata_sr[3]) self.sync += rddata_sr.eq(Cat(self.dfi.p0.rddata_en, rddata_sr[:3]))
def __init__(self, pads, dw=32, timeout=1024): read_fifo = ClockDomainsRenamer({ "write": "usb", "read": "sys" })(stream.AsyncFIFO(phy_description(dw), 128)) write_fifo = ClockDomainsRenamer({ "write": "sys", "read": "usb" })(stream.AsyncFIFO(phy_description(dw), 128)) read_buffer = ClockDomainsRenamer("usb")(stream.SyncFIFO( phy_description(dw), 4)) self.comb += read_buffer.source.connect(read_fifo.sink) self.submodules += read_fifo self.submodules += read_buffer self.submodules += write_fifo self.read_buffer = read_buffer self.sink = write_fifo.sink self.source = read_fifo.source self.tdata_w = tdata_w = Signal(dw) self.data_r = data_r = Signal(dw) self.data_oe = data_oe = Signal() self.specials += Tristate(pads.data, tdata_w, data_oe, data_r) data_w = Signal(dw) _data_w = Signal(dw) self.sync.usb += [_data_w.eq(data_w)] for i in range(dw): self.specials += [ Instance("ODDR", p_DDR_CLK_EDGE="SAME_EDGE", i_C=ClockSignal("usb"), i_CE=1, i_S=0, i_R=0, i_D1=_data_w[i], i_D2=data_w[i], o_Q=tdata_w[i]) ] self.rd_n = rd_n = Signal() _rd_n = Signal(reset=1) self.wr_n = wr_n = Signal() _wr_n = Signal(reset=1) self.oe_n = oe_n = Signal() _oe_n = Signal(reset=1) self.sync.usb += [ _rd_n.eq(rd_n), _wr_n.eq(wr_n), _oe_n.eq(oe_n), ] self.specials += [ Instance("ODDR", p_DDR_CLK_EDGE="SAME_EDGE", i_C=ClockSignal("usb"), i_CE=1, i_S=0, i_R=0, i_D1=_rd_n, i_D2=rd_n, o_Q=pads.rd_n), Instance("ODDR", p_DDR_CLK_EDGE="SAME_EDGE", i_C=ClockSignal("usb"), i_CE=1, i_S=0, i_R=0, i_D1=_wr_n, i_D2=wr_n, o_Q=pads.wr_n), Instance("ODDR", p_DDR_CLK_EDGE="SAME_EDGE", i_C=ClockSignal("usb"), i_CE=1, i_S=0, i_R=0, i_D1=_oe_n, i_D2=oe_n, o_Q=pads.oe_n) ] self.comb += [ pads.rst.eq(~ResetSignal("usb")), pads.be.eq(0xf), pads.siwua.eq(1), data_oe.eq(oe_n), ] fsm = FSM() self.submodules.fsm = ClockDomainsRenamer("usb")(fsm) self.tempsendval = tempsendval = Signal(dw) self.temptosend = temptosend = Signal() self.tempreadval = tempreadval = Signal(dw) self.temptoread = temptoread = Signal() self.wants_read = wants_read = Signal() self.wants_write = wants_write = Signal() self.cnt_write = cnt_write = Signal(max=timeout + 1) self.cnt_read = cnt_read = Signal(max=timeout + 1) first_write = Signal() self.comb += [ wants_read.eq(~temptoread & ~pads.rxf_n), wants_write.eq((temptosend | write_fifo.source.valid) & (pads.txe_n == 0)), ] self.fsmstate = Signal(4) self.comb += [ self.fsmstate.eq( Cat(fsm.ongoing("IDLE"), fsm.ongoing("WRITE"), fsm.ongoing("RDWAIT"), fsm.ongoing("READ"))) ] self.sync.usb += [ If(~fsm.ongoing("READ"), If(temptoread, If(read_buffer.sink.ready, temptoread.eq(0)))) ] self.comb += [ If( ~fsm.ongoing("READ"), If( temptoread, read_buffer.sink.data.eq(tempreadval), read_buffer.sink.valid.eq(1), )) ] fsm.act( "IDLE", rd_n.eq(1), wr_n.eq(1), If( wants_write, oe_n.eq(1), NextValue(cnt_write, 0), NextValue(first_write, 1), NextState("WRITE"), ).Elif(wants_read, oe_n.eq(0), NextState("RDWAIT")).Else(oe_n.eq(1), )) fsm.act( "WRITE", If( wants_read, NextValue(cnt_write, cnt_write + 1), ), NextValue(first_write, 0), rd_n.eq(1), If( pads.txe_n, oe_n.eq(1), wr_n.eq(1), write_fifo.source.ready.eq(0), If(write_fifo.source.valid & ~first_write, NextValue(temptosend, 1)), NextState("IDLE")).Elif( temptosend, oe_n.eq(1), data_w.eq(tempsendval), wr_n.eq(0), NextValue(temptosend, 0)).Elif(cnt_write > timeout, oe_n.eq(0), NextState("RDWAIT")).Elif( write_fifo.source.valid, oe_n.eq(1), data_w.eq(write_fifo.source.data), write_fifo.source.ready.eq(1), NextValue(tempsendval, write_fifo.source.data), NextValue(temptosend, 0), wr_n.eq(0), ).Else(oe_n.eq(1), wr_n.eq(1), NextValue(temptosend, 0), NextState("IDLE"))) fsm.act("RDWAIT", rd_n.eq(0), oe_n.eq(0), wr_n.eq(1), NextValue(cnt_read, 0), NextState("READ")) fsm.act( "READ", If( wants_write, NextValue(cnt_read, cnt_read + 1), ), wr_n.eq(1), If( pads.rxf_n, oe_n.eq(0), rd_n.eq(1), NextState("IDLE"), ).Elif( cnt_read > timeout, NextValue(cnt_write, 0), NextValue(first_write, 1), NextState("WRITE"), oe_n.eq(1), ).Else( oe_n.eq(0), read_buffer.sink.valid.eq(1), read_buffer.sink.data.eq(data_r), NextValue(tempreadval, data_r), If(read_buffer.sink.ready, rd_n.eq(0)).Else(NextValue(temptoread, 1), NextState("IDLE"), rd_n.eq(1))))
def __init__(self, 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, pads, default=_default_edid): self._hpd_notif = CSRStatus() self._hpd_en = CSRStorage() mem_size = len(default) assert mem_size%128 == 0 self.specials.mem = Memory(8, mem_size, init=default) # # # # HPD if hasattr(pads, "hpd_notif"): self.specials += MultiReg(pads.hpd_notif, self._hpd_notif.status) else: self.comb += self._hpd_notif.status.eq(1) if hasattr(pads, "hpd_en"): self.comb += pads.hpd_en.eq(self._hpd_en.storage) # EDID scl_raw = Signal() sda_i = Signal() sda_raw = Signal() sda_drv = Signal() _sda_drv_reg = Signal() _sda_i_async = Signal() self.sync += _sda_drv_reg.eq(sda_drv) pad_scl = getattr(pads, "scl") if hasattr(pad_scl, "inverted"): self.specials += MultiReg(pads.scl, scl_raw) else: self.specials += MultiReg(~pads.scl, scl_raw) self.specials += [ Tristate(pads.sda, 0, _sda_drv_reg, _sda_i_async), MultiReg(_sda_i_async, sda_raw) ] # for debug self.scl = scl_raw self.sda_i = sda_i self.sda_o = Signal() self.comb += self.sda_o.eq(~_sda_drv_reg) self.sda_oe = _sda_drv_reg scl_i = Signal() samp_count = Signal(6) samp_carry = Signal() self.sync += [ Cat(samp_count, samp_carry).eq(samp_count + 1), If(samp_carry, scl_i.eq(scl_raw), sda_i.eq(sda_raw) ) ] scl_r = Signal() sda_r = Signal() scl_rising = Signal() sda_rising = Signal() sda_falling = Signal() self.sync += [ scl_r.eq(scl_i), sda_r.eq(sda_i) ] self.comb += [ scl_rising.eq(scl_i & ~scl_r), sda_rising.eq(sda_i & ~sda_r), sda_falling.eq(~sda_i & sda_r) ] start = Signal() self.comb += start.eq(scl_i & sda_falling) din = Signal(8) counter = Signal(max=9) self.sync += [ If(start, counter.eq(0)), If(scl_rising, If(counter == 8, counter.eq(0) ).Else( counter.eq(counter + 1), din.eq(Cat(sda_i, din[:7])) ) ) ] self.din = din self.counter = counter is_read = Signal() update_is_read = Signal() self.sync += If(update_is_read, is_read.eq(din[0])) offset_counter = Signal(max=mem_size) oc_load = Signal() oc_inc = Signal() self.sync += \ If(oc_load, offset_counter.eq(din) ).Elif(oc_inc, offset_counter.eq(offset_counter + 1) ) rdport = self.mem.get_port() self.specials += rdport self.comb += rdport.adr.eq(offset_counter) data_bit = Signal() zero_drv = Signal() data_drv = Signal() self.comb += \ If(zero_drv, sda_drv.eq(1) ).Elif(data_drv, sda_drv.eq(~data_bit) ) data_drv_en = Signal() data_drv_stop = Signal() self.sync += \ If(data_drv_en, data_drv.eq(1) ).Elif(data_drv_stop, data_drv.eq(0) ) self.sync += \ If(data_drv_en, chooser(rdport.dat_r, counter, data_bit, 8, reverse=True) ) self.submodules.fsm = fsm = FSM() fsm.act("WAIT_START") fsm.act("RCV_ADDRESS", If(counter == 8, If(din[1:] == 0x50, update_is_read.eq(1), NextState("ACK_ADDRESS0") ).Else( NextState("WAIT_START") ) ) ) fsm.act("ACK_ADDRESS0", If(~scl_i, NextState("ACK_ADDRESS1")) ) fsm.act("ACK_ADDRESS1", zero_drv.eq(1), If(scl_i, NextState("ACK_ADDRESS2")) ) fsm.act("ACK_ADDRESS2", zero_drv.eq(1), If(~scl_i, If(is_read, NextState("READ") ).Else( NextState("RCV_OFFSET") ) ) ) fsm.act("RCV_OFFSET", If(counter == 8, oc_load.eq(1), NextState("ACK_OFFSET0") ) ) fsm.act("ACK_OFFSET0", If(~scl_i, NextState("ACK_OFFSET1") ) ) fsm.act("ACK_OFFSET1", zero_drv.eq(1), If(scl_i, NextState("ACK_OFFSET2") ) ) fsm.act("ACK_OFFSET2", zero_drv.eq(1), If(~scl_i, NextState("RCV_ADDRESS") ) ) fsm.act("READ", If(~scl_i, If(counter == 8, data_drv_stop.eq(1), NextState("ACK_READ") ).Else( data_drv_en.eq(1) ) ) ) fsm.act("ACK_READ", If(scl_rising, oc_inc.eq(1), If(sda_i, NextState("WAIT_START") ).Else( NextState("READ") ) ) ) for state in fsm.actions.keys(): fsm.act(state, If(start, NextState("RCV_ADDRESS"))) if hasattr(pads, "hpd_en"): fsm.act(state, If(~self._hpd_en.storage, NextState("WAIT_START")))