example_riscv_asic_simplified:example_asic_simplified:example_riscv_simplified:example_simplified:example_riscv_asic:example_asic:example_riscv:example
This walkthough is one of a number which help to illustrate the principles of RISC-V SoC design:
Standard: | Simplified: |
---|---|
ASIC example with software customisation | ASIC example with hardware customisation <= |
FPGA example | FPGA example with hardware customisation |
Altera FPGA example | Altera FPGA example with hardware customisation |
While the three standard versions include examples of custom interface hardware typical of a System-on-Chip design, the three simplified versions include non-specific input and output ports in the manner of a microcontroller system. While the use of custom interface hardware is likely to yield better results (if it doesn't yield better results you will probably be better off using a microcontroller rather than an SoC), the use of non-specific input and output ports can aid understanding and are used here as a starting point for the design of custom interface hardware.
There is also an ARM version for those interested in
alternative architectures.
A very simple RISC-V System on Chip has been designed:
The secondary images are an artefact of the partial address decoding which only uses
the top 4 address bits (HADDR[31:28]) in order to decide which slave is being accessed.
In order to build the RISC-V SoC, we need SystemVerilog files to model the hardware plus
'C' program files and other support files to build the software.
Further files are required to support simulation:
Running the appropriate make commands in the software directory:
Note that you can generate "code.hex", "code.vmem" and "code.lst" files at the
same time using the following make command:
(The xmverilog command to run the simulation is:
You are looking for three regions: Although the stack may be sparsely used (there are likely to be unused XXXXXXXX locations in the stack), it should still be possible to identify the larger area of unused memory between the globals and the stack. The key to system-on-chip design is the creation of custom interface
hardware.
A modified ARM System on Chip including a simple custom interface is to be designed:
The file name for the interface should be ahb_custom_interface.sv
and it should be placed in the existing behavioural/ directory.
A template for the custom interface can be found here:
ahb_custom_interface.sv
You will need to take the template and fill in the code where it is missing.
You can base the code that you enter on the code from the output port module:
ahb_output_port.sv.
Since the custom interface supports more than one address, you will need to add code
to generate a word_address signal during the address phase.
An example of this sort of code can be found in this example module:
ahb_switches.sv
The file name for the top-level module should be soc_custom.sv
and it should be placed in the existing behavioural/ directory.
You can base the new module on the existing SoC module code:
soc.sv.
Changes that you should make are:
Since this new slave will have the highest base address, the new signals will need to be added at the left
(most significant) end of each signal bus concatenation. Thus:
The testbench/ directory already includes a
soc_custom_stim.sv testbench
file to test the new system.
The command to use is:
If all goes well, the behaviour of the new system will match that of the old one
since the the 'C' program is unchanged (there are no memory accesses for the custom slave).
Now modify the 'C' program to access the other registers in the custom interface.
Changes that you should make are:
After each change you should recompile the code then re-run
the simulation and check that the new behaviour is as you expect.
Having completed this lab walkthrough, you should have a basic understanding
of SoC design including an ability to build a simple custom interface
and write a 'C' program to access the interface.
At this stage you can experiment with other changes to the
system but you should try to make only small changes between
simulations to increase the chances of being able to debug
the system.
Iain McNally
Overview of a Simple RISC-V SoC
16K bytes for program memory
512 bytes for data memory (including stack)
Occupying one 32-bit memory location
Occupying one 32-bit memory locationMemory Map
Files
Preparation
mkdir -p ~/design/system_on_chip/example_riscv_asic_simplified
cd ~/design/system_on_chip/example_riscv_asic_simplified
init_riscv_soc_asic_simplified_example -here
Compile C Program
cd software
make clean
make code.vmem
should create a Verilog hex format file named "code.hex"
which could be used in simulation but not in ASIC synthesis and a "code.vmem" version of the same hex data which is better suited to ASIC synthesis.
make code.lst
Examining the "code.lst" file in a text editor can be very helpful when trying to debug a system-on-chip
design in simulation.
make all
Simulate RISC-V SoC
cd ..
./simulate &
xmverilog +gui +access+r \
+tcl+testbench/soc.tcl \
-y behavioural +libext+.sv \
+define+prog_file_vmem=software/code.vmem \
testbench/soc_stim.sv
but it's easier to use the simulate script)
Note that because the stack grows downwards, the higher memory addresses
are used before the lower ones.
Create a custom interface
{HSEL_OPORT,HSEL_IPORT, ...
will become:
{HSEL_CUSTOM,HSEL_OPORT,HSEL_IPORT, ...
./simulate testbench/soc_custom_stim.sv &
// Define the raw base address value for the custom interface
#define AHB_CUSTOM_BASE 0x60000000
// Define a pointer with correct type for access to 32-bit registers
//
// The the four registers in the interface can then be accessed as:
// CUSTOM_REGS[0]
// CUSTOM_REGS[1]
// CUSTOM_REGS[2]
// CUSTOM_REGS[3]
volatile uint32_t* CUSTOM_REGS = (volatile uint32_t*) AHB_CUSTOM_BASE;
10-8-2023