Exemple #1
0
    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)
Exemple #2
0
    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
Exemple #3
0
        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))
            ]
Exemple #4
0
    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 __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)
Exemple #6
0
 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,
     )
Exemple #7
0
    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)),
        ]
Exemple #8
0
 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,
     )
Exemple #9
0
 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, 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
                                  )
Exemple #12
0
    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()
Exemple #13
0
    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,
                 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
                                  )
Exemple #15
0
        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,
            )
Exemple #16
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)
    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)
Exemple #18
0
        def __init__(self, platform):
            clk12_raw = platform.request("clk12")
            clk18 = Signal()

            self.clock_domains.cd_sys = ClockDomain()
            self.comb += self.cd_sys.clk.eq(clk18)

            platform.add_period_constraint(clk12_raw, 1e9/12e6)  # this is fixed and comes from external crystal

            # POR reset logic- POR generated from sys clk, POR logic feeds sys clk
            # reset. Just need a pulse one cycle wide to get things working right.
            # ^^^ this line is a lie. I have found devices that do not reliably reset with
            # one pulse. Extending the pulse to 2 wide seems to fix the issue.
            self.clock_domains.cd_por = ClockDomain()
            reset_cascade = Signal(reset=1)
            reset_cascade2 = Signal(reset=1)
            reset_initiator = Signal()
            self.sync.por += [
                reset_cascade.eq(reset_initiator),
                reset_cascade2.eq(reset_cascade),
            ]
            self.comb += [
                self.cd_por.clk.eq(self.cd_sys.clk),
                self.cd_sys.rst.eq(reset_cascade2),
            ]

            # generate a >1us-wide pulse at ~1Hz based on sysclk for display extcomm signal
            # count down from 12e6 to 0 so that first extcomm pulse comes after lcd_disp is high
            # note: going to a 25-bit counter makes this the critical path at speeds > 12 MHz, so stay with
            # 24 bits but a faster extcomm clock.
            extcomm = platform.request("extcommin", 0)
            extcomm_div = Signal(24, reset=int(12e6)) # datasheet range is 0.5Hz - 5Hz, so actual speed is 1.5Hz
            self.sync += [
                If(extcomm_div == 0,
                   extcomm_div.eq(int(12e6))
                ).Else(
                   extcomm_div.eq(extcomm_div - 1)
                ),

                If(extcomm_div < 13,
                   extcomm.eq(1)
                ).Else(
                   extcomm.eq(0)
                )
            ]
            self.comb += platform.request("lcd_disp", 0).eq(1)  # force display on for now

            ### WATCHDOG RESET, uses the extcomm_div divider to save on gates
            self.watchdog = CSRStorage(17, fields=[
                CSRField("reset_code", size=16, description="Write `600d` then `c0de` in sequence to this register to reset the watchdog timer"),
                CSRField("enable", description="Enable the watchdog timer. Cannot be disabled once enabled, except with a reset. Notably, a watchdog reset will disable the watchdog.", reset=0),
            ])
            wdog_enabled=Signal(reset=0)
            self.sync += [
                If(self.watchdog.fields.enable,
                    wdog_enabled.eq(1)
                ).Else(
                    wdog_enabled.eq(wdog_enabled)
                )
            ]
            wdog_cycle_r = Signal()
            wdog_cycle = Signal()
            self.sync += wdog_cycle_r.eq(extcomm)
            self.comb += wdog_cycle.eq(extcomm & ~wdog_cycle_r)
            wdog = FSM(reset_state="IDLE")
            self.submodules += wdog
            wdog.act("IDLE",
                If(wdog_enabled,
                    NextState("WAIT_ARM")
                )
            )
            wdog.act("WAIT_ARM",
                # sync up to the watchdog cycle so we give ourselves a full cycle to disarm the watchdog
                If(wdog_cycle,
                    NextState("ARMED")
                )
            )
            wdog.act("ARMED",
                If(wdog_cycle,
                    self.cd_sys.rst.eq(1),
                ),
                If(self.watchdog.re,
                    If(self.watchdog.fields.reset_code == 0x600d,
                        NextState("DISARM1")
                    )
                )
            )
            wdog.act("DISARM1",
                If(wdog_cycle,
                    self.cd_sys.rst.eq(1),
                ),
                If(self.watchdog.re,
                    If(self.watchdog.fields.reset_code == 0xc0de,
                       NextState("DISARMED")
                    ).Else(
                       NextState("ARMED")
                    )
                )
            )
            wdog.act("DISARMED",
                If(wdog_cycle,
                    NextState("ARMED")
                )
            )


            # make an 18 MHz clock for the SPI bus controller
            self.specials += Instance(
                "SB_PLL40_PAD",
                # Parameters
                p_DIVR = 0,
                p_DIVF = 47,
                p_DIVQ = 5,
                p_FILTER_RANGE = 1,
                p_FEEDBACK_PATH = "SIMPLE",
                p_DELAY_ADJUSTMENT_MODE_FEEDBACK = "FIXED",
                p_FDA_FEEDBACK = 0,
                p_DELAY_ADJUSTMENT_MODE_RELATIVE = "FIXED",
                p_FDA_RELATIVE = 0,
                p_SHIFTREG_DIV_MODE = 1,
                p_PLLOUT_SELECT = "GENCLK",
                p_ENABLE_ICEGATE = 0,
                # IO
                i_PACKAGEPIN = clk12_raw,
                o_PLLOUTGLOBAL = clk18,   # from PLL
                i_BYPASS = 0,
                i_RESETB = 1,
            )
            # global buffer for input SPI clock
            self.clock_domains.cd_spi_peripheral = ClockDomain()
            clk_spi_peripheral = Signal()
            self.comb += self.cd_spi_peripheral.clk.eq(clk_spi_peripheral)
            clk_spi_peripheral_pin = platform.request("com_sclk")

            self.specials += Instance(
                "SB_GB",
                i_USER_SIGNAL_TO_GLOBAL_BUFFER=clk_spi_peripheral_pin,
                o_GLOBAL_BUFFER_OUTPUT=clk_spi_peripheral,
            )
            platform.add_period_constraint(clk_spi_peripheral_pin, 1e9/20e6)  # 20 MHz according to Artix betrusted-soc config

            # Add a period constraint for each clock wire.
            # NextPNR picks the clock domain's name randomly from one of the wires
            # that it finds in the domain.  Migen passes the information on timing
            # to NextPNR in a file called `top_pre_pack.py`.  In order to ensure
            # it chooses the timing for this net, annotate period constraints for
            # all wires.
            platform.add_period_constraint(clk_spi_peripheral, 1e9/20e6)
            platform.add_period_constraint(clk18, 1e9/sysclkfreq)
            platform.add_period_constraint(self.cd_por.clk, 1e9/sysclkfreq)
