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)
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")
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)
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"} ), ]