def __init__(self, use_ext_clock=False): self.ibuf_disable = CSRStorage(reset=1) self.jreset = CSRStorage(reset=1) self.jref = Signal() self.refclk = Signal() self.clock_domains.cd_jesd = ClockDomain() self.refclk_pads = lvdsPair(Signal(name="refclk_p"), Signal(name="refclk_n")) refclk2 = Signal() # Useless for gtx transceivers self.specials += [ Instance("IBUFDS_GTE2", i_CEB=self.ibuf_disable.storage, i_I=self.refclk_pads.p, i_IB=self.refclk_pads.n, o_O=self.refclk, o_ODIV2=refclk2), AsyncResetSynchronizer(self.cd_jesd, self.jreset.storage), ] if use_ext_clock: self.comb += self.cd_jesd.clk.eq(ClockSignal("ext")) else: self.specials += Instance("BUFG", i_I=self.refclk, o_O=self.cd_jesd.clk)
def __init__(self, parent, offsets=None): table = "" if offsets is not None: arr = [["Image", "Offset"]] for i, offset in enumerate(offsets): arr.append([str(i), str(offset)]) table = "\nYou can use this block to reboot into one of these four addresses:\n\n" \ + lxsocdoc.rst.make_table(arr) self.intro = ModuleDoc("""FPGA Reboot Interface This module provides the ability to reboot the FPGA. It is based on the ``SB_WARMBOOT`` primitive built in to the FPGA. When power is applied to the FPGA, it reads configuration data from the onboard flash chip. This contains reboot offsets for four images. It then booted from the first image, but kept note of the other addresses. {}""".format(table)) self.ctrl = CSRStorage(fields=[ CSRField("image", size=2, description=""" Which image to reboot to. ``SB_WARMBOOT`` supports four images that are configured at FPGA startup. The bootloader is image 0, so set these bits to 0 to reboot back into the bootloader. """), CSRField("key", size=6, description=""" A reboot key used to prevent accidental reboots when writing to random areas of memory. To initiate a reboot, set this to ``0b101011``.""" ) ], description=""" Provides support for rebooting the FPGA. You can select which of the four images to reboot to, just be sure to OR the image number with ``0xac``. For example, to reboot to the bootloader (image 0), write ``0xac``` to this register.""" ) self.addr = CSRStorage(size=32, description=""" This sets the reset vector for the VexRiscv. This address will be used whenever the CPU is reset, for example through a debug bridge. You should update this address whenever you load a new program, to enable the debugger to run ``mon reset`` """) do_reset = Signal() self.comb += [ # "Reset Key" is 0xac (0b101011xx) do_reset.eq(self.ctrl.storage[2] & self.ctrl.storage[3] & ~self.ctrl.storage[4] & self.ctrl.storage[5] & ~self.ctrl.storage[6] & self.ctrl.storage[7]) ] self.specials += Instance( "SB_WARMBOOT", i_S0=self.ctrl.storage[0], i_S1=self.ctrl.storage[1], i_BOOT=do_reset, ) parent.config["BITSTREAM_SYNC_HEADER1"] = 0x7e99aa7e parent.config["BITSTREAM_SYNC_HEADER2"] = 0x7eaa997e
def __init__(self, platform): clk12 = platform.request("clk12") self.clock_domains.cd_por = ClockDomain(reset_less=True) self.clock_domains.cd_sys = ClockDomain() reset_delay = Signal(max=1024) self.comb += [ self.cd_por.clk.eq(clk12), self.cd_sys.clk.eq(clk12), self.cd_sys.rst.eq(reset_delay != 1023) ] self.sync.por += \ If(reset_delay != 1023, reset_delay.eq(reset_delay + 1) ) self.submodules.dec = SyncDecoder(8, 3 * 7) self.comb += [ self.dec.data.eq(platform.request("din")), self.dec.wck.eq(platform.request("wck")), self.dec.bck.eq(platform.request("bck")), ] self.submodules.packager = Packager(0x47) serial = platform.request("fast_serial") self.submodules.tx = FastSerialTX(serial) self.comb += self.tx.sink.payload.port.eq(1) self.comb += [ self.dec.source.connect(self.packager.sink), self.packager.source.connect(self.tx.sink), ] # 96.000 MHz pll and /10 for mclk self.mclk = platform.request("mclk") pll_out = Signal() self.specials.pll = Instance("pll", i_clock_in=ClockSignal("sys"), o_clock_out=pll_out) self.clock_domains.cd_pll = ClockDomain(reset_less=True) self.comb += self.cd_pll.clk.eq(pll_out) self.counter = Signal(max=5) self.sync.pll += [ If(self.counter >= 4, self.counter.eq(0), self.mclk.eq(~self.mclk), ).Else( self.counter.eq(self.counter + 1), ) ]
def _dac_settings(self, platform): dac = platform.request("dac") dac_dat_a = Signal(bits, reset=0) dac_dat_b = Signal(bits, reset=0) dac_rst = Signal() # convert output registers + signed to unsigned and to negative slope self.sync += [ dac_dat_a.eq(Cat(~self.out1[:-1], self.out1[-1])), dac_dat_b.eq(Cat(~self.out2[:-1], self.out2[-1])), ] self.specials += [ Instance("ODDR", o_Q=dac.clk, i_D1=0, i_D2=1, i_C=ClockSignal("clk_dac_2p"), i_CE=1, i_R=0, i_S=0), Instance("ODDR", o_Q=dac.wrt, i_D1=0, i_D2=1, i_C=ClockSignal("clk_dac_2x"), i_CE=1, i_R=0, i_S=0), Instance("ODDR", o_Q=dac.sel, i_D1=1, i_D2=0, i_C=ClockSignal("clk_dac_1p"), i_CE=1, i_R=dac_rst, i_S=0), Instance("ODDR", o_Q=dac.rst, i_D1=dac_rst, i_D2=dac_rst, i_C=ClockSignal("clk_dac_1p"), i_CE=1, i_R=0, i_S=0), ] self.specials += [ Instance("ODDR", o_Q=dac.data[i], i_D1=dac_dat_b[i], i_D2=dac_dat_a[i], i_C=ClockSignal("clk_dac_1p"), i_CE=1, i_R=dac_rst, i_S=0) for i in range(len(dac.data)) ]
def __init__(self, platform, sys_clk_freq): self.clock_domains.cd_sys = ClockDomain() # # # self.cd_sys.clk.attr.add("keep") self.submodules.pll = pll = S7PLL(speedgrade=-1) self.comb += pll.reset.eq(~platform.request("cpu_reset")) pll_clkin = Signal() pll.register_clkin(pll_clkin, 100e6) pll.create_clkout(self.cd_sys, sys_clk_freq) self.specials += Instance("BUFG", i_I=platform.request("clk100"), o_O=pll_clkin)
def __init__(self): self.ctrl = CSRStorage(size=8) self.addr = CSRStorage(size=32) do_reset = Signal() self.comb += [ # "Reset Key" is 0xac (0b101011xx) do_reset.eq(self.ctrl.storage[2] & self.ctrl.storage[3] & ~self.ctrl.storage[4] & self.ctrl.storage[5] & ~self.ctrl.storage[6] & self.ctrl.storage[7]) ] self.specials += Instance( "SB_WARMBOOT", i_S0=self.ctrl.storage[0], i_S1=self.ctrl.storage[1], i_BOOT=do_reset, )
def __init__(self, platform): serial = platform.request("fast_serial") clk12 = platform.request("clk12") self.clock_domains.cd_sys = ClockDomain() if True: self.specials.pll = Instance("pll_test", i_clock_in=clk12, o_clock_out=self.cd_sys.clk) else: self.comb += self.cd_sys.clk.eq(clk12) self.clock_domains.cd_por = ClockDomain(reset_less=True) reset_delay = Signal(max=1024) self.comb += [ self.cd_por.clk.eq(self.cd_sys.clk), self.cd_sys.rst.eq(reset_delay != 1023) ] self.sync.por += If(reset_delay != 1023, reset_delay.eq(reset_delay + 1)) self.submodules.tx = FastSerialTX(serial) self.submodules.packager = Packager(0x47) self.comb += self.packager.source.connect(self.tx.sink) self.comb += self.tx.sink.payload.port.eq(1) counter = Signal(5) self.comb += [ self.packager.sink.stb.eq(1), self.packager.sink.payload.data.eq(counter), self.packager.sink.eop.eq(counter == 2**counter.nbits - 1) ] self.sync += [ If(self.packager.sink.stb & self.packager.sink.ack, counter.eq(counter + 1)), ] debug = platform.request("debug") self.comb += [ debug.eq(Cat(serial.clk, serial.di, serial.cts)), ]
def ts_buf(pad, sig_o, sig_i, en_out): # diff. IO. # sig_o: output from FPGA # sig_i: intput to FPGA # en_out: enable FPGA output driver self.specials += Instance( "IOBUFDS_INTERMDISABLE", p_DIFF_TERM="TRUE", p_IBUF_LOW_PWR="TRUE", p_USE_IBUFDISABLE="TRUE", i_IBUFDISABLE=en_out, i_INTERMDISABLE=en_out, i_I=sig_o, o_O=sig_i, i_T=~en_out, io_IO=pad.p, io_IOB=pad.n, )
def __init__(self, parent): self.ctrl = CSRStorage(size=8) self.addr = CSRStorage(size=32) do_reset = Signal() self.comb += [ # "Reset Key" is 0xac (0b101011xx) do_reset.eq(self.ctrl.storage[2] & self.ctrl.storage[3] & ~self.ctrl.storage[4] & self.ctrl.storage[5] & ~self.ctrl.storage[6] & self.ctrl.storage[7]) ] self.specials += Instance( "SB_WARMBOOT", i_S0=self.ctrl.storage[0], i_S1=self.ctrl.storage[1], i_BOOT=do_reset, ) parent.config["BITSTREAM_SYNC_HEADER1"] = 0x7e99aa7e parent.config["BITSTREAM_SYNC_HEADER2"] = 0x7eaa997e
def __init__(self, platform, sys_clk_freq): 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_eth = ClockDomain() # # # pll_clkin = Signal() self.specials += Instance("BUFG", i_I=platform.request("clk100"), o_O=pll_clkin) self.submodules.pll = pll = S7PLL(speedgrade=-1) self.comb += pll.reset.eq(~platform.request("cpu_reset")) pll.register_clkin(pll_clkin, 100e6) pll.create_clkout(self.cd_sys, sys_clk_freq) pll.create_clkout(self.cd_sys4x, 4 * sys_clk_freq) pll.create_clkout(self.cd_sys4x_dqs, 4 * sys_clk_freq, phase=90) pll.create_clkout(self.cd_clk200, 200e6) self.submodules.idelayctrl = S7IDELAYCTRL(self.cd_clk200)
def __init__(self, cd_sys, platform, dw=64): self._reset = CSRStorage(reset=0) self._pcs_status = CSRStatus(fields=[ CSRField("pcs_fault", size=1, offset=1), CSRField("pcs_fault_rx", size=1, offset=2), CSRField("pcs_fault_tx", size=1, offset=3), ]) self._pcs_config = CSRStorage(reset=0, fields=[ CSRField("pcs_clear", size=1, offset=0, pulse=True), ]) self.clock_domains.cd_clkmgt = ClockDomain() self.tx_data = Signal(dw) self.tx_ctl = Signal(dw//8) self.rx_data = Signal(dw) self.rx_ctl = Signal(dw//8) self.pma_status = Signal(448) _pma_status = Signal(448) txusrclk = Signal() txusrclk2 = Signal() drp_req = Signal() drp_daddr_o = Signal(16) drp_den_o = Signal() drp_di_o = Signal(16) drp_dwe_o = Signal() drp_drpdo_i = Signal(16) drp_drdy_i = Signal() drp_den_i = Signal() refclk_pads = platform.request("user_sma_mgt_refclk") rx_pads = platform.request("sfp_rx") tx_pads = platform.request("sfp_tx") self.tx_disable = Signal() self.qplllock = Signal() self.gtrxreset = Signal() self.gttxreset = Signal() self.txusrrdy = Signal() self.coreclk = Signal() self.comb += [ platform.request("sfp_tx_disable_n").eq(~self.tx_disable), ] self.pcs_clear = pcs_clear = Signal() config_vector = Signal(536, reset=0) self.submodules.ps = PulseSynchronizer("sys", "clkmgt") self.pma_multi = pma_multi = Signal(3) self.specials += MultiReg(Cat(self.pma_status[250:252], self.pma_status[231]), pma_multi) self.comb += [ self.ps.i.eq(self._pcs_config.fields.pcs_clear), pcs_clear.eq(self.ps.o), self._pcs_status.fields.pcs_fault_rx.eq(pma_multi[0]), self._pcs_status.fields.pcs_fault_tx.eq(pma_multi[1]), self._pcs_status.fields.pcs_fault.eq(pma_multi[2]) ] self.comb += [ ClockSignal("clkmgt").eq(self.coreclk) ] self.sync.clkmgt += [ config_vector[517].eq(pcs_clear), self.pma_status.eq(_pma_status) ] self.specials += Instance( "ten_gig_eth_pcs_pma_0", i_refclk_p=refclk_pads.p, i_refclk_n=refclk_pads.n, i_reset=self._reset.storage, # o_resetdone_out= o_coreclk_out=self.coreclk, # rxrecclkout_0=rxrecclkout_0, # What is i_rxp=rx_pads.p, i_rxn=rx_pads.n, o_txp=tx_pads.p, o_txn=tx_pads.n, i_dclk=cd_sys.clk, i_sim_speedup_control=0, o_txusrclk_out=txusrclk, o_txusrclk2_out=txusrclk2, # UltraScale only #o_areset_datapathclk_out= o_qplllock_out=self.qplllock, o_txuserrdy_out=self.txusrrdy, #o_reset_counter_done=, # UltraScale only o_gttxreset_out=self.gttxreset, o_gtrxreset_out=self.gtrxreset, # TODO Set it to 5 seconds? o_xgmii_rxd=self.rx_data, o_xgmii_rxc=self.rx_ctl, i_xgmii_txd=self.tx_data, i_xgmii_txc=self.tx_ctl, i_configuration_vector=config_vector, o_status_vector=_pma_status, # o_core_status=, # tx_resetdone=, # rx_resetdone=, # Connects to sfp+ i_signal_detect=1, i_tx_fault=0, # Unused inside the core o_tx_disable=self.tx_disable, i_pma_pmd_type=0b111, # DRP Stuff o_drp_req=drp_req, i_drp_gnt=drp_req, o_drp_daddr_o=drp_daddr_o, o_drp_den_o=drp_den_o, o_drp_di_o=drp_di_o, o_drp_dwe_o=drp_dwe_o, i_drp_drpdo_i=drp_drpdo_i, i_drp_drdy_i=drp_drdy_i, i_drp_daddr_i=drp_daddr_o, i_drp_den_i=drp_den_o, i_drp_di_i=drp_di_o, i_drp_dwe_i=drp_dwe_o, o_drp_drpdo_o=drp_drpdo_i, o_drp_drdy_o=drp_drdy_i, ) class Pads: rx = ClockSignal("clkmgt") rx_ctl = self.rx_ctl rx_data = self.rx_data tx = ClockSignal("clkmgt") tx_ctl = self.tx_ctl tx_data = self.tx_data self.pads = Pads()
def __init__(self, pads): def io_bus(n): return Record([("oe", 1), ("i", n), ("o", n)]) # # # self.clk_enable = Signal() self.cs = Signal() self.dq = io_bus(32) self.rwds = io_bus(4) ## IO Delay shifting self.dly_io = delayf_pins() self.dly_clk = delayf_pins() dq = self.add_tristate( pads.dq) if not hasattr(pads.dq, "oe") else pads.dq rwds = self.add_tristate( pads.rwds) if not hasattr(pads.rwds, "oe") else pads.rwds # Shift non DDR signals to match the FF's inside DDR modules. self.specials += MultiReg(self.cs, pads.cs_n, n=3) self.specials += MultiReg(self.rwds.oe, rwds.oe, n=3) self.specials += MultiReg(self.dq.oe, dq.oe, n=3) # mask off clock when no CS clk_en = Signal() self.comb += clk_en.eq(self.clk_enable & ~self.cs) #clk_out clkp = Signal() clkn = Signal() self.specials += [ Instance("ODDRX2F", i_D3=clk_en, i_D2=0, i_D1=clk_en, i_D0=0, i_SCLK=ClockSignal("hr_90"), i_ECLK=ClockSignal("hr2x_90"), i_RST=ResetSignal("hr"), o_Q=clkp), Instance( "DELAYF", p_DEL_MODE="USER_DEFINED", p_DEL_VALUE=0, # (25ps per tap) i_A=clkp, i_LOADN=self.dly_clk.loadn, i_MOVE=self.dly_clk.move, i_DIRECTION=self.dly_clk.direction, o_Z=pads.clk_p) ] self.specials += [ Instance("ODDRX2F", i_D3=~clk_en, i_D2=1, i_D1=~clk_en, i_D0=1, i_SCLK=ClockSignal("hr_90"), i_ECLK=ClockSignal("hr2x_90"), i_RST=ResetSignal("hr"), o_Q=clkn), Instance( "DELAYF", p_DEL_MODE="USER_DEFINED", p_DEL_VALUE=0, # (25ps per tap) i_A=clkn, i_LOADN=self.dly_clk.loadn, i_MOVE=self.dly_clk.move, i_DIRECTION=self.dly_clk.direction, o_Z=pads.clk_n) ] # DQ_out for i in range(8): self.specials += [ Instance("ODDRX2F", i_D3=self.dq.o[i], i_D2=self.dq.o[8 + i], i_D1=self.dq.o[16 + i], i_D0=self.dq.o[24 + i], i_SCLK=ClockSignal("hr"), i_ECLK=ClockSignal("hr2x"), i_RST=ResetSignal("hr"), o_Q=dq.o[i]) ] # DQ_in for i in range(8): dq_in = Signal() self.specials += [ Instance("IDDRX2F", i_D=dq_in, i_SCLK=ClockSignal("hr"), i_ECLK=ClockSignal("hr2x"), i_RST=ResetSignal("hr"), o_Q3=self.dq.i[i], o_Q2=self.dq.i[i + 8], o_Q1=self.dq.i[i + 16], o_Q0=self.dq.i[i + 24]), Instance( "DELAYF", p_DEL_MODE="USER_DEFINED", p_DEL_VALUE=0, # (25ps per tap) i_A=dq.i[i], i_LOADN=self.dly_io.loadn, i_MOVE=self.dly_io.move, i_DIRECTION=self.dly_io.direction, o_Z=dq_in) ] # RWDS_out self.specials += [ Instance("ODDRX2F", i_D3=self.rwds.o[0], i_D2=self.rwds.o[1], i_D1=self.rwds.o[2], i_D0=self.rwds.o[3], i_SCLK=ClockSignal("hr"), i_ECLK=ClockSignal("hr2x"), i_RST=ResetSignal("hr"), o_Q=rwds.o) ] # RWDS_in rwds_in = Signal() self.specials += [ Instance("IDDRX2F", i_D=rwds_in, i_SCLK=ClockSignal("hr"), i_ECLK=ClockSignal("hr2x"), i_RST=ResetSignal("hr"), o_Q3=self.rwds.i[0], o_Q2=self.rwds.i[1], o_Q1=self.rwds.i[2], o_Q0=self.rwds.i[3]), Instance( "DELAYF", p_DEL_MODE="USER_DEFINED", p_DEL_VALUE=0, # (25ps per tap) i_A=rwds.i, i_LOADN=self.dly_io.loadn, i_MOVE=self.dly_io.move, i_DIRECTION=self.dly_io.direction, o_Z=rwds_in) ]
def __init__(self, platform, output_dir="build", **kwargs): kwargs['cpu_reset_address'] = 0x0 kwargs['integrated_rom_size'] = 0x000c000 kwargs['integrated_sram_size'] = 0x0004000 kwargs['integrated_main_ram_size'] = 0x0400 kwargs['with_uart'] = True self.output_dir = output_dir clk_freq = int(48e6) self.submodules.crg = _CRG(platform) SoCCore.__init__(self, platform, clk_freq, **kwargs) # Modify stack address for FW self.cpu.cpu_params.update(p_STACKADDR=0x00000400) usb_pads = platform.request("usb") # USB IP core bus interface (wb[4] in riscv project) self.wb_ub = wishbone.Interface() self.add_memory_region("ipcore_bus_if", self.mem_map["ipcore_bus_if"], 1 << 16, "io") self.add_wb_slave(self.mem_map["ipcore_bus_if"], self.wb_ub, 1 << 16) # USB IP core Endpoint interface (wb[5] in riscv project) self.wb_ep = wishbone.Interface() self.add_memory_region("ipcore_ep_if", self.mem_map["ipcore_ep_if"], 1 << 16, "io") self.add_wb_slave(self.mem_map["ipcore_ep_if"], self.wb_ep, 1 << 16) # USB Core # EP Buffer ep_tx_addr_0 = Signal(9) ep_tx_data_0 = Signal(32) ep_tx_we_0 = Signal() ep_rx_addr_0 = Signal(9) ep_rx_data_1 = Signal(32) ep_rx_re_0 = Signal() ep_tx_addr_0 = self.wb_ep.adr ep_tx_data_0 = self.wb_ep.dat_w ep_tx_we_0 = self.wb_ep.we & ~self.wb_ep.ack & self.wb_ep.cyc ep_rx_addr_0 = self.wb_ep.adr self.comb += If( self.wb_ep.cyc == 1, # then self.wb_ep.dat_r.eq(ep_rx_data_1) ).Else( self.wb_ep.eq(0) ) ep_rx_re_0 = 1 # Automatic ACK with 1 cycle delay ack_tmp = Signal() self.sync.sys += ack_tmp.eq(self.wb_ep.cyc & ~self.wb_ep.ack) self.wb_ep.ack = ack_tmp # Bus interface ub_addr = Signal(12) ub_wdata = Signal(16) ub_rdata = Signal(16) ub_cyc = Signal() ub_we = Signal() ub_ack = Signal() ub_addr = self.wb_ub.adr ub_wdata = self.wb_ub.dat_w ub_rdata = self.wb_ub.dat_r ub_cyc = self.wb_ub.cyc ub_we = self.wb_ub.we ub_ack = self.wb_ub.ack # Core platform.add_source("../ice40-playground/cores/usb/rtl/usb.v") self.specials += Instance("usb", p_EPDW=32, # Pads io_pad_dp=usb_pads.d_p, io_pad_dn=usb_pads.d_n, o_pad_pu=usb_pads.pullup, # EP buffer interface i_ep_tx_addr_0=ep_tx_addr_0, i_ep_tx_data_0=ep_tx_data_0, i_ep_tx_we_0=ep_tx_we_0, i_ep_rx_addr_0=ep_rx_addr_0, o_ep_rx_data_1=ep_rx_data_1, i_ep_rx_re_0=ep_rx_re_0, i_ep_clk=self.crg.cd_sys.clk, # Bus interface i_bus_addr=ub_addr, i_bus_din=ub_wdata, o_bus_dout=ub_rdata, i_bus_cyc=ub_cyc, i_bus_we=ub_we, o_bus_ack=ub_ack, # IRQ # output wire irq, # SOF indication # output wire sof, # Common i_clk=self.crg.cd_sys.clk, i_rst=self.crg.cd_sys.rst )
def __logic__(self, platform): # signals for external connectivity clk_adc_pins = platform.request("clk125") platform.add_platform_command( "create_clock -name clk_adc -period 8 [get_ports {port}]", port=clk_adc_pins.p) # xdc 208 clk_adc_unbuffered = Signal() clk_adc_buffered = Signal() self.specials += Instance("IBUFGDS", i_I=clk_adc_pins.p, i_IB=clk_adc_pins.n, o_O=clk_adc_unbuffered) self.specials += Instance("BUFG", i_I=clk_adc_unbuffered, o_O=clk_adc_buffered) clk_feedback = Signal() clk_feedback_buffered = Signal() self.specials += Instance("BUFG", i_I=clk_feedback, o_O=clk_feedback_buffered) clk_adc = Signal() clk_dac_1p = Signal() clk_dac_2x = Signal() clk_dac_2p = Signal() clk_ser = Signal() clk_pwm = Signal() reset = Signal(reset=1) self.specials += [ Instance( "PLLE2_ADV", p_BANDWIDTH="OPTIMIZED", p_COMPENSATION="ZHOLD", p_DIVCLK_DIVIDE=1, p_CLKIN1_PERIOD=8.000, p_REF_JITTER1=0.010, i_RST=~reset, i_CLKIN1= clk_adc_unbuffered, # top.v 314 uses unbuffered version i_CLKIN2=0, i_CLKINSEL=1, i_PWRDWN=0, p_CLKFBOUT_MULT=8, p_CLKFBOUT_PHASE=0.0, o_CLKFBOUT=clk_feedback, i_CLKFBIN=clk_feedback_buffered, o_LOCKED=self.locked, # dynamic reconfiguration settings, all disabled i_DADDR=0, i_DCLK=0, i_DEN=0, i_DI=0, i_DWE=0, # o_DO=, # o_DRDY=, p_CLKOUT0_DIVIDE=8, # 125 MHz p_CLKOUT0_PHASE=0.0, p_CLKOUT0_DUTY_CYCLE=0.5, o_CLKOUT0=clk_adc, p_CLKOUT1_DIVIDE=8, # 125 MHz p_CLKOUT1_PHASE=0.000, p_CLKOUT1_DUTY_CYCLE=0.5, o_CLKOUT1=clk_dac_1p, p_CLKOUT2_DIVIDE=4, # 250 MHz p_CLKOUT2_PHASE=0.000, p_CLKOUT2_DUTY_CYCLE=0.5, o_CLKOUT2=clk_dac_2x, p_CLKOUT3_DIVIDE=4, # 250 MHz, 45 degree advanced p_CLKOUT3_PHASE=-45.000, p_CLKOUT3_DUTY_CYCLE=0.5, o_CLKOUT3=clk_dac_2p, p_CLKOUT4_DIVIDE=4, # 250 MHz p_CLKOUT4_PHASE=0.000, p_CLKOUT4_DUTY_CYCLE=0.5, o_CLKOUT4=clk_ser, p_CLKOUT5_DIVIDE=4, # 250 MHz p_CLKOUT5_PHASE=0.000, p_CLKOUT5_DUTY_CYCLE=0.5, o_CLKOUT5=clk_pwm, ) ] self.clock_domains.sys_ps = ClockDomain() self.clock_domains.clk_adc = ClockDomain() self.clock_domains.clk_dac_1p = ClockDomain(reset_less=True) self.clock_domains.clk_dac_2x = ClockDomain(reset_less=True) self.clock_domains.clk_dac_2p = ClockDomain(reset_less=True) self.clock_domains.clk_ser = ClockDomain(reset_less=True) self.clock_domains.clk_pwm = ClockDomain(reset_less=True) self.specials += Instance("BUFG", i_I=clk_adc, o_O=self.clk_adc.clk) self.specials += Instance("BUFG", i_I=clk_dac_1p, o_O=self.clk_dac_1p.clk) self.specials += Instance("BUFG", i_I=clk_dac_2x, o_O=self.clk_dac_2x.clk) self.specials += Instance("BUFG", i_I=clk_dac_2p, o_O=self.clk_dac_2p.clk) self.specials += Instance("BUFG", i_I=clk_ser, o_O=self.clk_ser.clk) self.specials += Instance("BUFG", i_I=clk_pwm, o_O=self.clk_pwm.clk) self.specials += Instance( "FD", p_INIT=1, i_D=~self.locked, i_C=self.clk_adc.clk, o_Q=self.clk_adc.rst, )
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_clk50 = ClockDomain() clk100 = platform.request("clk100") rst = ~platform.request("cpu_reset") pll_locked = Signal() pll_fb = Signal() self.pll_sys = Signal() pll_sys4x = Signal() pll_sys4x_dqs = Signal() pll_clk200 = Signal() pll_clk50 = 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=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, # 50MHz p_CLKOUT4_DIVIDE=32, p_CLKOUT4_PHASE=0.0, o_CLKOUT4=pll_clk50), Instance("BUFG", i_I=self.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), Instance("BUFG", i_I=pll_clk50, o_O=self.cd_clk50.clk), AsyncResetSynchronizer(self.cd_sys, ~pll_locked | rst), AsyncResetSynchronizer(self.cd_clk200, ~pll_locked | rst), AsyncResetSynchronizer(self.cd_clk50, ~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) # For Arty, this is required in order to get a clock generated. Otherwise, # there will be no carrier. if platform.device[:4] == "xc7a": eth_clk = Signal() self.specials += [ Instance("BUFR", p_BUFR_DIVIDE="4", i_CE=1, i_CLR=0, i_I=clk100, o_O=eth_clk), Instance("BUFG", i_I=eth_clk, o_O=platform.request("eth_ref_clk")), ]
def __init__(self, pads, detected_pulse): rgba_pwm = Signal(3) self.dat = CSRStorage(8) self.addr = CSRStorage(4) self.ctrl = CSRStorage(4) self.bypass = CSRStorage(3) self.pulse = CSRStorage(24) self.duty = CSRStorage(24) self.sent_pulses = CSRStatus(32) self.detected_pulses = CSRStatus(32) count = Signal(24) led_value = Signal() rgb = Signal(3) sent_pulses = Signal(32) detected_pulses = Signal(32) rgba_drv = Signal(3) last_detected_val = Signal() self.sync += [ If( last_detected_val != detected_pulse, detected_pulses.eq(detected_pulses + 1), ), last_detected_val.eq(detected_pulse), # When the PWM count is updated, reset everything and # copy the results out. If( self.pulse.re, count.eq(0), self.sent_pulses.status.eq(sent_pulses), sent_pulses.eq(0), self.detected_pulses.status.eq(detected_pulses), detected_pulses.eq(0), led_value.eq(0), ).Elif( count < self.pulse.storage, count.eq(count + 1), If( count < self.duty.storage, led_value.eq(0), ).Elif( count == self.duty.storage, led_value.eq(1), sent_pulses.eq(sent_pulses + 1), ).Else(led_value.eq(1), ), ).Else( # Reset the count once it gets greater than "Pulse" count.eq(0), led_value.eq(0), ), ] # last_led_value = Signal() # self.sync += [ # last_led_value.eq(led_value), # # When the PWM count is updated, reset everything and # # copy the results out. # If(self.pulse.re, # count.eq(0), # self.sent_pulses.status.eq(sent_pulses), # sent_pulses.eq(0), # self.detected_pulses.status.eq(detected_pulses), # detected_pulses.eq(0), # led_value.eq(0), # ).Elif(count < self.pulse.storage, # count.eq(count + 1), # If(count < self.duty.storage, # led_value.eq(0), # ).Else( # led_value.eq(1), # # On the transition from 0 > 1, increment the counter # # and see if the LED has changed. If so, increment # # the number of detected pulses. # If(~last_led_value, # sent_pulses.eq(sent_pulses + 1), # If(detected_pulse, # detected_pulses.eq(detected_pulses + 1), # ), # ), # ), # ).Else( # # Reset the count once it gets greater than "Pulse" # count.eq(0), # led_value.eq(0), # ), # ] # Wire up the bypasses self.comb += [ If( self.bypass.storage[0], rgb[0].eq(led_value), ).Else(rgb[0].eq(rgba_pwm[0]), ), If( self.bypass.storage[1], rgb[1].eq(led_value), ).Else(rgb[1].eq(rgba_pwm[1]), ), If( self.bypass.storage[2], rgb[2].eq(led_value), ).Else(rgb[2].eq(rgba_pwm[2]), ), ] # Drive the red LED at 12 mA, since the sensor isn't # very sensitive to red. # NOTE: This is over the 10 mA current limit of the LED, # however we're pulsing it at 10% duty cycle, at which # point the LED can handle up to 48 mA. self.specials += Instance( "SB_RGBA_DRV", i_CURREN=self.ctrl.storage[1], i_RGBLEDEN=self.ctrl.storage[2], i_RGB0PWM=rgb[0], i_RGB1PWM=rgb[1], i_RGB2PWM=rgb[2], o_RGB0=pads.rgb0, o_RGB1=pads.rgb1, o_RGB2=pads.rgb2, p_CURRENT_MODE="0b1", # Half current p_RGB0_CURRENT="0b000011", # 4 mA p_RGB1_CURRENT="0b111111", # 12 mA p_RGB2_CURRENT="0b000011", # 4 mA ) self.specials += Instance( "SB_LEDDA_IP", i_LEDDCS=self.dat.re, i_LEDDCLK=ClockSignal(), i_LEDDDAT7=self.dat.storage[7], i_LEDDDAT6=self.dat.storage[6], i_LEDDDAT5=self.dat.storage[5], i_LEDDDAT4=self.dat.storage[4], i_LEDDDAT3=self.dat.storage[3], i_LEDDDAT2=self.dat.storage[2], i_LEDDDAT1=self.dat.storage[1], i_LEDDDAT0=self.dat.storage[0], i_LEDDADDR3=self.addr.storage[3], i_LEDDADDR2=self.addr.storage[2], i_LEDDADDR1=self.addr.storage[1], i_LEDDADDR0=self.addr.storage[0], i_LEDDDEN=self.dat.re, i_LEDDEXE=self.ctrl.storage[0], # i_LEDDRST = ResetSignal(), # This port doesn't actually exist o_PWMOUT0=rgba_pwm[0], o_PWMOUT1=rgba_pwm[1], o_PWMOUT2=rgba_pwm[2], o_LEDDON=Signal(), )
def __init__(self, revision, pads): rgba_pwm = Signal(3) self.dat = CSRStorage(8) self.addr = CSRStorage(4) self.ctrl = CSRStorage(6) self.raw = CSRStorage(3) ledd_value = Signal(3) if revision == "pvt" or revision == "evt" or revision == "dvt": self.comb += [ If(self.ctrl.storage[3], rgba_pwm[1].eq( self.raw.storage[0])).Else(rgba_pwm[1].eq(ledd_value[0])), If(self.ctrl.storage[4], rgba_pwm[0].eq( self.raw.storage[1])).Else(rgba_pwm[0].eq(ledd_value[1])), If(self.ctrl.storage[5], rgba_pwm[2].eq( self.raw.storage[2])).Else(rgba_pwm[2].eq(ledd_value[2])), ] elif revision == "hacker": self.comb += [ If(self.ctrl.storage[3], rgba_pwm[2].eq( self.raw.storage[0])).Else(rgba_pwm[2].eq(ledd_value[0])), If(self.ctrl.storage[4], rgba_pwm[1].eq( self.raw.storage[1])).Else(rgba_pwm[1].eq(ledd_value[1])), If(self.ctrl.storage[5], rgba_pwm[0].eq( self.raw.storage[2])).Else(rgba_pwm[0].eq(ledd_value[2])), ] else: self.comb += [ If(self.ctrl.storage[3], rgba_pwm[0].eq( self.raw.storage[0])).Else(rgba_pwm[0].eq(ledd_value[0])), If(self.ctrl.storage[4], rgba_pwm[1].eq( self.raw.storage[1])).Else(rgba_pwm[1].eq(ledd_value[1])), If(self.ctrl.storage[5], rgba_pwm[2].eq( self.raw.storage[2])).Else(rgba_pwm[2].eq(ledd_value[2])), ] self.specials += Instance( "SB_RGBA_DRV", i_CURREN=self.ctrl.storage[1], i_RGBLEDEN=self.ctrl.storage[2], i_RGB0PWM=rgba_pwm[0], i_RGB1PWM=rgba_pwm[1], i_RGB2PWM=rgba_pwm[2], o_RGB0=pads.rgb0, o_RGB1=pads.rgb1, o_RGB2=pads.rgb2, p_CURRENT_MODE="0b1", p_RGB0_CURRENT="0b000011", p_RGB1_CURRENT="0b000011", p_RGB2_CURRENT="0b000011", ) self.specials += Instance( "SB_LEDDA_IP", i_LEDDCS=self.dat.re, i_LEDDCLK=ClockSignal(), i_LEDDDAT7=self.dat.storage[7], i_LEDDDAT6=self.dat.storage[6], i_LEDDDAT5=self.dat.storage[5], i_LEDDDAT4=self.dat.storage[4], i_LEDDDAT3=self.dat.storage[3], i_LEDDDAT2=self.dat.storage[2], i_LEDDDAT1=self.dat.storage[1], i_LEDDDAT0=self.dat.storage[0], i_LEDDADDR3=self.addr.storage[3], i_LEDDADDR2=self.addr.storage[2], i_LEDDADDR1=self.addr.storage[1], i_LEDDADDR0=self.addr.storage[0], i_LEDDDEN=self.dat.re, i_LEDDEXE=self.ctrl.storage[0], # o_LEDDON = led_is_on, # Indicates whether LED is on or not # i_LEDDRST = ResetSignal(), # This port doesn't actually exist o_PWMOUT0=ledd_value[0], o_PWMOUT1=ledd_value[1], o_PWMOUT2=ledd_value[2], o_LEDDON=Signal(), )
def __init__(self, width=25): self.gpio_trigger = Signal() self.sweep_trigger = Signal() # when lock is disabled and sweep enabled, acquisition process arms the # scope, waits until scope has triggered and reads out the data. Once # data is read out, it rearms the acquisition. When robust autolock is # looking for a lock point, acquisition process doesn't send any triggers # though because it doesn't transmit any data until lock is confirmed. # Therefore, autolock turns on "always_arm" mode which automatically # rearms scope when it has finished. self.automatically_rearm = Signal() # this mode is used when the laser is locked. In this case we don't have # to sync acquisition with a ramp. Synchronisation with readout takes # place by manually rearming after reading out the data. self.automatically_trigger = Signal() automatic_trigger_signal = Signal() self.sync += [ If(self.automatically_trigger, automatic_trigger_signal.eq(~automatic_trigger_signal) ).Else( automatic_trigger_signal.eq(0) ) ] self.external_trigger = CSRStorage(1) ext_scope_trigger = Array([self.gpio_trigger, self.sweep_trigger])[ self.external_trigger.storage ] self.scope_sys = Record(sys_layout) self.asg_sys = Record(sys_layout) adc_a = Signal((width, True)) adc_a_q = Signal((width, True)) adc_b = Signal((width, True)) adc_b_q = Signal((width, True)) dac_a = Signal((width, True)) dac_b = Signal((width, True)) self.signal_in = adc_a, adc_b, adc_a_q, adc_b_q self.signal_out = dac_a, dac_b self.state_in = () self.state_out = () asg_a = Signal((14, True)) asg_b = Signal((14, True)) asg_trig = Signal() s = width - len(asg_a) self.comb += dac_a.eq(asg_a << s), dac_b.eq(asg_b << s) # these signals will be connected to autolock which inspects written data self.writing_data_now = Signal() self.scope_written_data = Signal((14, True)) self.scope_position = Signal(14) self.specials.scope = Instance( "red_pitaya_scope", i_automatically_rearm_i=self.automatically_rearm, i_adc_a_i=adc_a >> s, i_adc_b_i=adc_b >> s, i_adc_a_q_i=adc_a_q >> s, i_adc_b_q_i=adc_b_q >> s, # i_adc_a_q_i=0b11111111111111, # i_adc_b_q_i=0b11111111111111, i_adc_clk_i=ClockSignal(), i_adc_rstn_i=~ResetSignal(), i_trig_ext_i=ext_scope_trigger | automatic_trigger_signal, i_trig_asg_i=asg_trig, i_sys_clk_i=self.scope_sys.clk, i_sys_rstn_i=self.scope_sys.rstn, i_sys_addr_i=self.scope_sys.addr, i_sys_wdata_i=self.scope_sys.wdata, i_sys_sel_i=self.scope_sys.sel, i_sys_wen_i=self.scope_sys.wen, i_sys_ren_i=self.scope_sys.ren, o_sys_rdata_o=self.scope_sys.rdata, o_sys_err_o=self.scope_sys.err, o_sys_ack_o=self.scope_sys.ack, o_written_data=self.scope_written_data, o_scope_position=self.scope_position, o_scope_writing_now=self.writing_data_now, )
def __init__(self, platform, debug, variant=None, cpu_cfu=None, execute_from_lram=False, separate_arena=False, with_led_chaser=False, integrated_rom_init=[], build_bios=False, cfu_mport=False, dynamic_clock_control=False): LiteXSoC.__init__(self, platform=platform, sys_clk_freq=platform.sys_clk_freq, csr_data_width=32) if variant == None: variant = "full+debug" if debug else "full" # Clock, Controller, CPU self.submodules.crg = platform.create_crg() self.add_controller("ctrl") if execute_from_lram: reset_address = 0x00000000 else: reset_address = self.spiflash_region.origin + self.rom_offset self.add_cpu(self.cpu_type, variant=variant, reset_address=reset_address, cfu=cpu_cfu) # RAM if separate_arena: ram_size = 64 * KB arena_size = RAM_SIZE - ram_size elif execute_from_lram: # Leave one LRAM free for ROM ram_size = RAM_SIZE - 64 * KB arena_size = 0 else: ram_size = RAM_SIZE arena_size = 0 self.setup_ram(size=ram_size) self.setup_arena(size=arena_size) # Dynamic clock control between CPU and CFU if dynamic_clock_control: # Add dynamic clock control logic from clock_control import CfuCpuClockCtrl self.submodules.cfu_cpu_clk_ctl = ClockDomainsRenamer("osc")( CfuCpuClockCtrl()) cfu_cen = self.cfu_cpu_clk_ctl.cfu_cen cpu_cen = self.cfu_cpu_clk_ctl.cpu_cen ctl_cfu_bus = self.cfu_cpu_clk_ctl.cfu_bus cpu_cfu_bus = self.cpu.cfu_bus self.comb += [ # Connect dynamic clock control bus to CPU <-> CFU BUS ctl_cfu_bus.rsp.valid.eq(cpu_cfu_bus.rsp.valid), ctl_cfu_bus.rsp.ready.eq(cpu_cfu_bus.rsp.ready), ctl_cfu_bus.cmd.valid.eq(cpu_cfu_bus.cmd.valid), ctl_cfu_bus.cmd.ready.eq(cpu_cfu_bus.cmd.ready), # Connect system clock to dynamic clock enable self.crg.sys_clk_enable.eq(cpu_cen), ] # Create separate clock for CFU clko = ClockSignal("cfu") self.clock_domains.cd_cfu = ClockDomain("cfu") self.specials += Instance( "DCC", i_CLKI=ClockSignal("osc"), o_CLKO=clko, i_CE=cfu_cen, ) # Connect separate clock to CFU, keep reset from oscillator clock domain self.cpu.cfu_params.update(i_clk=clko) self.cpu.cfu_params.update(i_reset=ResetSignal("osc")) # Connect clock enable signals to RAM and Arena self.comb += [ self.lram.a_clkens[i].eq(cpu_cen) for i in range(len(self.lram.a_clkens)) ] if separate_arena: self.comb += [ self.arena.a_clkens[i].eq(cpu_cen) for i in range(len(self.arena.a_clkens)) ] if cfu_mport: self.comb += [ self.arena.b_clkens[i].eq(cfu_cen) for i in range(len(self.arena.b_clkens)) ] else: # If dynamic clock control is disabled, assert all memory clock enable signals self.comb += [ self.lram.a_clkens[i].eq(1) for i in range(len(self.lram.a_clkens)) ] if separate_arena: self.comb += [ self.arena.a_clkens[i].eq(1) for i in range(len(self.arena.a_clkens)) ] if cfu_mport: self.comb += [ self.arena.b_clkens[i].eq(1) for i in range(len(self.arena.b_clkens)) ] # Connect CFU directly to Arena LRAM memory if cfu_mport: self.connect_cfu_to_lram() # SPI Flash self.setup_litespi_flash() # ROM (either part of SPI Flash, or embedded) if execute_from_lram: self.setup_rom_in_lram() if integrated_rom_init: assert len(integrated_rom_init) <= 64 * KB / 4 self.integrated_rom_initialized = True self.rom.add_init(integrated_rom_init) else: self.setup_rom_in_flash() # "LEDS" - Just one LED on JTAG port if with_led_chaser: self.submodules.leds = LedChaser( pads=platform.request_all("user_led"), sys_clk_freq=platform.sys_clk_freq) self.csr.add("leds") # UART self.add_serial() # Wishbone UART and CPU debug - JTAG must be disabled to use serial2 if debug: self.add_uartbone("serial2", baudrate=UART_SPEED) self.bus.add_slave("vexriscv_debug", self.cpu.debug_bus, self.vexriscv_region) if build_bios: # Timer (required for the BIOS build only) self.add_timer(name="timer0") self.timer0.add_uptime()
def __init__( self, core_link_pads: typing.Sequence[platform.Pins], output_pads: typing.Sequence[platform.Pins], passthrough_sigs: typing.Sequence[Signal], input_phys: typing.Sequence["PHY"], simulate: bool = False, ): """Define the submodules & connections between them to form an ``Entangler``. Args: core_link_pads (typing.Sequence[platform.Pins]): A list of 4 FPGA pins used to link a master & slave ``Entangler`` device. output_pads (typing.Sequence[platform.Pins]): The output pins that will be driven by the state machines to output the entanglement generation signals. passthrough_sigs (typing.Sequence[Signal]): The signals that should be passed through to the ``output_pads`` when the ``Entangler`` is not running. input_phys (typing.Sequence["PHY"]): TTLInput physical gateware modules that register an input TTL event. Expects a list of 4, with the first 4 being the input APD/TTL signals, and the last one as a sync signal with the entanglement laser. simulate (bool, optional): If this should be instantiated in simulation mode. If it is simulated, it disables several options like the passthrough_sigs. Defaults to False. """ self.enable = Signal() # # # phy_apds = input_phys[0:4] phy_422pulse = input_phys[4] self.submodules.msm = MainStateMachine() self.submodules.sequencers = [ ChannelSequencer(self.msm.m) for _ in range(4) ] self.submodules.apd_gaters = [ TriggeredInputGater(self.msm.m, phy_422pulse, phy_apd) for phy_apd in phy_apds ] self.submodules.heralder = PatternMatcher(num_inputs=4, num_patterns=4) if not simulate: # To be able to trigger the pulse picker from both systems without # re-plugging cables, we OR the output from the slave (transmitted over the # core link ribbon cable) into the master, as long as the entangler core is # not actually active. There is no mechanism to arbitrate between concurrent # users at this level; the application code must ensure only one experiment # requiring the pulsed laser runs at a time. local_422ps_out = Signal() slave_422ps_raw = Signal() # Connect output pads to sequencer output when enabled, otherwise use # the RTIO phy output for i, (sequencer, pad, passthrough_sig) in enumerate( zip(self.sequencers, output_pads, passthrough_sigs)): if i == SEQUENCER_IDX_422ps: local_422ps_out = Mux(self.enable, sequencer.output, passthrough_sig) passthrough_sig = passthrough_sig | (slave_422ps_raw & self.msm.is_master) self.specials += Instance( "OBUFDS", i_I=Mux(self.enable, sequencer.output, passthrough_sig), o_O=pad.p, o_OB=pad.n, ) # Connect the "running" output, which is asserted when the core is # running, or controlled by the passthrough signal when the core is # not running. self.specials += Instance( "OBUFDS", i_I=Mux(self.msm.running, 1, passthrough_sigs[4]), o_O=output_pads[4].p, o_OB=output_pads[4].n, ) def ts_buf(pad, sig_o, sig_i, en_out): # diff. IO. # sig_o: output from FPGA # sig_i: intput to FPGA # en_out: enable FPGA output driver self.specials += Instance( "IOBUFDS_INTERMDISABLE", p_DIFF_TERM="TRUE", p_IBUF_LOW_PWR="TRUE", p_USE_IBUFDISABLE="TRUE", i_IBUFDISABLE=en_out, i_INTERMDISABLE=en_out, i_I=sig_o, o_O=sig_i, i_T=~en_out, io_IO=pad.p, io_IOB=pad.n, ) # Interface between master and slave core. # Slave -> master: ts_buf( core_link_pads[0], self.msm.ready, self.msm.slave_ready_raw, ~self.msm.is_master & ~self.msm.standalone, ) ts_buf(core_link_pads[4], local_422ps_out, slave_422ps_raw, ~self.msm.is_master) # Master -> slave: ts_buf( core_link_pads[1], self.msm.trigger_out, self.msm.trigger_in_raw, self.msm.is_master, ) ts_buf( core_link_pads[2], self.msm.success, self.msm.success_in_raw, self.msm.is_master, ) ts_buf( core_link_pads[3], self.msm.timeout, self.msm.timeout_in_raw, self.msm.is_master, ) # Connect heralder inputs. self.comb += self.heralder.sig.eq( Cat(*(g.triggered for g in self.apd_gaters))) # Clear gater and sequencer state at start of each cycle self.comb += [ gater.clear.eq(self.msm.cycle_starting) for gater in self.apd_gaters ] self.comb += [ sequencer.clear.eq(self.msm.cycle_starting) for sequencer in self.sequencers ] self.comb += self.msm.herald.eq(self.heralder.is_match) # 422ps trigger event counter. We use got_ref from the first gater for # convenience (any other channel would work just as well). self.triggers_received = Signal(14) self.sync += [ If(self.msm.run_stb, self.triggers_received.eq(0)).Else( If( self.msm.cycle_ending & self.apd_gaters[0].got_ref, self.triggers_received.eq(self.triggers_received + 1), )) ]
def __init__(self, platform, output_dir="build", usb_variant='dummy', **kwargs): # Disable integrated RAM as we'll add it later self.integrated_sram_size = 0 self.output_dir = output_dir clk_freq = int(48e6) self.submodules.crg = _CRG(platform) SoCCore.__init__(self, platform, clk_freq, cpu_type=None, integrated_rom_size=0x0, integrated_sram_size=0x0, integrated_main_ram_size=0x0, csr_address_width=14, csr_data_width=8, with_uart=False, with_timer=False) # USB signals usb_p_tx = Signal() usb_n_tx = Signal() usb_p_rx = Signal() usb_n_rx = Signal() usb_tx_en = Signal() usb_tx_en_dut = Signal() usb_reset = Signal() usb_p_t = TSTriple() usb_n_t = TSTriple() usb_pads = platform.request("usb") # Assign signals to triple self.comb += [ If( ~usb_tx_en_dut, usb_p_rx.eq(0b1), usb_n_rx.eq(0b0), ).Else( usb_p_rx.eq(usb_p_t.i), usb_n_rx.eq(usb_n_t.i), ), usb_p_t.oe.eq(~usb_tx_en_dut), usb_n_t.oe.eq(~usb_tx_en_dut), usb_p_t.o.eq(usb_p_tx), usb_n_t.o.eq(usb_n_tx), ] self.comb += usb_tx_en.eq(~usb_tx_en_dut) # Delay USB_TX_EN line for i in range(4): tx_en_tmp = Signal() self.sync.sys += tx_en_tmp.eq(usb_tx_en) usb_tx_en = tx_en_tmp self.comb += usb_reset.eq(~self.crg.cd_sys.rst) # Assign pads to triple self.specials += usb_p_t.get_tristate(usb_pads.d_p) self.specials += usb_n_t.get_tristate(usb_pads.d_n) # Deasserting tx_en should not be delayed self.comb += usb_pads.tx_en.eq(usb_tx_en & ~usb_tx_en_dut) platform.add_source("../usb1_device/rtl/verilog/usb1_core.v") self.specials += Instance( "usb1_core", i_clk_i=self.crg.cd_sys.clk, i_rst_i=usb_reset, # USB lines o_tx_dp=usb_p_tx, o_tx_dn=usb_n_tx, i_rx_dp=usb_p_rx, i_rx_dn=usb_n_rx, o_tx_oe=usb_tx_en_dut, i_rx_d=usb_p_rx, i_phy_tx_mode=0b1)
def __init__(self, revision, pads): rgba_pwm = Signal(3) self.intro = ModuleDoc("""RGB LED Controller The ICE40 contains two different RGB LED control devices. The first is a constant-current LED source, which is fixed to deliver 4 mA to each of the three LEDs. This block is called ``SB_RGBA_DRV``. The other is used for creating interesting fading effects, particularly for "breathing" effects used to indicate a given state. This block is called ``SB_LEDDA_IP``. This block feeds directly into ``SB_RGBA_DRV``. The RGB LED controller available on this device allows for control of these two LED control devices. Additionally, it is possible to disable ``SB_LEDDA_IP`` and directly control the individual LEDs. """) self.dat = CSRStorage(8, description=""" This is the value for the ``SB_LEDDA_IP.DAT`` register. It is directly written into the ``SB_LEDDA_IP`` hardware block, so you should refer to http://www.latticesemi.com/view_document?document_id=50668. The contents of this register are written to the address specified in ``ADDR`` immediately upon writing this register.""" ) self.addr = CSRStorage(4, description=""" This register is directly connected to ``SB_LEDDA_IP.ADDR``. This register controls the address that is updated whenever ``DAT`` is written. Writing to this register has no immediate effect -- data isn't written until the ``DAT`` register is written.""" ) self.ctrl = CSRStorage(fields=[ CSRField( "exe", description= "Connected to ``SB_LEDDA_IP.LEDDEXE``. Set this to ``1`` to enable the fading pattern." ), CSRField( "curren", description= "Connected to ``SB_RGBA_DRV.CURREN``. Set this to ``1`` to enable the current source." ), CSRField( "rgbleden", description= "Connected to ``SB_RGBA_DRV.RGBLEDEN``. Set this to ``1`` to enable the RGB PWM control logic." ), CSRField( "rraw", description= "Set this to ``1`` to enable raw control of the red LED via the ``RAW.R`` register." ), CSRField( "graw", description= "Set this to ``1`` to enable raw control of the green LED via the ``RAW.G`` register." ), CSRField( "braw", description= "Set this to ``1`` to enable raw control of the blue LED via the ``RAW.B`` register." ), ], description= "Control logic for the RGB LED and LEDDA hardware PWM LED block." ) self.raw = CSRStorage(fields=[ CSRField("r", description= "Raw value for the red LED when ``CTRL.RRAW`` is ``1``."), CSRField( "g", description= "Raw value for the green LED when ``CTRL.GRAW`` is ``1``."), CSRField( "b", description= "Raw value for the blue LED when ``CTRL.BRAW`` is ``1``."), ], description=""" Normally the hardware ``SB_LEDDA_IP`` block controls the brightness of the LED, creating a gentle fading pattern. However, by setting the appropriate bit in ``CTRL``, it is possible to manually control the three individual LEDs.""" ) ledd_value = Signal(3) if revision == "pvt" or revision == "dvt": self.comb += [ If(self.ctrl.storage[3], rgba_pwm[1].eq( self.raw.storage[0])).Else(rgba_pwm[1].eq(ledd_value[0])), If(self.ctrl.storage[4], rgba_pwm[0].eq( self.raw.storage[1])).Else(rgba_pwm[0].eq(ledd_value[1])), If(self.ctrl.storage[5], rgba_pwm[2].eq( self.raw.storage[2])).Else(rgba_pwm[2].eq(ledd_value[2])), ] elif revision == "evt": self.comb += [ If(self.ctrl.storage[3], rgba_pwm[1].eq( self.raw.storage[0])).Else(rgba_pwm[1].eq(ledd_value[0])), If(self.ctrl.storage[4], rgba_pwm[2].eq( self.raw.storage[1])).Else(rgba_pwm[2].eq(ledd_value[1])), If(self.ctrl.storage[5], rgba_pwm[0].eq( self.raw.storage[2])).Else(rgba_pwm[0].eq(ledd_value[2])), ] elif revision == "hacker": self.comb += [ If(self.ctrl.storage[3], rgba_pwm[2].eq( self.raw.storage[0])).Else(rgba_pwm[2].eq(ledd_value[0])), If(self.ctrl.storage[4], rgba_pwm[1].eq( self.raw.storage[1])).Else(rgba_pwm[1].eq(ledd_value[1])), If(self.ctrl.storage[5], rgba_pwm[0].eq( self.raw.storage[2])).Else(rgba_pwm[0].eq(ledd_value[2])), ] else: self.comb += [ If(self.ctrl.storage[3], rgba_pwm[0].eq( self.raw.storage[0])).Else(rgba_pwm[0].eq(ledd_value[0])), If(self.ctrl.storage[4], rgba_pwm[1].eq( self.raw.storage[1])).Else(rgba_pwm[1].eq(ledd_value[1])), If(self.ctrl.storage[5], rgba_pwm[2].eq( self.raw.storage[2])).Else(rgba_pwm[2].eq(ledd_value[2])), ] self.specials += Instance( "SB_RGBA_DRV", i_CURREN=self.ctrl.storage[1], i_RGBLEDEN=self.ctrl.storage[2], i_RGB0PWM=rgba_pwm[0], i_RGB1PWM=rgba_pwm[1], i_RGB2PWM=rgba_pwm[2], o_RGB0=pads.r, o_RGB1=pads.g, o_RGB2=pads.b, p_CURRENT_MODE="0b1", p_RGB0_CURRENT="0b000011", p_RGB1_CURRENT="0b000011", p_RGB2_CURRENT="0b000011", ) self.specials += Instance( "SB_LEDDA_IP", i_LEDDCS=self.dat.re, i_LEDDCLK=ClockSignal(), i_LEDDDAT7=self.dat.storage[7], i_LEDDDAT6=self.dat.storage[6], i_LEDDDAT5=self.dat.storage[5], i_LEDDDAT4=self.dat.storage[4], i_LEDDDAT3=self.dat.storage[3], i_LEDDDAT2=self.dat.storage[2], i_LEDDDAT1=self.dat.storage[1], i_LEDDDAT0=self.dat.storage[0], i_LEDDADDR3=self.addr.storage[3], i_LEDDADDR2=self.addr.storage[2], i_LEDDADDR1=self.addr.storage[1], i_LEDDADDR0=self.addr.storage[0], i_LEDDDEN=self.dat.re, i_LEDDEXE=self.ctrl.storage[0], # o_LEDDON = led_is_on, # Indicates whether LED is on or not # i_LEDDRST = ResetSignal(), # This port doesn't actually exist o_PWMOUT0=ledd_value[0], o_PWMOUT1=ledd_value[1], o_PWMOUT2=ledd_value[2], o_LEDDON=Signal(), )
def __init__(self, platform, output_dir="build", **kwargs): # Disable integrated RAM as we'll add it later self.integrated_sram_size = 0 self.output_dir = output_dir clk_freq = int(12e6) self.submodules.crg = _CRG(platform) SoCCore.__init__(self, platform, clk_freq, cpu_type=None, integrated_rom_size=0x0, integrated_sram_size=0x0, integrated_main_ram_size=0x0, csr_address_width=14, csr_data_width=8, with_uart=False, with_timer=False) # USB signals usb_p_tx = Signal() usb_n_tx = Signal() usb_p_rx = Signal() usb_n_rx = Signal() usb_tx_en = Signal() usb_p_t = TSTriple() usb_n_t = TSTriple() usb_pads = platform.request("usb") # Assign signals to triple self.comb += [ If(usb_tx_en, usb_p_rx.eq(0b1), usb_n_rx.eq(0b0), ).Else( usb_p_rx.eq(usb_p_t.i), usb_n_rx.eq(usb_n_t.i), ), usb_p_t.oe.eq(usb_tx_en), usb_n_t.oe.eq(usb_tx_en), usb_p_t.o.eq(usb_p_tx), usb_n_t.o.eq(usb_n_tx), ] # Assign pads to triple self.specials += usb_p_t.get_tristate(usb_pads.d_p) self.specials += usb_n_t.get_tristate(usb_pads.d_n) self.comb += usb_pads.tx_en.eq(usb_tx_en) self.comb += usb_pads.pullup.eq(0b1) platform.add_source("../tinyfpga/common/tinyfpga_bootloader.v") self.specials += Instance("tinyfpga_bootloader", i_clk_48mhz=self.crg.cd_usb_48.clk, i_clk=self.crg.cd_usb_48.clk, i_reset=self.crg.cd_sys.rst, # USB lines o_usb_p_tx=usb_p_tx, o_usb_n_tx=usb_n_tx, i_usb_p_rx=usb_p_rx, i_usb_n_rx=usb_n_rx, o_usb_tx_en=usb_tx_en )
def __init__(self, platform): clk48_raw = platform.request("clk48") clk12 = Signal() reset_delay = Signal(12, reset=4095) self.clock_domains.cd_por = ClockDomain() self.reset = Signal() self.clock_domains.cd_sys = ClockDomain() self.clock_domains.cd_usb_12 = ClockDomain() self.clock_domains.cd_usb_48 = ClockDomain() platform.add_period_constraint(self.cd_usb_48.clk, 1e9 / 48e6) platform.add_period_constraint(self.cd_sys.clk, 1e9 / 12e6) platform.add_period_constraint(self.cd_usb_12.clk, 1e9 / 12e6) platform.add_period_constraint(clk48_raw, 1e9 / 48e6) # POR reset logic- POR generated from sys clk, POR logic feeds sys clk # reset. self.comb += [ self.cd_por.clk.eq(self.cd_sys.clk), self.cd_sys.rst.eq(reset_delay != 0), self.cd_usb_12.rst.eq(reset_delay != 0), ] # POR reset logic- POR generated from sys clk, POR logic feeds sys clk # reset. self.comb += [ self.cd_usb_48.rst.eq(reset_delay != 0), ] self.comb += self.cd_usb_48.clk.eq(clk48_raw) self.specials += Instance( "SB_PLL40_CORE", # Parameters p_DIVR=0, p_DIVF=15, p_DIVQ=5, p_FILTER_RANGE=1, p_FEEDBACK_PATH="SIMPLE", p_DELAY_ADJUSTMENT_MODE_FEEDBACK="FIXED", p_FDA_FEEDBACK=15, p_DELAY_ADJUSTMENT_MODE_RELATIVE="FIXED", p_FDA_RELATIVE=0, p_SHIFTREG_DIV_MODE=1, p_PLLOUT_SELECT="GENCLK_HALF", p_ENABLE_ICEGATE=0, # IO i_REFERENCECLK=clk48_raw, o_PLLOUTCORE=clk12, # o_PLLOUTGLOBAL = clk12, #i_EXTFEEDBACK, #i_DYNAMICDELAY, #o_LOCK, i_BYPASS=0, i_RESETB=1, #i_LATCHINPUTVALUE, #o_SDO, #i_SDI, ) self.comb += self.cd_sys.clk.eq(clk12) self.comb += self.cd_usb_12.clk.eq(clk12) self.sync.por += \ If(reset_delay != 0, reset_delay.eq(reset_delay - 1) ) self.specials += AsyncResetSynchronizer(self.cd_por, self.reset)
def __init__(self, platform, pads, size=2 * 1024 * 1024): self.size = size self.bus = bus = wishbone.Interface() self.reset = Signal() self.cfg1 = CSRStorage(size=8) self.cfg2 = CSRStorage(size=8) self.cfg3 = CSRStorage(size=8) self.cfg4 = CSRStorage(size=8) self.stat1 = CSRStatus(size=8) self.stat2 = CSRStatus(size=8) self.stat3 = CSRStatus(size=8) self.stat4 = CSRStatus(size=8) cfg = Signal(32) cfg_we = Signal(4) cfg_out = Signal(32) self.comb += [ cfg.eq( Cat(self.cfg1.storage, self.cfg2.storage, self.cfg3.storage, self.cfg4.storage)), cfg_we.eq( Cat(self.cfg1.re, self.cfg2.re, self.cfg3.re, self.cfg4.re)), self.stat1.status.eq(cfg_out[0:8]), self.stat2.status.eq(cfg_out[8:16]), self.stat3.status.eq(cfg_out[16:24]), self.stat4.status.eq(cfg_out[24:32]), ] mosi_pad = TSTriple() miso_pad = TSTriple() cs_n_pad = TSTriple() clk_pad = TSTriple() wp_pad = TSTriple() hold_pad = TSTriple() self.specials += mosi_pad.get_tristate(pads.mosi) self.specials += miso_pad.get_tristate(pads.miso) self.specials += cs_n_pad.get_tristate(pads.cs_n) self.specials += clk_pad.get_tristate(pads.clk) self.specials += wp_pad.get_tristate(pads.wp) self.specials += hold_pad.get_tristate(pads.hold) reset = Signal() self.comb += [ reset.eq(ResetSignal() | self.reset), cs_n_pad.oe.eq(~reset), clk_pad.oe.eq(~reset), ] flash_addr = Signal(24) # size/4 because data bus is 32 bits wide, -1 for base 0 mem_bits = bits_for(int(size / 4) - 1) pad = Signal(2) self.comb += flash_addr.eq(Cat(pad, bus.adr[0:mem_bits - 1])) read_active = Signal() spi_ready = Signal() self.sync += [ If( bus.stb & bus.cyc & ~read_active, read_active.eq(1), bus.ack.eq(0), ).Elif( read_active & spi_ready, read_active.eq(0), bus.ack.eq(1), ).Else( bus.ack.eq(0), read_active.eq(0), ) ] o_rdata = Signal(32) self.comb += bus.dat_r.eq(o_rdata) self.specials += Instance( "spimemio", o_flash_io0_oe=mosi_pad.oe, o_flash_io1_oe=miso_pad.oe, o_flash_io2_oe=wp_pad.oe, o_flash_io3_oe=hold_pad.oe, o_flash_io0_do=mosi_pad.o, o_flash_io1_do=miso_pad.o, o_flash_io2_do=wp_pad.o, o_flash_io3_do=hold_pad.o, o_flash_csb=cs_n_pad.o, o_flash_clk=clk_pad.o, i_flash_io0_di=mosi_pad.i, i_flash_io1_di=miso_pad.i, i_flash_io2_di=wp_pad.i, i_flash_io3_di=hold_pad.i, i_resetn=~reset, i_clk=ClockSignal(), i_valid=bus.stb & bus.cyc, o_ready=spi_ready, i_addr=flash_addr, o_rdata=o_rdata, i_cfgreg_we=cfg_we, i_cfgreg_di=cfg, o_cfgreg_do=cfg_out, ) platform.add_source("rtl/spimemio.v")
def __init__(self, platform, mem, minimal=False): self.intro = ModuleDoc("""FOMU Apple II+ A virtual computer within a virtual computer inside a USB port. Instantiate 6502 processor with 1MHz core clock. Tie in to system memory as a wishbone master. Create virtual keyboard, video display and disk drive. """) addr = Signal(16) dout = Signal(8) din = Signal(8) wren = Signal() iosel = Signal() ior_addr = Signal(8) r_memsel = Signal() w_memsel = Signal() clk_en = Signal() # Clock divider limits CPU activity active = Signal() # CPU is active this cycle available = Signal() # Key press ready for reading div1M = 4 idlecount = Signal(div1M) # Counter to slow CPU clock # Disk II Controller Registers disk_phase = Signal(4) disk_motor = Signal() disk_drive = Signal() #disk_write = Signal() disk_reading = Signal() # DOS trying to read sector disk_data_available = Signal() # Data available for DOS to read disk_data_wanted = Signal() # Data wanted by DOS disk_read = Signal() # Data read by DOS so clear readable simulation = getenv("SIMULATION") synthesis = not simulation # Wishbone visible registers self.control = CSRStorage(fields=[ CSRField( "Reset", reset=1 if synthesis else 0, # auto-start in sim description="6502 Reset line - 1: Reset Asserted, 0: Running"), CSRField("RWROM", size=1, description="Allow writes to ROM"), #CSRField("Pause", description="Halt processor allowing stepping"), #CSRField("Step", description="Single step 6502 one clock cycle"), #CSRField("NMI", size=1, description="Non-maskable interrupt"), #CSRField("IRQ", size=1, description="Maskable interrupt request"), #CSRField("RDY", size=1, description=""), CSRField( "Divisor", size=div1M, offset=8, reset=11 if synthesis else 0, # Over-clock simulation description="Clock divider minius 1: 11 for 1MHz, 0 for 12MHz" ), #CSRField("DI", size=8, offset=16, description=""), ]) self.keyboard = CSRStorage(8, write_from_dev=True, description="Keyboard input ($C000)") self.strobe = CSR(1) #, description="Keyboard strobe ($C010)") self.screen = CSRStatus( fields=[ CSRField("Character", size=8, description="Character written to screen"), CSRField("Valid", size=1, description="Character is valid"), CSRField( "More", size=1, description="Additional characters are available to read"), #CSRField("Move", size=1, # description="Character is not adjacent to previous"), CSRField("Repeat", size=1, offset=11, description= "Previous character repeated to current position"), CSRField("ScrollStart", size=1, offset=12, description="Start of scroll region detected"), CSRField("ScrollEnd", size=1, offset=13, description="End of scroll region"), CSRField( "Horizontal", size=6, offset=16, description="Location of current character in screen memory" ), CSRField( "Vertical", size=5, offset=24, description="Location of current character in screen memory" ), ], description="Video Display Output") self.diskctrl = CSRStatus( fields=[ CSRField("Phase", size=4, description= "Four phases of the track selection stepper motor"), CSRField("Motor", size=1, description="Drive is spinning"), CSRField( "Drive", size=1, description="Drive select: drive 1 if clear, drive 2 if set" ), CSRField("Wanted", size=1, description="Drive is waiting for data"), CSRField("Pending", size=1, description="Drive has not yet read data written"), #CSRField("WriteMode", size=1, # description="Drive is reading when clear, writing when set"), ], description="Disk drive control ($C0EX)") self.diskdata = CSRStorage(8, description="Disk drive data ($C0EC)") #self.bus=CSRStatus(32, fields=[ # CSRField("Addr", size=16, description="Address bus"), # CSRField("Data", size=8, description="Data bus"), # CSRField("WrEn", size=1, description="Write enable"), # ], description="Address and data bus") #self.debug=CSRStatus(32, fields=[ # CSRField("PC", size=8, # description="Program counter"), # CSRField("A", size=8, # description="Accumulator"), # CSRField("X", size=8, # description="X index register"), # CSRField("Y", size=8, # description="Y index register"), # ], description="Address and data bus") if not minimal: # The minimal configuration provides all registers the host needs to # see so software can run unmodified. However, it does not implement # the 6502 to save gates. The video driver is also greatly reduced. # TODO eliminate wire [31:0] apple2_display_fifo_wrport_dat_r self.submodules.display_fifo = fifo.SyncFIFOBuffered(width=32, depth=256) self.comb += [ mem.addr6502.eq(addr), mem.din6502.eq(dout), mem.wren6502.eq(wren), self.strobe.w.eq(available), #self.bus.fields.Addr.eq(addr), #self.bus.fields.Data.eq(dout), #self.bus.fields.WrEn.eq(wren), If(addr[8:16] == 0xC0, iosel.eq(1), w_memsel.eq(0), mem.access6502.eq(0)).Else(iosel.eq(0), w_memsel.eq(1), mem.access6502.eq(active)), disk_read.eq(0), If( r_memsel, din.eq(mem.dout6502), ).Else( # I/O Read Address Decoder (reading but not from memory) If( ior_addr[4:8] == 0x0, din.eq(Cat(self.keyboard.storage[0:7], available)), ), # Disk II Controller Card in slot 6 (0x8 | 0x6) # The only data to be read are locations C and D. Simplify the # logic to only look at bit 0 of the address. If( ior_addr[4:8] == 0xE, din[0:7].eq(self.diskdata.storage[0:7]), # Write protect - TODO write is not supported #If(ior_addr[0], # # Return high bit set - protected # din[7].eq(1) #).Else( disk_read.eq(1), If( disk_data_available | self.diskdata.re, # Return byte given by host din[7].eq(self.diskdata.storage[7]), ).Else( # Return high bit clear - data not available din[7].eq(0), ), #), ), ), active.eq(clk_en & self.display_fifo.writable), ] self.sync += [ # Slow clock to prototypical speed or as configured by user If( idlecount == self.control.fields.Divisor, idlecount.eq(0), clk_en.eq(1), ).Else( idlecount.eq(idlecount + 1), clk_en.eq(0), ), # Read (DI) follows Write (AB/DO) by one clock cycle If( active, r_memsel.eq(w_memsel), ior_addr.eq(addr[0:8]), ), # Keyboard key available when written by host If( self.keyboard.re, available.eq(1), ), If( iosel, # I/O Write Address Decoder If( addr[4:8] == 0x1, # KBDSTRB # Strobe cleared on read or write to KBDSTRB # Any read or write to this address clears the pending key available.eq(0), ), ), ] self.specials += Instance( "cpu", i_clk=ClockSignal(), i_reset=ResetSignal() | self.control.storage[0], i_DI=din, # &(self.rand.we|self.cfg.storage[1])), o_AB=addr, # .dat_w, o_DO=dout, # .dat_w, o_WE=wren, i_IRQ=False, # self.control.fields.IRQ, i_NMI=False, # self.control.fields.NMI, # seed.re, i_RDY=active, # self.control.fields.RDY, ) platform.add_source("rtl/verilog-6502/cpu.v") platform.add_source("rtl/verilog-6502/ALU.v") #=============================================================================== # Disk Drive - Emulate Disk II controller in slot 6 #=============================================================================== # The Disk II controller card has 16 addressable locations. Eight of these are # dedicated to moving the arm, two for motor control, two for drive selection # and four that handle read, write, and write protection detection. #=============================================================================== self.comb += [ self.diskctrl.fields.Phase.eq(disk_phase), self.diskctrl.fields.Motor.eq(disk_motor), self.diskctrl.fields.Drive.eq(disk_drive), #self.diskctrl.fields.WriteMode.eq(disk_write), self.diskctrl.fields.Wanted.eq(disk_data_wanted), self.diskctrl.fields.Pending.eq(disk_data_available), ] self.sync += [ If( self.diskdata.re, disk_data_available.eq(1), ), # Set false again on read If( active & disk_read, disk_reading.eq(0), If( disk_data_available, disk_data_wanted.eq(0), ).Else(disk_data_wanted.eq(1), ), disk_data_available.eq(0), ), If( iosel, # Disk II Controller Card in slot 6 # C0E0 PHASEOFF Stepper motor phase 0 off. # C0E1 PHASEON Stepper motor phase 0 on. # C0E2 PHASE1OFF Stepper motor phase 1 off. # C0E3 PHASElON Stepper motor phase 1 on. # C0E4 PHASE2OFF Stepper motor phase 2 off. # C0E5 PHASE2ON Stepper notor phase 2 on. # C0E6 PHASE3OFF Stepper motor phase 3 off. # C0E7 PHASE3ON Stepper motor phase 3 on. # C0E8 MOTOROFF Turn motor off. # C0E9 MOTORON Turn motor on. # C0EA DRV0EN Engage drive 1. # C0EB DRV1EN Engage drive 2. # C0EC Q6L Strobe Data Latch for I/O. # C0ED Q6H Load Data Latch. # C0EE Q7H Prepare latch for input (read from disk). # C0EF Q7L Prepare latch for output (write to disk). # Q7L with Q6L = Read # Q7L with Q6H = Sense Write Protect # Q7H with Q6L = Write # Q7H with Q6H = Load Write Latch If( addr[4:8] == 0xE, # (8|6) # Addresses 0-7 simply update a bit in the status register If(addr[0:4] == 0x0, disk_phase[0].eq(0)), If(addr[0:4] == 0x1, disk_phase[0].eq(1)), If(addr[0:4] == 0x2, disk_phase[1].eq(0)), If(addr[0:4] == 0x3, disk_phase[1].eq(1)), If(addr[0:4] == 0x4, disk_phase[2].eq(0)), If(addr[0:4] == 0x5, disk_phase[2].eq(1)), If(addr[0:4] == 0x6, disk_phase[3].eq(0)), If(addr[0:4] == 0x7, disk_phase[3].eq(1)), # Likewise, motor active and drive select update status If(addr[0:4] == 0x8, disk_motor.eq(0)), If(addr[0:4] == 0x9, disk_motor.eq(1)), If(addr[0:4] == 0xA, disk_drive.eq(0)), If(addr[0:4] == 0xB, disk_drive.eq(1)), # Write is ignored and read must be delayed one clock tick If(addr[0:4] == 0xC, disk_reading.eq(1)), #If(addr[0:4]==0xD, disk_ior_wp.eq(1)), #If(addr[0:4]==0xE, disk_write.eq(0)), #If(addr[0:4]==0xF, disk_write.eq(1)), ), ), ] #=============================================================================== # Video Output - Text Mode #=============================================================================== # The Apple II screen memory contains 8 segments containing 3 rows each in a 128 # byte block leaving 8 unused bytes in each of the 8 blocks To assist with # scroll detection, we convert memory addresses to screen coordinates. #=============================================================================== # Video memory - Frame Buffer access shortcuts fbsel = Signal() fb_r = Signal() fb_w = Signal() # Conversion from memory address to X,Y screen coordinates segment = Signal(3) triple = Signal(7) third = Signal(2) horiz = Signal(6) vert = Signal(5) move = Signal() scroll_active = Signal() scroll_match = Signal() scroll_start = Signal() scroll_end = Signal() scroll_read = Signal() scroll_write_valid = Signal() scroll_next_col = Signal() scroll_next_row = Signal() scroll_sequential = Signal() read_horiz = Signal(6) read_vert = Signal(5) repeat_active = Signal() repeat_match = Signal() repeat_start = Signal() repeat_end = Signal() repeat_next_col = Signal() repeat_next_row = Signal() repeat_sequential = Signal() # Registers shared by scroll and repeat compression circuits #horiz_start = Signal(max=40) #vert_start = Signal(max=24) #horiz_end = Signal(max=40) #vert_end = Signal(max=24) prev_horiz = Signal(max=40) prev_vert = Signal(max=24) prev_char = Signal(8) prev_start = Signal() push_save = Signal() push_saving = Signal() fifo_out = Signal(32) self.comb += [ # Detect access to frame memory: Address range 0x0400-0x7ff fbsel.eq((addr[10:15] == 0x1) & active), fb_r.eq(fbsel & ~wren), fb_w.eq(fbsel & wren), # Convert memory address to X,Y coordinates segment.eq(addr[7:10]), triple.eq(addr[0:7]), # TODO This generates reg - change to cause only wire If( triple >= 80, third.eq(2), horiz.eq(addr[0:7] - 80), ).Else( If( triple >= 40, third.eq(1), horiz.eq(addr[0:7] - 40), ).Else( third.eq(0), horiz.eq(addr[0:7]), )), vert.eq(Cat(segment, third)), # TODO Detect scroll - frame buffer read immediately followed by # frame buffer write to character on previous line, directly above. # Scroll is Right to Left (asm: DEY at FC90 in Autostart ROM) scroll_match.eq((horiz == read_horiz) & (vert + 1 == read_vert)), # & (din==read_char)) <== TODO Need to delay din by 1 cycle scroll_write_valid.eq(scroll_read & fb_w & scroll_match), scroll_start.eq(scroll_write_valid & ~scroll_active), # Scroll ends on any write that does not follow the required pattern scroll_end.eq(scroll_active & fb_w & ~scroll_write_valid), scroll_next_col.eq((horiz + 1 == prev_horiz) & (vert == prev_vert)), scroll_next_row.eq((horiz == 39) & (prev_horiz == 0) & (vert == prev_vert + 1)), scroll_sequential.eq(scroll_next_col | scroll_next_row), # Detect repeated charaters (spaces) # Clear is Left to Right (asm: INY at FCA2 in Autostart ROM) # repeat_match.eq(fb_w & (dout==prev_char)), # repeat_start.eq(repeat_match & repeat_sequential & ~repeat_active), # repeat_end.eq(fb_w & repeat_active & # (~repeat_match |~repeat_sequential)), # repeat_next_col.eq((horiz==prev_horiz+1) & (vert==prev_vert)), # repeat_next_row.eq((horiz==0) & (prev_horiz==39) & # (vert==prev_vert+1)), # repeat_sequential.eq(repeat_next_col | repeat_next_row), # repeat_sequential.eq(repeat_next_col), # This or the previous one # Place writes in the fifo self.display_fifo.din[8].eq(0), # Valid is calculated self.display_fifo.din[9].eq(0), # More is calculated #self.display_fifo.din[ 10].eq(move), self.display_fifo.din[11].eq(repeat_end), If( push_save, self.display_fifo.din[0:8].eq(prev_char), self.display_fifo.din[12].eq(prev_start), self.display_fifo.din[13].eq(scroll_end), #self.display_fifo.din[14:16].eq(0), # Reserved self.display_fifo.din[16:22].eq(prev_horiz ), # 2 bits padding self.display_fifo.din[24:29].eq( prev_vert), # 3 bits padding ).Elif( push_saving, # push_save will be valid on the next cycle - so push previous self.display_fifo.din[0:8].eq(prev_char), #self.display_fifo.din[ 8].eq(0), # Valid is calculated #self.display_fifo.din[ 9].eq(0), # More is calculated #self.display_fifo.din[ 10].eq(move), #self.display_fifo.din[ 11].eq(repeat_end), self.display_fifo.din[12].eq(scroll_start), self.display_fifo.din[13].eq(scroll_end), #self.display_fifo.din[14:16].eq(0), # Reserved self.display_fifo.din[16:22].eq(prev_horiz ), # 2 bits padding self.display_fifo.din[24:29].eq( prev_vert), # 3 bits padding ).Else( #self.display_fifo.din.eq(Cat(dout, horiz, vert, # move, scroll_start, scroll_end, repeat_start, repeat_end)), self.display_fifo.din[0:8].eq(dout), #self.display_fifo.din[ 8].eq(0), # Valid is calculated #self.display_fifo.din[ 9].eq(0), # More is calculated #self.display_fifo.din[ 10].eq(move), #self.display_fifo.din[ 11].eq(repeat_end), self.display_fifo.din[12].eq(scroll_start), self.display_fifo.din[13].eq(scroll_end), #self.display_fifo.din[14:16].eq(0), # Reserved self.display_fifo.din[16:22].eq(horiz), # 2 bits padding self.display_fifo.din[24:29].eq(vert), # 3 bits padding ), self.display_fifo.we.eq(push_save | repeat_end | scroll_start | scroll_end | (fb_w & ~scroll_active & ~repeat_active & ~repeat_start)), push_saving.eq(((repeat_end & ~repeat_sequential) | scroll_end) & ~push_save), # Retrieve characters from fifo self.display_fifo.re.eq(self.screen.we), self.screen.we.eq(self.display_fifo.re), self.screen.fields.Valid.eq(self.display_fifo.readable), self.screen.fields.More.eq(self.display_fifo.readable), self.screen.fields.Character.eq(fifo_out[0:8]), self.screen.fields.Horizontal.eq(fifo_out[16:22]), self.screen.fields.Vertical.eq(fifo_out[24:29]), #self.screen.fields.Move.eq(fifo_out[10]), self.screen.fields.Repeat.eq(fifo_out[11]), self.screen.fields.ScrollStart.eq(fifo_out[12]), self.screen.fields.ScrollEnd.eq(fifo_out[13]), ] self.sync += [ fifo_out.eq(self.display_fifo.dout), # Scroll If( scroll_start, scroll_active.eq(1), #horiz_start.eq(horiz), #vert_start.eq(vert), #horiz_end.eq(horiz), #vert_end.eq(vert), ), If( scroll_end, push_save.eq(1), scroll_active.eq(0), # These happen on any write to the frame buffer #prev_horiz.eq(horiz), #prev_vert.eq(vert), #prev_char.eq(dout), prev_start.eq(scroll_start), ), If( fb_r, If((scroll_read & (scroll_sequential | ~scroll_active)) | (repeat_active & repeat_sequential), # A faithful 6502 model issues a read of the target # address before the write cycle of an indirect store # instruction. Do nothing if we suspect the current read is # actually part of a store instruction. ). Else( scroll_read.eq(1), read_horiz.eq(horiz), read_vert.eq(vert), # TODO read_char should be din on the next clock cycle # read_char.eq(dout), ), ), # Write to the frame buffer: remember the location and character # that generate the sequential and repeat signals which are used # by the scroll and clear functions. Also, update scroll signals. If( fb_w, scroll_read.eq(0), prev_vert.eq(vert), prev_horiz.eq(horiz), prev_char.eq(dout), # Repeat - Mostly needed for screen clearing operations but made # generic to conserve bandwidth and allow any character to be # repeated. If( repeat_match & repeat_sequential, # Supress output, begin sequence if not started already # Store location and character as this will be needed if the # following write is not sequential # Setting repeat is redundant if already active repeat_active.eq(1), ).Elif( repeat_active & ~repeat_sequential, # The cursor moved and we must terminate repeat mode # indicating the last character in the sequence. This is # required whether or not the same character is present. # Output saved location with Repeat flag set to mark end. # Then output current signal set on next cycle push_save.eq(1), prev_start.eq(scroll_start), repeat_active.eq(0), ).Else( # Push current character on stack either because: # a. character is different breaking repeat # b. character is different preventing repeat # c. location is not sequential breaking repeat # d. location is not sequential preventing repeat # Cases a,c need to clear repeat. This is irrelevant for b,d repeat_active.eq(0), ), ), # We can safely use the cycle after a write to frame memory as a # second push into the character fifo knowing that the only time the # 6502 has two consecutive write cycles is the JSR instruction which # writes the return address onto the stack, and the RMW instructions # INC, DEC, LSR, ASR, ROL, ROR which write the original and the new # values in two consecutive cycles. It is extremely poor programming # practice to keep the stack inside the frame buffer while clearing # or scrolling the screen so no special handling of these cases is # taken. If( push_save, # Auto-clear after one clock cycle push_save.eq(0), ), ]
def __init__(self, platform, with_sdram_bist=True, bist_async=True, spiflash="spiflash", **kwargs): clk_freq = int(100e6) SoCSDRAM.__init__(self, platform, clk_freq, integrated_rom_size=0x8000, integrated_sram_size=0x8000, ident="Arty LiteX Test SoC", ident_version=True, with_uart=False, **kwargs) self.submodules.crg = CRG(platform) self.submodules.dna = dna.DNA() self.submodules.xadc = xadc.XADC() uart_interfaces = [RS232PHYInterface() for i in range(2)] self.submodules.uart = UART(uart_interfaces[0]) self.submodules.bridge = WishboneStreamingBridge( uart_interfaces[1], self.clk_freq) self.add_wb_master(self.bridge.wishbone) self.submodules.uart_phy = RS232PHY(platform.request("serial"), self.clk_freq, 115200) self.submodules.uart_multiplexer = RS232PHYMultiplexer( uart_interfaces, self.uart_phy) self.comb += self.uart_multiplexer.sel.eq( platform.request("user_sw", 0)) self.crg.cd_sys.clk.attr.add("keep") self.platform.add_period_constraint(self.crg.cd_sys.clk, period_ns(100e6)) # self.submodules.leds = led.ClassicLed(Cat(platform.request("user_led", i) # for i in range(4))) # self.submodules.rgb_led0 = led.RGBLed(platform.request("rgb_led", 0)) # self.submodules.rgb_led1 = led.RGBLed(platform.request("rgb_led", 1)) # self.submodules.rgb_led2 = led.RGBLed(platform.request("rgb_led", 2)) # self.submodules.rgb_led3 = led.RGBLed(platform.request("rgb_led", 3)) # sdram self.submodules.ddrphy = a7ddrphy.A7DDRPHY(platform.request("ddram")) sdram_module = MT41K128M16(self.clk_freq, "1:4") self.register_sdram( self.ddrphy, sdram_module.geom_settings, sdram_module.timing_settings, controller_settings=ControllerSettings(cmd_buffer_depth=8)) # sdram bist if with_sdram_bist: generator_user_port = self.sdram.crossbar.get_port( mode="write", clock_domain="clk50" if bist_async else "sys") self.submodules.generator = LiteDRAMBISTGenerator( generator_user_port) checker_user_port = self.sdram.crossbar.get_port( mode="read", clock_domain="clk50" if bist_async else "sys") self.submodules.checker = LiteDRAMBISTChecker(checker_user_port) # spi flash spiflash_pads = platform.request(spiflash) spiflash_pads.clk = Signal() self.specials += Instance("STARTUPE2", i_CLK=0, i_GSR=0, i_GTS=0, i_KEYCLEARB=0, i_PACK=0, i_USRCCLKO=spiflash_pads.clk, i_USRCCLKTS=0, i_USRDONEO=1, i_USRDONETS=1) spiflash_dummy = { "spiflash": 9, "spiflash4x": 11, } self.submodules.spiflash = spi_flash.SpiFlash( spiflash_pads, dummy=spiflash_dummy[spiflash], div=2) self.add_constant("SPIFLASH_PAGE_SIZE", 256) self.add_constant("SPIFLASH_SECTOR_SIZE", 0x10000) self.add_wb_slave(mem_decoder(self.mem_map["spiflash"]), self.spiflash.bus) self.add_memory_region("spiflash", self.mem_map["spiflash"] | self.shadow_base, 16 * 1024 * 1024)