Exemple #19
0
    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()
Exemple #20
0
    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),
                ),
            ]
Exemple #21
0
    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),
                ))
        ]
Exemple #22
0
    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):
        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)
Exemple #24
0
    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")
Exemple #25
0
    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(),
        )
Exemple #26
0
    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")),
            ]
Exemple #27
0
    def __init__(self, platform, pads, size=16 * 1024 * 1024):
        self.size = size

        self.bus = bus = wishbone.Interface()

        self.reset = Signal()

        self.cfg1 = CSRStorage(fields=[
            CSRField(
                "bb_out", size=4, description="Output bits in bit-bang mode"),
            CSRField("bb_clk",
                     description="Serial clock line in bit-bang mode"),
            CSRField("bb_cs", description="Chip select line in bit-bang mode"),
        ])
        self.cfg2 = CSRStorage(fields=[
            CSRField("bb_oe",
                     size=4,
                     description="Output Enable bits in bit-bang mode"),
        ])
        self.cfg3 = CSRStorage(fields=[
            CSRField(
                "rlat", size=4, description="Read latency/dummy cycle count"),
            CSRField("crm", description="Continuous Read Mode enable bit"),
            CSRField("qspi", description="Quad-SPI enable bit"),
            CSRField("ddr", description="Double Data Rate enable bit"),
        ])
        self.cfg4 = CSRStorage(fields=[
            CSRField(
                "memio",
                offset=7,
                reset=1,
                description=
                "Enable memory-mapped mode (set to 0 to enable bit-bang mode)")
        ])

        self.stat1 = CSRStatus(fields=[
            CSRField(
                "bb_in", size=4, description="Input bits in bit-bang mode"),
        ])
        self.stat2 = CSRStatus(8, description="Reserved")
        self.stat3 = CSRStatus(8, description="Reserved")
        self.stat4 = CSRStatus(8, description="Reserved")

        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:4]),
            self.stat2.status.eq(0),
            self.stat3.status.eq(0),
            self.stat4.status.eq(0),
        ]

        reset = Signal()

        mosi_pad = TSTriple()
        miso_pad = TSTriple()
        cs_n_pad = TSTriple()
        clk_pad = TSTriple()
        wp_pad = TSTriple()
        hold_pad = TSTriple()

        clk = Signal()
        if hasattr(pads, "clk"):
            clk = pads.clk
            self.specials += clk_pad.get_tristate(clk)
            self.comb += clk_pad.oe.eq(~reset)
        else:
            self.specials += Instance("USRMCLK", i_USRMCLKI=clk, i_USRMCLKTS=0)

        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 += wp_pad.get_tristate(pads.wp)
        self.specials += hold_pad.get_tristate(pads.hold)

        self.comb += [
            reset.eq(ResetSignal() | self.reset),
            cs_n_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,
            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")
Exemple #28
0
    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,
        )
