nanoFOX - a simple RISC-V compatible kernel

    A small introduction:


    The idea of ​​writing your own core appeared after passing a school-seminar on digital circuitry in the city of Tomsk . At this event, they were introduced to the current hardware description languages ​​(Verilog HDL and VHDL), as well as to the small schoolMIPS processor core. To understand the structure of the cores, it was decided to invent their own bike, following the path of development of schoolMIPS, but taking another command system as a basis. Due to the growing popularity of RISC-V and the openness of its command system (MIPS did not have an open command system at the time the kernel was written), a set of RISC-V instructions, namely RV32I, was chosen for the development of the future kernel. RV32I has a small set of basic instructions (37 excluding special ones) and, if desired, can be expanded, for example, by adding integer multiplication and division instructions (RV32M) or support for compressed instructions (RV32C). Also, this project was conceived as educational, so it was decided to maximize the visibility of the kernel to effectively demonstrate its work.


    By analogy with schoolMIPS, the following kernel versions were implemented:


    1. Single-cycle version (00_simple_risc_v_cpu).
    2. A single-cycle version with support for lw / sw instructions (load word / store word) (01_simple_risc_v_cpu_lwsw).
    3. Conveyor version (5-stage conveyor) (02_pipe_risc_v_cpu).

    Currently, the next kernel version (03_pipe_risc_v_cpu_fc) with the full set of RV32I commands (without taking into account some special ones) is being described.


    Brief information:


    In the course of the kernel description, ways to improve the visibility of work, debugging, and verification were thought out. The following methods are currently implemented:


    1. Adding a debug text VGA module (for two single-cycle kernel branches). The inclusion of this module allows you to simultaneously track the value of 32 registers on the monitor screen, which is not possible when using the output of information on seven-segment indicators. In the figures presented below, the kernel calculates Leonardo numbers and displays information on the corresponding debugging module;


      hex_display and DebugScreenCore

      Information output to seven-segment indicators: Information output to a VGA display:image
      image


    2. Adding messages to the simulator terminal about the status of the register file and currently executing instructions. This method allows you to better analyze the operation of the kernel in the early stages of development, but is not always convenient;


      Terminal

      Initialization of the register file: Change the value of sp:image
      image


    3. Adding string variables to waveform with the display of executable instructions. Using these string variables, the developer can track the correct setting of control signals at all stages of the pipeline;


      Waveform

      Initialization of the register file: Changing the value of sp:image
      image


    4. Adding the ability to write debugging information about the state of the kernel in a text file. The status of the register file is presented in a table form, and the instruction / instructions currently executed by the kernel are also indicated. It is an analogue of 2 points, but allows more manipulations with the information received;


      Text file

      Initialization of the register file: Changing the value of sp:image
      image


    5. Adding the ability to write kernel state debugging information to an HTML file. The status of the register file is presented in tabular form with notes about changing the values ​​of the cells, as well as instructions that are currently executed by the kernel are displayed. It is an analogue of paragraphs 2 and 4, but in addition to them it allows you to conveniently indicate a change in data. As you can see in the pictures below, if the register value was not defined, then the registers are highlighted in red (registers s0 / fp - t6). On cycle 17, the value of the register s0 / fp changes and the cell is highlighted in green.
      On cycle 41, the value 0x00010000 is loaded into the sp register.


      HTML file

      Initialization of the register file: Changing the value of sp:image
      image



    Comparison of kernel branches:

    Currently supported kernel instructions for different branches:


    Instruction manual00_simple_risc_v_cpu01_simple_risc_v_cpu_lwsw02_pipe_risc_v_cpu
    add+++
    and--+
    sll--+
    or+++
    addi+++
    ori--+
    slli+++
    lw-++
    jalr--+
    lui+++
    beq+++
    bne--+
    sw-++
    jal--+
    sub++-

    Peripherals Supported:


    Periphery00_simple_risc_v_cpu01_simple_risc_v_cpu_lwsw02_pipe_risc_v_cpu
    RAM-++
    Pwm-++
    GPIO-++
    UART--+

    Supported languages ​​for writing programs:


    Tongue00_simple_risc_v_cpu01_simple_risc_v_cpu_lwsw02_pipe_risc_v_cpu
    Assembler+++
    C--+

    Required FPGA resources for the kernel (nf_cpu):


    EP4CE22F17C6 (de0_nano):


    01_simple_risc_v_cpu_lwsw02_pipe_risc_v_cpu03_pipe_risc_v_cpu_fc
    Total memory bits0 / 608,256 (0%)2,048 / 608,256 (<1%)2,144 / 608,256 (<1%)
    Total logic elements3.645 / 22.320 (16%)1,739 / 22,320 (8%)2,058 / 22,320 (9%)
    Total combinational functions2.653 / 22.320 (12%)1,472 / 22,320 (7%)1,838 / 22,320 (8%)
    Dedicated logic registers1,055 / 22,320 (5%)575 / 22,320 (3%)606 / 22,320 (3%)

    10M50DAF484C7G (de10_lite):


    00_simple_risc_v_cpu01_simple_risc_v_cpu_lwsw02_pipe_risc_v_cpu03_pipe_risc_v_cpu_fc
    Total memory bits0 / 1,677,312 (0%)0 / 1,677,312 (0%)2,048 / 1,677,312 (<1%)2,144 / 1,677,312 (<1%)
    Total logic elements2,851 / 49,760 (6%)2,881 / 49,760 (6%)1,629 / 49,760 (3%)1.927 / 49.760 (4%)
    Total combinational functions2.613 / 49.760 (5%)2.653 / 49.760 (5%)1,473 / 49,760 (3%)1,849 / 49,760 (4%)
    Dedicated logic registers1,055 / 49,760 (2%)1,055 / 49,760 (2%)575 / 49,760 (1%)606 / 49,760 (1%)

    Project development.


    What is planned to be done in the future:


    1. add all RV32I instructions (at the description stage);
    2. implement debugging;
    3. add a DMA (DMA) controller;
    4. add support for other tires AXI, Avalon, Wishbone;
    5. add cache (cache) memory;
    6. integrate various peripherals (SPI, TWI (I2C), Ethernet (10 base-t));
    7. add interrupt controller;
    8. port different versions to other debug boards;
    9. add other methods to increase the visibility of the kernel;
    10. starting RTOS, for example zephyr .

    Recommendations and suggestions for the development of the kernel are also accepted.


    Link to repository: nanoFOX .

    Only registered users can participate in the survey. Please come in.

    What is better to disclose in the following articles?

    • 48.6% Detailed examination of individual kernel branches; 18
    • 56.7% Assembler RISC-V; 21
    • 40.5% Building programs for the kernel; fifteen
    • 54% Initial kernel verification; 20
    • 35.1% Start of projects for simulation; thirteen
    • 29.7% Launch of synthesis projects; eleven
    • 5.4% Other (write in the comments). 2

    Also popular now: