
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Thu Apr 16 09:26:49 EEST 2026

  32-bit RISCV ISA CPU core which supports integer (I), multiplication,
  division (M), ZB, A, and CSR instructions (Z) extensions (RV32IMZicsr).
  Cpu has also a simple MMU unit.

  Core is tested in FPGA with uart, SPI and timer peripherals.
  Two setups are used:
    - core with tightly coupled memory (default with 64KW dual-port RAM)
    - core with instruction and data cache (configurable cache sizes and ways)
      External memory interface uses AXI4 bus

  Example setups for Arria 10 device (10AX022C4U19E3SG) and Gidel board
  (Stratix II device EP2S130F1020C5) are in directory fpga


  Directories:
     rtl/          - riscv soc hdl codes in VHDL
     sim/          - Modelsim simulation scripts
     fpga/         - Altera (Intel) FPGA sysnthesis scripts
     sw/           - software upload script (.elf), linux/bare metal images



  References:
     https://github.com/ultraembedded/riscv
     https://github.com/ultraembedded/riscv_soc

     https://github.com/ultraembedded/riscv32_linux_from_scratch
     https://github.com/ultraembedded/riscv-linux
     https://github.com/ultraembedded/busybox
     https://github.com/ultraembedded/riscv-linux-prebuilt
     https://github.com/ultraembedded/riscv-linux-boot


- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

  RTL DIRECTORY FILES:

      rtl
      |-- core
      |   |-- rv_alu.vhd
      |   |-- rv_cpu.vhd
      |   |-- rv_csr.vhd
      |   |-- rv_csr_rf.vhd
      |   |-- rv_decode.vhd
      |   |-- rv_decoder.vhd
      |   |-- rv_divider.vhd
      |   |-- rv_exec.vhd
      |   |-- rv_fetch.vhd
      |   |-- rv_issue.vhd
      |   |-- rv_lsu.vhd
      |   |-- rv_mmu.vhd
      |   |-- rv_mmu_basic.vhd
      |   |-- rv_multiplier.vhd
      |   |-- rv_pipe_ctrl.vhd
      |   |-- rv_pkg.vhd
      |   `-- rv_regfile.vhd
      |-- dbg
      |   |-- dbg_bridge.vhd
      |   |-- dbg_bridge_fifo.vhd
      |   `-- dbg_bridge_uart.vhd
      |-- fpga
      |   |-- rv_ddr2_fpga.vhd
      |   `-- rv_tcm_fpga.vhd
      |-- soc
      |   |-- dma.vhd
      |   |-- rv_if.vhd
      |   |-- rv_soc.vhd
      |   |-- rv_soc_tcm.vhd
      |   |-- uart16550
      |   |   |-- uart16550.vhd
      |   |   |-- uart_pkg.vhd
      |   |   |-- uart_receiver.vhd
      |   |   |-- uart_rfifo.vhd
      |   |   |-- uart_tfifo.vhd
      |   |   `-- uart_transmitter.vhd
      |   |-- vsgpio.vhd
      |   |-- vsirq_ctrl.vhd
      |   |-- vsperips.vhd
      |   |-- vsspi_lite.vhd
      |   |-- vstimer.vhd
      |   `-- vsuart_lite.vhd
      |-- tb
      |   |-- axi_sram.vhd
      |   |-- linux_riscv_soc.elf.mif
      |   `-- rv_soc_tb.vhd
      |-- top_cache
      |   |-- axi4_arb.vhd
      |   |-- axi4_retime.vhd
      |   |-- axi_mem_if.vhd
      |   |-- axi_wrapper_rom.vhd
      |   |-- dcachew.vhd
      |   |-- icachew.vhd
      |   |-- memories.vhd
      |   `-- rv_core.vhd
      `-- top_tcm
          |-- rv_tcm.vhd
          |-- tcm_axi.vhd
          `-- tcm_mem.vhd




- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
RISCV CPU CONFIGURATION PARAMETERS:


   riscv cpu hierarcy :
      rv_pkg               (configuration/parameters file)
      rv_cpu                :  /u_cpu
      |--rv_fetch           :  /u_cpu/u_fetch
      |--rv_decode          :  /u_cpu/u_decode
      |   |--rv_decoder     :  /u_cpu/u_decode/u_dec
      |--rv_issue           :  /u_cpu/u_issue
      |   |--rv_pipe_ctrl   :  /u_cpu/u_issue/u_pipe_ctrl
      |   |--rv_regfile     :  /u_cpu/u_issue/u_regfile
      |--rv_exec            :  /u_cpu/u_exec
      |   |--rv_alu         :  /u_cpu/u_exec/u_alu
      |   |--rv_multiplier  :  /u_cpu/u_exec/u_mul
      |   |--rv_divider     :  /u_cpu/u_exec/u_div
      |--rv_lsu             :  /u_cpu/u_lsu
      |--rv_csr             :  /u_cpu/u_csr
      |   |--rv_csr_rf      :  /u_cpu/u_csr/u_csr_rf
      |--rv_mmu             :  /u_cpu/u_mmu


entity rv_cpu is
  generic ( BOOT_ADDR      : slv_31_00 := X"80000000";
            CPU_ID         : slv_31_00 := X"00000000";  -- hardware thread ID
            CACHE_ADDR_L   : slv_31_00 := X"80000000";
            CACHE_ADDR_H   : slv_31_00 := X"8FFFFFFF";
            --
            RISCV_M         : sl_t := '1';   -- RV mul / div extension
            RISCV_A         : sl_t := '1';   -- amo extension
            RISCV_E         : sl_t := '0';   -- RV rf embedded extension
            RISCV_S_U       : sl_t := '1';   -- supervisor/user privilege levels
            RISCV_Zba       : sl_t := '1';   -- address generation (shXadd)
            RISCV_ZB        : sl_t := '1';   -- ZB-extension + Zicond
--          RISCV_I         : sl_t := '1';   -- always enabled when no RISCV_E !
--          RISCV_Zicsr     : sl_t := '1';   -- always enabled !
--          RISCV_Zifencei  : sl_t := '1';   -- always enabled !
            --
            SUPPORT_MMU     : sl_t := '1' ); -- enable simple sv32 MMU


- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
INSTRUCTION / DATA CACHE CONFIGURATION PARAMETERS:

  Cache implementation is set associative

  Cache has three parameters to set its configuration:
     WAYS        : natural range 1 to 8  := 2;   -- Nro of ways 1,2,4,8
     LINE_ADDR_W : natural range 6 to 12 := 8;   -- Line address
     LINE_SIZE_W : natural range 2 to 8  := 5 ); -- Line size (bytes !)


     - Number of ways can be set to 1, 2, 4 or 8
     - Number of lines is set with LINE_ADDR_W           (2^LINE_ADDR_W)
     - Number of bytes in line is set with LINE_SIZE_W   (2^LINE_SIZE_W)

  Default configuration is (2, 8, 5) i.e. 2-way cache, 2^8 = 256 lines and
  2^5 = 32 bytes on line. 
  
  Instruction and data cache size is 2 * 256 * 32 = 16384 bytes
 (total 32KB or 8KW each)

  Axi bus width can be selected with  AXIDATA_W to be either 32b or 64b.


- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
RISCV SOC WITH TIGHTLY COUPLED MEMORY:

   rv_soc_tcm
   |
   |--dbg_bridge                   : /u_dbg_bridge
   |  |--dbg_bridge_uart           : /u_dbg_bridge/u_uart
   |  |--dbg_bridge_fifo           : /u_dbg_bridge/u_fifo_tx
   |  |--dbg_bridge_fifo           : /u_dbg_bridge/u_fifo_rx
   |  
   |--vsperips                     : /u_vsperips
   |  |--vsirq_ctrl                : /u_vsperips/u_vsirq_ctrl
   |  |--vstimer                   : /u_vsperips/u_vstimer
   |  |--vsuart_lite               : /u_vsperips/u_vsuart_lite
   |  |--vsspi_lite                : /u_vsperips/u_vsspi_lite
   |  |--vsgpio                    : /u_vsperips/u_vsgpio
   |  |--uart16550                 : /u_vsperips/u_uart16550
   |     |--uart_pkg                    (configuration/parameters file)
   |     |--uart_transmitter       : /u_vsperips/u_uart16550/transmitter
   |     |  |--uart_tfifo          : /u_vsperips/u_uart16550/transmitter/fifo_tx
   |     |--uart_receiver          : /u_vsperips/u_uart16550/receiver
   |        |--uart_rfifo          : /u_vsperips/u_uart16550/receiver/fifo_rx
   |      
   |--rv_tcm                       : /u_rv_tcm
      |--tcm_mem                   : /u_rv_tcm/u_tcm_mem
      |  |--tcm_ram                : /u_rv_tcm/u_tcm_ram
      |  |--tcm_axi                : /u_rv_tcm/u_tcm_mem/u_conv
      |     |--tcm_mem_pmem_fifo2  : /u_rv_tcm/u_tcm_mem/u_conv/u_requests
      |     |--tcm_mem_pmem_fifo2  : /u_rv_tcm/u_tcm_mem/u_conv/u_response
      |
      |--rv_cpu                    : /u_rv_tcm/u_cpu
         |--rv_pkg                      (configuration/parameters file)
         |--rv_fetch               : /u_rv_tcm/u_cpu/u_fetch
         |--rv_decode              : /u_rv_tcm/u_cpu/u_decode
         |   |--rv_decoder         : /u_rv_tcm/u_cpu/u_decode/u_dec
         |--rv_issue               : /u_rv_tcm/u_cpu/u_issue
         |   |--rv_pipe_ctrl       : /u_rv_tcm/u_cpu/u_issue/u_pipe_ctrl
         |   |--rv_regfile         : /u_rv_tcm/u_cpu/u_issue/u_regfile
         |--rv_exec                : /u_rv_tcm/u_cpu/u_exec
         |   |--rv_alu             : /u_rv_tcm/u_cpu/u_exec/u_alu
         |   |--rv_multiplier      : /u_rv_tcm/u_cpu/u_exec/u_mul
         |   |--rv_divider         : /u_rv_tcm/u_cpu/u_exec/u_div
         |--rv_lsu                 : /u_rv_tcm/u_cpu/u_lsu
         |--rv_csr                 : /u_rv_tcm/u_cpu/u_csr
         |   |--rv_csr_rf          : /u_rv_tcm/u_cpu/u_csr/u_csr_rf
         |--rv_mmu                 : /u_rv_tcm/u_cpu/u_mmu



   FPGA:

      rv_tcm_fpga
      |
      |--pll24M576_50M_50M         : /u_pll
      |
      |--rv_soc_tcm                : /u_rv_soc_tcm
      |
      |--iopad                     : /u7_iopad
      |--iopad                     : /u6_iopad
      |--iopad                     : /u5_iopad
      |--iopad                     : /u4_iopad
      |--iopad                     : /u3_iopad
      |--iopad                     : /u2_iopad
      |--iopad                     : /u1_iopad
      |--iopad                     : /u0_iopad


   Set system clock and uart speed at file rtl/fpga/rv_tcm_fpga.vhd
     generic map ( CLK_FREQ    => 50000000,    -- default 50M
                   UART_SPEED  =>  1000000,    -- default 1M
                   NR_GPIOS    => 8 )
   Here 50MHz system clock is used and 1M uart speed
   The 50MHz clock is generated with Arria 10 PLL IP

   FPGA uses dual-port RAM IP. Its size can be changed by changing
   component:
     u_ram_2p : ram_2p
   in file
     rtl/top_tcm/tcm_mem.vhd

   For simulation a behavioral model is used. Its size can be changed
   with a generic  RAM_WORDS in file rtl/top_tcm/rv_tcm.vhd

   entity rv_tcm is
     generic (
       RAM_WORDS     : natural range 2**10 to 2**20 := 2**16;  -- RAM in words
       --
       BOOT_ADDR     : slv_31_00 := X"80000000";
       CPU_ID        : slv_31_00 := X"00000000";
       CACHE_ADDR_L  : slv_31_00 := X"80000000";
       CACHE_ADDR_H  : slv_31_00 := X"8FFFFFFF";
       --
       RISCV_M       : std_logic := '1';    -- RV mul / div extension
       RISCV_E       : std_logic := '0';    -- RV rf embedded extension
       RISCV_S_U     : std_logic := '1' );  -- supervisor/user privilege levels


   Used Arria 10 IPs:
     - PLL to generate 50MHz clock : fpga/pll24M576_50M_50M.qsys
     - 64KW dual-port RAM          : fpga/ram_2p.qsys

      FPGA board has 24.576MHz clock input


- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
RISCV SOC WITH CACHES :
 
   rv_soc
   |
   |--dbg_bridge                : /u_dbg_bridge
   |  |--dbg_bridge_uart        : /u_dbg_bridge/u_uart
   |  |--dbg_bridge_fifo        : /u_dbg_bridge/u_fifo_tx
   |  |--dbg_bridge_fifo        : /u_dbg_bridge/u_fifo_rx
   |  
   |--vsperips                  : /u_vsperips
   |  |--vsirq_ctrl             : /u_vsperips/u_vsirq_ctrl
   |  |--vstimer                : /u_vsperips/u_vstimer
   |  |--vsuart_lite            : /u_vsperips/u_vsuart_lite
   |  |--vsspi_lite             : /u_vsperips/u_vsspi_lite
   |  |--vsgpio                 : /u_vsperips/u_vsgpio
   |  |--uart16550              : /u_vsperips/u_uart16550
   |     |--uart_pkg                    (configuration/parameters file)
   |     |--uart_transmitter    : /u_vsperips/u_uart16550/transmitter
   |     |  |--uart_tfifo       : /u_vsperips/u_uart16550/transmitter/fifo_tx
   |     |--uart_receiver       : /u_vsperips/u_uart16550/receiver
   |        |--uart_rfifo       : /u_vsperips/u_uart16550/receiver/fifo_rx
   |
   |--axi_mem_if                : /u_axi_mem_if
   |  |--axi4_arb               : /u_axi_mem_if/u_arb
   |  |  |--axi4_arb_onehot4    : /u_axi_mem_if/u_arb/u_rd_arb
   |  |  |--axi4_arb_onehot4    : /u_axi_mem_if/u_arb/u_wr_arb
   |  |--axi4_retime            : /u_axi_mem_if/u_retime
   |      
   |--rv_core                   : /u_core
      |
      |--icachew                : /u_core/u_icache
      |  |--ram_itag            : /u_core/u_icache/u_tag0
      |  |--ram_itag            : /u_core/u_icache/u_tag1
      |  |--ram_idata           : /u_core/u_icache/u_data0
      |  |--ram_idata           : /u_core/u_icache/u_data1
      |
      |--dcachew                : /u_core/u_dcache
      |  |--ram_dtag            : /u_core/u_dcache/u_tag0
      |  |--ram_dtag            : /u_core/u_dcache/u_tag1
      |  |--ram_ddata           : /u_core/u_dcache/u_data0
      |  |--ram_ddata           : /u_core/u_dcache/u_data1
      |
      |--rv_cpu                 : /u_core/u_cpu
         |--rv_pkg                   (configuration/parameters file)
         |--rv_fetch            : /u_rv_tcm/u_cpu/u_fetch
         |--rv_decode           : /u_rv_tcm/u_cpu/u_decode
         |   |--rv_decoder      : /u_rv_tcm/u_cpu/u_decode/u_dec
         |--rv_issue            : /u_rv_tcm/u_cpu/u_issue
         |   |--rv_pipe_ctrl    : /u_rv_tcm/u_cpu/u_issue/u_pipe_ctrl
         |   |--rv_regfile      : /u_rv_tcm/u_cpu/u_issue/u_regfile
         |--rv_exec             : /u_rv_tcm/u_cpu/u_exec
         |   |--rv_alu          : /u_rv_tcm/u_cpu/u_exec/u_alu
         |   |--rv_multiplier   : /u_rv_tcm/u_cpu/u_exec/u_mul
         |   |--rv_divider      : /u_rv_tcm/u_cpu/u_exec/u_div
         |--rv_lsu              : /u_rv_tcm/u_cpu/u_lsu
         |--rv_csr              : /u_rv_tcm/u_cpu/u_csr
         |   |--rv_csr_rf       : /u_rv_tcm/u_cpu/u_csr/u_csr_rf
         |--rv_mmu              : /u_rv_tcm/u_cpu/u_mmu



   FPGA:

      rv_ddr2_fpga
      |
      |--axi_ddr2     : /axi_ddr2_i0          (FPGA axi-ddr2 IP)
      |
      |--rv_soc       : /u_rv_soc

      FPGA board has 50MHz clock input

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