Exemple #29
0
    def __init__(self, platform, pads, size=2*1024*1024):
        self.intro = ModuleDoc("See https://github.com/cliffordwolf/picorv32/tree/master/picosoc#spi-flash-controller-config-register; used with modifications")
        self.size = size

        self.bus = bus = wishbone.Interface()

        self.reset = Signal()

        cfg = Signal(32)
        cfg_we = Signal(4)
        cfg_out = Signal(32)

        # Add pulse the cfg_we line after reset
        reset_counter = Signal(2, reset=3)
        ic_reset = Signal(reset=1)
        self.sync += \
            If(reset_counter != 0,
                reset_counter.eq(reset_counter - 1)
            ).Else(
                ic_reset.eq(0)
            )

        self.rdata = CSRStatus(fields=[
            CSRField("data", size=4, description="Data bits from SPI [3:hold, 2:wp, 1:cipo, 0:copi]"),
        ])
        self.mode = CSRStorage(fields=[
            CSRField("bitbang", size=1, description="Turn on bitbang mode", reset = 0),
            CSRField("csn", size=1, description="Chip select (set to `0` to select the chip)"),
        ])
        self.wdata = CSRStorage(description="Writes to this field automatically pulse CLK", fields=[
            CSRField("data", size=4, description="Data bits to SPI [3:hold, 2:wp, 1:cipo, 0:copi]"),
            CSRField("oe", size=4, description="Output enable for data pins"),
        ])
        bb_clk = Signal()
        self.sync += [
            bb_clk.eq(self.wdata.re), # auto-clock the SPI chip whenever wdata is written. Delay a cycle for setup/hold.
        ]

        copi_pad = TSTriple()
        cipo_pad = TSTriple()
        cs_n_pad = TSTriple()
        clk_pad  = TSTriple()
        wp_pad   = TSTriple()
        hold_pad = TSTriple()
        self.specials += copi_pad.get_tristate(pads.copi)
        self.specials += cipo_pad.get_tristate(pads.cipo)
        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 = copi_pad.oe,
            o_flash_io1_oe = cipo_pad.oe,
            o_flash_io2_oe = wp_pad.oe,
            o_flash_io3_oe = hold_pad.oe,

            o_flash_io0_do = copi_pad.o,
            o_flash_io1_do = cipo_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 = copi_pad.i,
            i_flash_io1_di = cipo_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_bb_oe = self.wdata.fields.oe,
            i_bb_wd = self.wdata.fields.data,
            i_bb_clk = bb_clk,
            i_bb_csb = self.mode.fields.csn,
            o_bb_rd = self.rdata.fields.data,
            i_config_update = self.mode.re | ic_reset,
            i_memio_enable = ~self.mode.fields.bitbang,
        )
        platform.add_source("rtl/spimemio.v")
Exemple #30
0
    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(),
        )