Source code for luna_soc.gateware.cpu.vexriscv

#
# This file is part of LUNA.
#
# Copyright (c) 2023-2025 Great Scott Gadgets <info@greatscottgadgets.com>
# SPDX-License-Identifier: BSD-3-Clause

import os
import logging

from amaranth             import *
from amaranth.lib.wiring  import Component, In, Out

from amaranth_soc         import wishbone
from amaranth_soc.periph  import ConstantMap

__all__ = ["VexRiscv"]


# Variants --------------------------------------------------------------------

CPU_VARIANTS = {
    "cynthion":      "vexriscv_cynthion",
    "cynthion+jtag": "vexriscv_cynthion+jtag",
    "imac+dcache":   "vexriscv_imac+dcache",
    "imc":           "vexriscv_imc",
}

JTAG_VARIANTS = [ "cynthion+jtag" ]

# - VexRiscv ------------------------------------------------------------------

[docs] class VexRiscv(Component): name = "vexriscv" arch = "riscv" byteorder = "little" data_width = 32 def __init__(self, variant="imac+dcache", reset_addr=0x00000000): self._variant = variant self._reset_addr = reset_addr super().__init__({ "ext_reset": In(unsigned(1)), "irq_external": In(unsigned(32)), "irq_timer": In(unsigned(1)), "irq_software": In(unsigned(1)), "ibus": Out(wishbone.Signature( addr_width=30, data_width=32, granularity=8, features=("err", "cti", "bte") )), "dbus": Out(wishbone.Signature( addr_width=30, data_width=32, granularity=8, features=("err", "cti", "bte") )), "jtag_tms": In(unsigned(1)), "jtag_tdi": In(unsigned(1)), "jtag_tdo": Out(unsigned(1)), "jtag_tck": In(unsigned(1)), "dbg_reset": In(unsigned(1)), "ndm_reset": In(unsigned(1)), "stop_time": In(unsigned(1)), }) # read source verilog if not variant in CPU_VARIANTS: raise ValueError(f"unsupported variant: {variant}") self._source_file = f"{CPU_VARIANTS[variant]}.v" self._source_path = os.path.join(os.path.dirname(__file__), "verilog", "vexriscv", self._source_file) if not os.path.exists(self._source_path): FileNotFoundError(f"Verilog source file not found: {self._source_path}") with open(self._source_path, "r") as f: logging.info(f"reading verilog file: {self._source_path}") self._source_verilog = f.read() @property def reset_addr(self): return self._reset_addr
[docs] def elaborate(self, platform): m = Module() # optional signals optional_signals = {} if self._variant in JTAG_VARIANTS: optional_signals = { "i_jtag_tms": self.jtag_tms, "i_jtag_tdi": self.jtag_tdi, "o_jtag_tdo": self.jtag_tdo, "i_jtag_tck": self.jtag_tck, "i_debugReset": self.dbg_reset, "o_ndmreset": self.ndm_reset, "o_stoptime": self.stop_time, } # instantiate VexRiscv platform.add_file(self._source_file, self._source_verilog) self._cpu = Instance( "VexRiscv", # clock and reset i_clk = ClockSignal("sync"), i_reset = ResetSignal("sync") | self.ext_reset, i_externalResetVector = Const(self._reset_addr, unsigned(32)), # interrupts i_externalInterruptArray = self.irq_external, i_timerInterrupt = self.irq_timer, i_softwareInterrupt = self.irq_software, # instruction bus o_iBusWishbone_ADR = self.ibus.adr, o_iBusWishbone_DAT_MOSI = self.ibus.dat_w, o_iBusWishbone_SEL = self.ibus.sel, o_iBusWishbone_CYC = self.ibus.cyc, o_iBusWishbone_STB = self.ibus.stb, o_iBusWishbone_WE = self.ibus.we, o_iBusWishbone_CTI = self.ibus.cti, o_iBusWishbone_BTE = self.ibus.bte, i_iBusWishbone_DAT_MISO = self.ibus.dat_r, i_iBusWishbone_ACK = self.ibus.ack, i_iBusWishbone_ERR = self.ibus.err, # data bus o_dBusWishbone_ADR = self.dbus.adr, o_dBusWishbone_DAT_MOSI = self.dbus.dat_w, o_dBusWishbone_SEL = self.dbus.sel, o_dBusWishbone_CYC = self.dbus.cyc, o_dBusWishbone_STB = self.dbus.stb, o_dBusWishbone_WE = self.dbus.we, o_dBusWishbone_CTI = self.dbus.cti, o_dBusWishbone_BTE = self.dbus.bte, i_dBusWishbone_DAT_MISO = self.dbus.dat_r, i_dBusWishbone_ACK = self.dbus.ack, i_dBusWishbone_ERR = self.dbus.err, # optional signals **optional_signals, ) m.submodules.vexriscv = self._cpu return m