Exemple #1
0
    def __init__(self, platform, spiboot=False, **kwargs):
        Sim.__init__(self,
                     platform,
                     custom_clocks=local_clocks,
                     spiboot=spiboot,
                     **kwargs)  # SoC magic is in here

        # LCD interface
        self.submodules.memlcd = memlcd.MemLCD(platform.request("lcd"))
        self.add_csr("memlcd")
        self.register_mem("memlcd",
                          self.mem_map["memlcd"],
                          self.memlcd.bus,
                          size=self.memlcd.fb_depth * 4)

        # external SRAM for testing the build system
        self.submodules.sram_ext = sram_32.SRAM32(platform.request("sram"),
                                                  rd_timing=7,
                                                  wr_timing=6,
                                                  page_rd_timing=2)
        self.add_csr("sram_ext")
        self.register_mem("sram_ext",
                          self.mem_map["sram_ext"],
                          self.sram_ext.bus,
                          size=0x1000000)
Exemple #2
0
    def __init__(self, platform, **kwargs):
        SoCCore.__init__(self, platform, sim_config["sys_clk_freq"],
                         integrated_rom_size=0x8000,
                         integrated_sram_size=0x20000,
                         ident="betrusted.io LiteX Base SoC",
                         cpu_type="vexriscv",
                         **kwargs)

        self.add_constant("COM_SIMULATION", 1) # add extra COM commands to BIOS
        self.add_constant("SIMULATION", 1)

        # instantiate the clock module
        self.submodules.crg = CRG(platform, sim_config)
        self.platform.add_period_constraint(self.crg.cd_sys.clk, 1e9/sim_config["sys_clk_freq"])

        self.platform.add_platform_command(
            "create_clock -name clk12 -period 83.3333 [get_nets clk12]")

        # SPI interface
        self.submodules.spimaster = spi.SPIMaster(platform.request("com"))
        self.add_csr("spimaster")

        self.submodules.spislave = spi.SPISlave(platform.request("slave"))
        self.add_csr("spislave")

        # external SRAM to make BIOS build happy
        self.submodules.sram_ext = sram_32.SRAM32(platform.request("sram"), rd_timing=7, wr_timing=6, page_rd_timing=2)
        self.add_csr("sram_ext")
        self.register_mem("sram_ext", self.mem_map["sram_ext"],
                  self.sram_ext.bus, size=0x1000000)
    def __init__(self, platform, **kwargs):
        SoCCore.__init__(self,
                         platform,
                         sim_config["sys_clk_freq"],
                         integrated_rom_size=0x8000,
                         integrated_sram_size=0x20000,
                         ident="betrusted.io LiteX Base SoC",
                         cpu_type="vexriscv",
                         **kwargs)

        kwargs["cpu_reset_address"] = self.mem_map["spiflash"] + boot_offset
        self.submodules.reboot = WarmBoot(
            self, reset_vector=kwargs["cpu_reset_address"])
        self.add_csr("reboot")
        warm_reset = Signal()
        self.comb += warm_reset.eq(self.reboot.do_reset)
        self.cpu.cpu_params.update(
            i_externalResetVector=self.reboot.addr.storage)

        self.add_constant("SIMULATION", 1)
        self.add_constant("SPIFLASH_SIMULATION", 1)

        # instantiate the clock module
        self.submodules.crg = CRG(platform, sim_config)
        self.add_csr("crg")
        # self.platform.add_period_constraint(self.crg.cd_sys.clk, 1e9/sim_config["sys_clk_freq"])

        self.platform.add_platform_command(
            "create_clock -name clk12 -period 83.3333 [get_nets clk12]")

        # external SRAM to make BIOS build happy
        self.submodules.sram_ext = sram_32.SRAM32(platform.request("sram"),
                                                  rd_timing=7,
                                                  wr_timing=6,
                                                  page_rd_timing=2)
        self.add_csr("sram_ext")
        self.register_mem("sram_ext",
                          self.mem_map["sram_ext"],
                          self.sram_ext.bus,
                          size=0x1000000)

        # spi control -- that's the point of this simulation!
        SPI_FLASH_SIZE = 128 * 1024 * 1024
        sclk_instance_name = "SCLK_ODDR"
        iddr_instance_name = "SPI_IDDR"
        miso_instance_name = "MISO_FDRE"
        self.submodules.spinor = spinor.SpiOpi(platform.request("spiflash_8x"),
                                               sclk_name=sclk_instance_name,
                                               iddr_name=iddr_instance_name,
                                               miso_name=miso_instance_name,
                                               sim=True)
        platform.add_source(
            "../../gateware/spimemio.v"
        )  ### NOTE: this actually doesn't help for SIM, but it reminds us to scroll to the bottom of this file and add it to the xvlog imports
        self.register_mem("spiflash",
                          self.mem_map["spiflash"],
                          self.spinor.bus,
                          size=SPI_FLASH_SIZE)
        self.add_csr("spinor")
Exemple #4
0
    def __init__(self, platform, spiboot=False, **kwargs):
        Sim.__init__(self, platform, custom_clocks=local_clocks, spiboot=spiboot, **kwargs) # SoC magic is in here

        # external SRAM
        self.submodules.sram_ext = sram_32.SRAM32(platform.request("sram"), rd_timing=7, wr_timing=6, page_rd_timing=6)
        self.add_csr("sram_ext")
        self.register_mem("sram_ext", self.mem_map["sram_ext"],
                  self.sram_ext.bus, size=0x1000000)
Exemple #5
0
    def __init__(self, platform, **kwargs):
        SoCCore.__init__(self,
                         platform,
                         sim_config["sys_clk_freq"],
                         integrated_rom_size=0x8000,
                         integrated_sram_size=0x20000,
                         ident="betrusted.io LiteX Base SoC",
                         cpu_type="vexriscv",
                         **kwargs)

        self.add_constant("SIMULATION", 1)
        self.add_constant("KBD_SIMULATION", 1)

        # instantiate the clock module
        self.submodules.crg = CRG(platform, sim_config)
        self.platform.add_period_constraint(self.crg.cd_sys.clk,
                                            1e9 / sim_config["sys_clk_freq"])

        self.platform.add_platform_command(
            "create_clock -name clk12 -period 83.3333 [get_nets clk12]")

        # Keyboard module
        self.submodules.keyboard = ClockDomainsRenamer(
            cd_remapping={"kbd": "lpclk"})(keyboard.KeyScan(
                platform.request("kbd")))
        self.add_csr("keyboard")
        self.add_interrupt("keyboard")

        # external SRAM to make BIOS build happy
        self.submodules.sram_ext = sram_32.SRAM32(platform.request("sram"),
                                                  rd_timing=7,
                                                  wr_timing=6,
                                                  page_rd_timing=2)
        self.add_csr("sram_ext")
        self.register_mem("sram_ext",
                          self.mem_map["sram_ext"],
                          self.sram_ext.bus,
                          size=0x1000000)

        self.clock_domains.cd_lpclk = ClockDomain()
        self.comb += self.cd_lpclk.clk.eq(platform.request("lpclk"))
    def __init__(self, platform, sys_clk_freq=int(100e6), spiflash="spiflash_1x", **kwargs):
        assert sys_clk_freq in [int(12e6), int(100e6)]

        # CPU cluster
        ## For dev work, we're booting from SPI directly. However, for enhanced security
        ## we will eventually want to move to a bitstream-ROM based bootloader that does
        ## a signature verification of the external SPI code before running it. The theory is that
        ## a user will burn a random AES key into their FPGA and encrypt their bitstream to their
        ## unique AES key, creating a root of trust that offers a defense against trivial patch attacks.

        # SoCCore ----------------------------------------------------------------------------------
        SoCCore.__init__(self, platform, sys_clk_freq, csr_data_width=8,
            integrated_rom_size  = 0,
            integrated_sram_size = 0x20000,
            ident                = "betrusted.io LiteX Base SoC",
            cpu_type             = "vexriscv",
            #cpu_variant="linux+debug",  # this core doesn't work, but left for jogging my memory later on if I need to try it
            **kwargs)

        # CPU --------------------------------------------------------------------------------------
        self.cpu.use_external_variant("gateware/cpu/VexRiscv_BetrustedSoC_Debug.v")
        self.cpu.add_debug()
        self.add_memory_region("rom", 0, 0) # Required to keep litex happy
        kwargs["cpu_reset_address"] = self.mem_map["spiflash"]+boot_offset
        self.submodules.reboot = WarmBoot(self, reset_vector=kwargs["cpu_reset_address"])
        self.add_csr("reboot")
        warm_reset = Signal()
        self.comb += warm_reset.eq(self.reboot.do_reset)
        self.cpu.cpu_params.update(i_externalResetVector=self.reboot.addr.storage)

        # Debug cluster ----------------------------------------------------------------------------
        from litex.soc.cores.uart import UARTWishboneBridge
        self.submodules.uart_bridge = UARTWishboneBridge(platform.request("debug"), sys_clk_freq, baudrate=115200)
        self.add_wb_master(self.uart_bridge.wishbone)
        self.register_mem("vexriscv_debug", 0xe00f0000, self.cpu.debug_bus, 0x100)

        # Clockgen cluster -------------------------------------------------------------------------
        self.submodules.crg = CRG(platform, sys_clk_freq, spinor_edge_delay_ns=2.2)
        self.add_csr("crg")
        self.comb += self.crg.warm_reset.eq(warm_reset)

        # Info -------------------------------------------------------------------------------------
        # XADC analog interface---------------------------------------------------------------------

        from litex.soc.cores.xadc import analog_layout
        analog_pads = Record(analog_layout)
        analog = platform.request("analog")
        self.comb += [
            # NOTE - if part is changed to XC7S25, the pin-to-channel mappings change
            analog_pads.vauxp.eq(Cat(analog.noise0,       # 0
                                     Signal(7, reset=0),  # 1,2,3,4,5,6,7
                                     analog.noise1, analog.vbus_div, analog.usbc_cc1, analog.usbc_cc2, # 8,9,10,11
                                     Signal(4, reset=0),  # 12,13,14,15
                                )),
            analog_pads.vauxn.eq(Cat(analog.noise0_n, Signal(15, reset=0))), # PATCH
            analog_pads.vp.eq(analog.ana_vp),
            analog_pads.vn.eq(analog.ana_vn),
        ]
        self.submodules.info = info.Info(platform, self.__class__.__name__, analog_pads)
        self.add_csr("info")
        self.platform.add_platform_command('create_generated_clock -name dna_cnt -source [get_pins {{betrustedsoc_dna_cnt_reg[0]/Q}}] -divide_by 2 [get_pins {{DNA_PORT/CLK}}]')

        # External SRAM ----------------------------------------------------------------------------
        # Note that page_rd_timing=2 works, but is a slight overclock on RAM. Cache fill time goes from 436ns to 368ns for 8 words.
        self.submodules.sram_ext = sram_32.SRAM32(platform.request("sram"), rd_timing=7, wr_timing=6, page_rd_timing=3)  # this works with 2:nbits page length with Rust firmware...
        #self.submodules.sram_ext = sram_32.SRAM32(platform.request("sram"), rd_timing=7, wr_timing=6, page_rd_timing=5)  # this worked with 3:nbits page length in C firmware
        self.add_csr("sram_ext")
        self.register_mem("sram_ext", self.mem_map["sram_ext"], self.sram_ext.bus, size=0x1000000)
        # A bit of a bodge -- the path is actually async, so what we are doing is trying to constrain intra-channel skew by pushing them up against clock limits
        self.platform.add_platform_command("set_input_delay -clock [get_clocks sys_clk] -min -add_delay 4.0 [get_ports {{sram_d[*]}}]")
        self.platform.add_platform_command("set_input_delay -clock [get_clocks sys_clk] -max -add_delay 9.0 [get_ports {{sram_d[*]}}]")
        self.platform.add_platform_command("set_output_delay -clock [get_clocks sys_clk] -min -add_delay 0.0 [get_ports {{sram_adr[*] sram_d[*] sram_ce_n sram_oe_n sram_we_n sram_zz_n sram_dm_n[*]}}]")
        self.platform.add_platform_command("set_output_delay -clock [get_clocks sys_clk] -max -add_delay 3.0 [get_ports {{sram_adr[*] sram_d[*] sram_ce_n sram_oe_n sram_we_n sram_zz_n sram_dm_n[*]}}]")
        # ODDR falling edge ignore
        self.platform.add_platform_command("set_false_path -fall_from [get_clocks sys_clk] -through [get_ports {{sram_d[*] sram_adr[*] sram_ce_n sram_oe_n sram_we_n sram_zz_n sram_dm_n[*]}}]")
        self.platform.add_platform_command("set_false_path -fall_to [get_clocks sys_clk] -through [get_ports {{sram_d[*]}}]")
        self.platform.add_platform_command("set_false_path -fall_from [get_clocks sys_clk] -through [get_nets betrustedsoc_sram_ext_load]")
        self.platform.add_platform_command("set_false_path -fall_to [get_clocks sys_clk] -through [get_nets betrustedsoc_sram_ext_load]")
        self.platform.add_platform_command("set_false_path -rise_from [get_clocks sys_clk] -fall_to [get_clocks sys_clk]")  # sort of a big hammer but should be OK
        # reset ignore
        self.platform.add_platform_command("set_false_path -through [get_nets sys_rst]")
        # relax OE driver constraint (it's OK if it is a bit late, and it's an async path from fabric to output so it will be late)
        self.platform.add_platform_command("set_multicycle_path 2 -setup -through [get_pins betrustedsoc_sram_ext_sync_oe_n_reg/Q]")
        self.platform.add_platform_command("set_multicycle_path 1 -hold -through [get_pins betrustedsoc_sram_ext_sync_oe_n_reg/Q]")

        # LCD interface ----------------------------------------------------------------------------
        self.submodules.memlcd = memlcd.MemLCD(platform.request("lcd"))
        self.add_csr("memlcd")
        self.register_mem("memlcd", self.mem_map["memlcd"], self.memlcd.bus, size=self.memlcd.fb_depth*4)

        # COM SPI interface ------------------------------------------------------------------------
        self.submodules.com = spi.SPIMaster(platform.request("com"))
        self.add_csr("com")
        # 20.83ns = 1/2 of 24MHz clock, we are doing falling-to-rising timing
        # up5k tsu = -0.5ns, th = 5.55ns, tpdmax = 10ns
        # in reality, we are measuring a Tpd from the UP5K of 17ns. Routed input delay is ~3.9ns, which means
        # the fastest clock period supported would be 23.9MHz - just shy of 24MHz, with no margin to spare.
        # slow down clock period of SPI to 20MHz, this gives us about a 4ns margin for setup for PVT variation
        self.platform.add_platform_command("set_input_delay -clock [get_clocks spi_clk] -min -add_delay 0.5 [get_ports {{com_miso}}]") # could be as low as -0.5ns but why not
        self.platform.add_platform_command("set_input_delay -clock [get_clocks spi_clk] -max -add_delay 17.5 [get_ports {{com_miso}}]")
        self.platform.add_platform_command("set_output_delay -clock [get_clocks spi_clk] -min -add_delay 6.0 [get_ports {{com_mosi com_csn}}]")
        self.platform.add_platform_command("set_output_delay -clock [get_clocks spi_clk] -max -add_delay 16.0 [get_ports {{com_mosi com_csn}}]")  # could be as large as 21ns but why not
        # cross domain clocking is handled with explicit software barrires, or with multiregs
        self.platform.add_false_path_constraints(self.crg.cd_sys.clk, self.crg.cd_spi.clk)
        self.platform.add_false_path_constraints(self.crg.cd_spi.clk, self.crg.cd_sys.clk)

        # I2C interface ----------------------------------------------------------------------------
        self.submodules.i2c = i2c.RTLI2C(platform, platform.request("i2c", 0))
        self.add_csr("i2c")
        self.add_interrupt("i2c")

        # Event generation for I2C and COM ---------------------------------------------------------
        self.submodules.btevents = BtEvents(platform.request("com_irq", 0), platform.request("rtc_irq", 0))
        self.add_csr("btevents")
        self.add_interrupt("btevents")

        # Messible for debug -----------------------------------------------------------------------
        self.submodules.messible = messible.Messible()
        self.add_csr("messible")

        # Tick timer -------------------------------------------------------------------------------
        self.submodules.ticktimer = ticktimer.TickTimer(sys_clk_freq/1000)
        self.add_csr("ticktimer")

        # Power control pins -----------------------------------------------------------------------
        self.submodules.power = BtPower(platform.request("power"))
        self.add_csr("power")

        # SPI flash controller ---------------------------------------------------------------------
        legacy_spi = False
        if legacy_spi:
            self.submodules.spinor = spinor.SPINOR(platform, platform.request("spiflash_1x"), size=SPI_FLASH_SIZE)
        else:
            sclk_instance_name="SCLK_ODDR"
            iddr_instance_name="SPI_IDDR"
            miso_instance_name="MISO_FDRE"
            self.submodules.spinor = spinor.SpiOpi(platform.request("spiflash_8x"),
                    sclk_name=sclk_instance_name, iddr_name=iddr_instance_name, miso_name=miso_instance_name)
            # reminder to self: the {{ and }} overloading is because Python treats these as special in strings, so {{ -> { in actual constraint
            # NOTE: ECSn is deliberately not constrained -- it's more or less async (0-10ns delay on the signal, only meant to line up with "block" region

            # constrain DQS-to-DQ input DDR delays
            self.platform.add_platform_command("create_clock -name spidqs -period 10 [get_ports spiflash_8x_dqs]")
            self.platform.add_platform_command("set_input_delay -clock spidqs -max 0.6 [get_ports {{spiflash_8x_dq[*]}}]")
            self.platform.add_platform_command("set_input_delay -clock spidqs -min -0.6 [get_ports {{spiflash_8x_dq[*]}}]")
            self.platform.add_platform_command("set_input_delay -clock spidqs -max 0.6 [get_ports {{spiflash_8x_dq[*]}}] -clock_fall -add_delay")
            self.platform.add_platform_command("set_input_delay -clock spidqs -min -0.6 [get_ports {{spiflash_8x_dq[*]}}] -clock_fall -add_delay")

            # derive clock for SCLK - clock-forwarded from DDR see Xilinx answer 62488 use case #4
            self.platform.add_platform_command("create_generated_clock -name spiclk_out -multiply_by 1 -source [get_pins {}/Q] [get_ports spiflash_8x_sclk]".format(sclk_instance_name))
            # if using CCLK output and not DDR forwarded clock, these are the commands used to define the clock
            #self.platform.add_platform_command("create_generated_clock -name spiclk_out -source [get_pins STARTUPE2/USRCCLKO] -combinational [get_pins STARTUPE2/USRCCLKO]")
            #self.platform.add_platform_command("set_clock_latency -min 0.5 [get_clocks spiclk_out]")  # define the min/max delay of the STARTUPE2 buffer
            #self.platform.add_platform_command("set_clock_latency -max 7.5 [get_clocks spiclk_out]")

            # constrain MISO SDR delay -- WARNING: -max is 'actually' 5.0ns, but design can't meet timing @ 5.0 tPD from SPIROM. There is some margin in the timing closure tho, so 4.5ns is probably going to work....
            self.platform.add_platform_command("set_input_delay -clock [get_clocks spiclk_out] -clock_fall -max 4.5 [get_ports spiflash_8x_dq[1]]")
            self.platform.add_platform_command("set_input_delay -clock [get_clocks spiclk_out] -clock_fall -min 1 [get_ports spiflash_8x_dq[1]]")
            # corresponding false path on MISO DDR input when clocking SDR data
            self.platform.add_platform_command("set_false_path -from [get_clocks spiclk_out] -to [get_pin {}/D ]".format(iddr_instance_name + "1"))
            # corresponding false path on MISO SDR input from DQS strobe
            self.platform.add_platform_command("set_false_path -from [get_clocks spidqs] -to [get_pin {}/D ]".format(miso_instance_name))

            # constrain CLK-to-DQ output DDR delays; MOSI uses the same rules
            self.platform.add_platform_command("set_output_delay -clock [get_clocks spiclk_out] -max 1 [get_ports {{spiflash_8x_dq[*]}}]")
            self.platform.add_platform_command("set_output_delay -clock [get_clocks spiclk_out] -min -1 [get_ports {{spiflash_8x_dq[*]}}]")
            self.platform.add_platform_command("set_output_delay -clock [get_clocks spiclk_out] -max 1 [get_ports {{spiflash_8x_dq[*]}}] -clock_fall -add_delay")
            self.platform.add_platform_command("set_output_delay -clock [get_clocks spiclk_out] -min -1 [get_ports {{spiflash_8x_dq[*]}}] -clock_fall -add_delay")
            # constrain CLK-to-CS output delay. NOTE: timings require one dummy cycle insertion between CS and SCLK (de)activations. Not possible to meet timing for DQ & single-cycle CS due to longer tS/tH reqs for CS
            self.platform.add_platform_command("set_output_delay -clock [get_clocks spiclk_out] -min -1 [get_ports spiflash_8x_cs_n]") # -3 in reality
            self.platform.add_platform_command("set_output_delay -clock [get_clocks spiclk_out] -max 1 [get_ports spiflash_8x_cs_n]")  # 4.5 in reality
            # unconstrain OE path - we have like 10+ dummy cycles to turn the bus on wr->rd, and 2+ cycles to turn on end of read
            self.platform.add_platform_command("set_false_path -through [ get_pins betrustedsoc_spiopi_dq_mosi_oe_reg/Q ]")
            self.platform.add_platform_command("set_false_path -through [ get_pins betrustedsoc_spiopi_dq_oe_reg/Q ]")

        self.register_mem("spiflash", self.mem_map["spiflash"], self.spinor.bus, size=SPI_FLASH_SIZE)
        self.add_csr("spinor")

        # Keyboard module --------------------------------------------------------------------------
        self.submodules.keyboard = ClockDomainsRenamer(cd_remapping={"kbd":"lpclk"})(keyboard.KeyScan(platform.request("kbd")))
        self.add_csr("keyboard")
        self.add_interrupt("keyboard")

        # GPIO module ------90f63ac2678aed36813c9ecb1de9a245b7ef137a------------------------------------------------------------------------
        self.submodules.gpio = BtGpio(platform.request("gpio"))
        self.add_csr("gpio")
        self.add_interrupt("gpio")

        # Build seed -------------------------------------------------------------------------------
        self.submodules.seed = BtSeed()
        self.add_csr("seed")

        # ROM test ---------------------------------------------------------------------------------
        self.submodules.romtest = RomTest(platform)
        self.add_csr("romtest")

        # Ring Oscillator TRNG ---------------------------------------------------------------------
        self.submodules.trng_osc = TrngRingOsc(platform, target_freq=1e6)
        self.add_csr("trng_osc")
        # ignore ring osc paths
        self.platform.add_platform_command("set_false_path -through [get_nets betrustedsoc_trng_osc_ena]")
        self.platform.add_platform_command("set_false_path -through [get_nets betrustedsoc_trng_osc_ring_ccw_0]")
        self.platform.add_platform_command("set_false_path -through [get_nets betrustedsoc_trng_osc_ring_cw_1]")
        # MEMO: diagnostic option, need to turn off GPIO
        # gpio_pads = platform.request("gpio")
        # self.comb += gpio_pads[0].eq(self.trng_osc.trng_fast)
        # self.comb += gpio_pads[1].eq(self.trng_osc.trng_slow)
        # self.comb += gpio_pads[2].eq(self.trng_osc.trng_raw)

        # AES block --------------------------------------------------------------------------------
        #self.submodules.aes = Aes(platform)
        #self.add_csr("aes")

        ## TODO: audio, wide-width/fast SPINOR

        # Lock down both ICAPE2 blocks -------------------------------------------------------------
        # this attempts to make it harder to partially reconfigure a bitstream that attempts to use
        # the ICAP block. An ICAP block can read out everything inside the FPGA, including key ROM,
        # even when the encryption fuses are set for the configuration stream.
        platform.toolchain.attr_translate["icap0"] = ("LOC", "ICAP_X0Y0")
        platform.toolchain.attr_translate["icap1"] = ("LOC", "ICAP_X0Y1")
        self.specials += [
            Instance("ICAPE2", i_I=0, i_CLK=0, i_CSIB=1, i_RDWRB=1,
                     attr={"KEEP", "DONT_TOUCH", "icap0"}
                     ),
            Instance("ICAPE2", i_I=0, i_CLK=0, i_CSIB=1, i_RDWRB=1,
                     attr={"KEEP", "DONT_TOUCH", "icap1"}
                     ),
        ]