Instructor: KUNAL GHOSH
- Our first task is to refer to given videos on C-program based lab and RISCV based lab.
- We have to execute both the tasks in the terminal.
- Compilers we use are GCC and RISC GCC compiler.
-> First,make sure you are in the home directory
-> Open the terminal and enter the command:  
-> The program is as shown in the above image.
-> Now, to check the output, run the commands :
> "gcc sum.c"
> "./a.out"
-> It is as shown in the image.Just use ./a.out whenever we want to give input
- We are going to use the same program but with RISCV GCC compiler.
- We have to run the command: Â Â " cat sum.c ".
- It will display us the program we have written earlier on the terminal.
- To compile the program, we are going to use riscv64 gcc compiler.
- write the command:
 " riscv64-unknown-elf-gcc -o1 -mabi=lp64 -march=rv64i -o -sum.o -sum.c "
- Now run the command in new tab in the terminal:
 " riscv64-unknown-elf-objdump -d sum.o "
-> It shows the Assembly language program of our C program.
-> To search for "main" we have to first run the command:
 "riscv64-unknown-elf-objdump -d sum.o | less"
-> To search for main, enter "/main" as shown in the image.
-> Now, we can see the Assembly code for main function.
-> We can see that there are 41 instructions.
- Text Editor (gedit) is the default GUI text editor in the Ubuntu operating system.
- It is UTF-8 compatible and supports most standard text editor features as well as many advanced features.
- GCC stands for “GNU Compiler Collection”.
- GCC is an integrated distribution of compilers for several major programming languages.
- These languages currently include C, C++, Objective-C, Objective-C++, Fortran, Ada, D, and Go.
- The cat (concatenate) command in Linux displays file contents.
- It reads one or multiple files and prints their content to the terminal.
- cat is used to view file contents, combine files, and create new files.
- "riscv64-unknown-elf-gcc" is a cross compiler that target the bare-metal.
- It does not need the operating system.
- This is suitable when you are developing a software and want to run directly on hardware without OS.
- It uses "newlib", a C library designed for embedded systems
- This is to specify that the ABI (Application Binary Interface) we use is lp64 (64-bit long,pointer integer).
- Used for 64-bit RISCV architecture.
- This specifies that we are using 64-bit RISCV base integer instruction set.
- It can be used to disassemble RISCV binaries and helps in debugging.
- It greatly increase compilation time but optimizes the generated code by reducing its size.
- Other options are =>
-> o0 : no optimization.
-> o2 : More optimization than o1.
-> o3 : More optimization than o2.
-> os : enables all o2 optimizationsthat do not typically increase code size.
-> ofast : optimiztion flag used to instruct compiler to optimize generated code for maximum speed.
- Our second task is to perform "SPIKE" simulation and Debugging.
- Spike is used as simulator for RISC-V ISA.It is a free open-source C++ Simulator.
- In this task we are going to show that gcc compiler and riscv compiler.
- To compile in gcc compiler,we use : Â "gcc sum.c"
- To compile in riscv compiler,we use : Â "spike pk sum.c"
- From above picture,we can see "spike -d pk sum.c". It is to open the debugger mode.
- We can see the object file in above picture.
- We run the debugger with "until pc 0 100b0". It is to run the "Program Counter(PC)" from address 0 to 100b0.
- We can see the instruction lui a0,0x2b.Here,"lui" means " Load Upper Immediate"
- To see the register content, we are going to use : " reg 0 register_name ".
- We can see "addi sp,sp,-32". Here "addi" means "add immediate".
- All these instructions will be explored further in upcoming tasks.
- We can see that at first " Stack Pointer(sp) " has the value of "3ffffffb50".After that it became "3ffffffb30" by adding "-32".
- Here, we are using hexadecimal convention. So, in decimal convetion it is "-32" but in hexadecimal convention it is "-20".
- We can also use the debugger to check remaining instructions too.
- In this task, we are going to learn about different types of instruction formats in RISC-V.
- There are 6 types of instruction formats as shown below.
- Here, "opcode" represents a 7-bit instruction operator code, its role is to distinguish between different instructions.
- "funct3" represents a 3-bit function code.it is an additional opcode.
- "funct7" represents a 7-bit function code, which can help distinguish different kinds of instructions.
- "rs1" and "rs2" represent two 5-bit source registers.
- "rd" is a 5-bit destination register, and the result of the instruction operation is stored in rd.
- "imm" represents an immediate number of different lengths, which can be used directly as an operand.
-> It is a 32-bit instruction format.
-> These instructions use 3 register inputs.
-> Two registers are used as source operands (rs1 and rs2).
-> One desination register (rd).
-> Arithmetic and logical instructions comes under this format. Ex: add,xor,mul etc.
-> Arithmetic and logical operations between registers.
-> Below images show different types of funct3 and funct7 and opcodes of R-type instructions.
-> Here, we can see that "opcode" for all R-type instructions is "0110011" and "funct7" is "0000000" for all except for subtraction "0100000".
-> From above image:
- ADD : Addition
- SUB : Subtraction
- SLL : Shift Left Logical
- SLT : Set Less Than
- SLTU : Set Less Than Unsigned
- XOR : Bitwise xor
- SRL : Shift Right Logical
- SRA : Shift Right Arithmetic
- OR : Bitwise OR
- AND : Bitwise AND
-> These are called as "Immediate" instructions which are used for operations involving immediate value.
-> These perform arithmetic and logical operations where one operand is a constant(immediate).
-> This type of instrutions contains "funct3", "rs1","rd","opcode" and "imm".
-> I type instruction uses 12-bit immediate value ranging from -2047 to 2048.
-> Some of the I-type instructions are =>
- LI : Load Immediate.
li rd,imm
-> It loads a constant "imm" into "rd".
- ADDI : Add Immediate.
addi rd,rs1,imm
-> It adds signed immediate "imm" to value in "rs1" and stores in "rd".
- SUBI : Subtract Immediate.
subi rd,rs1,imm
-> It subtracts signed immediate "imm" from value in "rs1" and stores it in "rd".
- SLTI : Set Less Than Immediate.
slti rd,rs1,imm
-> It sets destination register to '1' if value in "rs1" is less than value in "imm" or else set to '0'.
- ORI : OR Immediate.
ori rd,rs1,imm
-> It performs a bitwise OR operation between "rs1" and "imm" values.
- SLLI : Shift Left Logical Immediate.
slli rd,rs1,imm
-> It left shifts the value in "rs1" by the value given in "imm" and stores it in rd.The vacated bits are filled with 'zeroes'.
- SRLI : Shift Right Logical Immediate.
srli rd,rs1,imm
-> It right shifts the value in "rs1" by the value given in "imm" and stores it in rd.The vacated bits are filled with 'zeroes'.
- SRAI : Shift Right Arithmetic Immediate.
srai rd,rs1,imm
-> It right shifts the value in "rs1" by the value given in "imm" and stores it in rd.The vacated bits are filled with 'sign bit'.
-> Below are some load instructions of I-type.
-> These are used for conditional branching.
-> They compare two registers and branch specified instruction if comparison is true.
-> Below image shows different B-type instructions.
-> Opcode reamins "1100011".
-> Target Address = PC(program Counter) + Immediate Target address.
-> From above image:
- BEQ : Branch Equal to
- BNEQ : Branch Not Equal to
- BGE : Branch Greater than or Equal to
- BLT : Branch Less Than
-> U means 'unsigned' in BGEU and BLTU.
-> U means "Upper Immediate".
-> These are designed to work with large immediate values.
-> These involve loading or adding a 20-bit immediate value to either a register or PC(Program Counter).<br/.
-> Below are some U-type instructions:
-
LUI : Load Upper Immediate
-> It loads 20-bit immediate value into upper 20 bits of a register,setting lower 12 bits to 'zero'.It is used to create large constants or prepare base address for further operations. -
AUIPC : Add Upper Immediate to PC
-> It adds 20-bit immediate value,shifted left by 12 bits to current value of PC.
-> These are called as Jump Instructions.
-> These are used to alter the flow of execution by setting PC to a specified address.
-> These instructions can be conditional and unconditional.
-> One of the main jump instructions in RISC-V is:
- JAL : Jump and Link.
-> It performs unconditional jump to a target address.It also stores return address in 'rd'.
-> Used typically for function calls.
-> Below is the image of some instructions in the object code.
- In this task, we are going to use a pre-written verilog code which is a micro-architecture and analyse the waveforms.
- This is a micro-architecture of a few important instructions of the instruction set of a Single cycle Reduced Instruction Set Computer - Five(RISC-V) Instruction Set Architecture suitable for use across wide-spectrum of Applications from low power embedded devices to high performance Cloud based Server processors.
- All the registers are 32-bit long.
- Below is the image of all instructions.
- Now we are going to debug an instruction.
-> Let us take " add r6,r1,r2 ".
Given 32'h02208300.
0000 0010 0010 0000 1000 0011 0000 0000
It can be written as =>
funct7 = 0000001.
rs2 = 00010 (which is r2).
rs1 = 00001 (which is r1).
funct3 = 000.
rd = 00110 (which is r6).
opcode = 0000000.
From this, we can write the expression as => " ADD R6,R1,R2 ".
- To implement this verilog code and simulate waveforms, we need to follow below steps.
- In the below steps, ' directory ' and ' module ' names are of your choice.
Note : ' $ ' need not to be typed in the terminal.
-> Create a directory using command ' mkdir ' in the terminal.
$ mkdir directory_name
-> Set the path to the directory using command 'cd' in the terminal.
$ cd directory_name
-> Now, create two ' .v ' files using command ' touch ' .
-> ' .v ' is the extension for verilog files.
$ touch module_name.v
$ touch module_name_tb.v
-> To run the verilog code enter below commands.
Note :
- While running this command, you have to be in the directory where .v files exist.
- The code doesn't give us any block diagrams or elaborated designs.
$ iverilog -o directory_name module_name.v module_name_tb.v
$ ./directory_name -> From running these commands, ' .vcd ' file will be generated.
-> We use this ' .vcd ' file for simulation.
-> To simulate the waveforms,we are going to use ' gtkwave '.
-> To invoke gtkwave =>
gtkwave module_name.vcd
-
To see the waveforms, we have to append them to the waveformsimulator.
- The below images will show the output waveform showing the instructions performed in a 5-stage pipelined architecture.
- In these images=>
- ' clk ' is the clock signal.
- ' EX_MEM_IR[31:0] is the 32-bit register storing instruction.
- ' ID_EX_A[31:0] ' and ' ID_EX_B[31:0] ' are the operands (32-bit registers).
- ' EX_MEM_ALUOUT[31:0] ' is the output 32-bit register.
Note :
We can observe the delay of " one clock cycle " in the output (sequential)=> So, we have to do operations between op1[n-1] and op2[n-1].(such as in signals)
-> EX_MEM_IR[31:0] = 32'h02208300.
-> Operation => 1 + 2 = 3.
-> EX_MEM_IR[31:0] = 02209380.
-> Operation => 1 - 2 = -1. (In signed decimal form).
-> In hexadecimal form, it is 'FFFFFFFF' (2's complement).
-> EX_MEM_IR[31:0] = 32'h0230A400.
-> Operation => 1 & 3 = 1 (bitwise AND operation) -> 001 & 011 = 001.
-> EX_MEM_IR[31:0] = 32'h02513480.
-> Operation => 2 | 5 = 7 (bitwise OR operation) -> 010 | 101 = 111.
-> EX_MEM_IR[31:0] = 32'h0240C500.
-> Operation => 1 ^ 4 = 5 (bitwwise XOR operation) -> 001 ^ 100 = 101.
-> EX_MEM_IR[31:0] = 32'h02415580.
-> SLT means ' Set if Less Than ' .For rs1 and rs2 => if rs1 < rs2 output will be ' 1 ' or else ' 0 '.
-> Operation : 2 < 4 = 1.
-> EX_MEM_IR[31:0] = 32'h00520600.
-> ADDI means 'Add Immediate '.
-> Operation 4 + 5 = 9.
-> EX_MEM_IR[31:0] = 32'h00209181.
-> SW means ' Store Word '.
-> Here Memory address = Base value in register + 12-bit offset.
-> Offset = 2 , base value = 1; Output = 3;
-> EX_MEM_IR[31:0] = 32'h00208681.
-> LW means ' Load Word '.
-> Here Memory address = Base value in register + 12-bit offset.
-> Offset = 2 , base value = 1; Output = 3;
-> EX_MEM_IR[31:0] = 32'h00f00002.
-> BEQ means ' Branch if Equal '.
-> We can see a new line named ' ID_EX_NPC '. It is the " Program Counter (PC) ".
-> Since the stored value in register is same as output, we have to increment PC by immediate value = 15.
-> PC = 10 (previous cycle) . Operation => 10 +15 = 25.
-> EX_MEM_IR[31:0] = 32'h00210700.
-> Operation => 2 + 2 = 4.
- These are the instructions used in the given micro-architecture
- Our final task is to use the VSDSQUADRON Mini board and implement a program on it.
- This project involves the implementation of LDR based Laser Security System using VSDSquadron Mini.
- This security system is widely used in perimeter protection, for detecting unauthoorized intrusion (trespassing).
- A laser emitter emits laser light( Light Amplification by Stimulated Emission of Radiation),
- LDR(Light Dependent Resistor) receives the laser light.
- The light will be given a level of voltage.
- When there is obstruction in light, the value of voltage varies and it sets off the alarm.
- Arduino IDE.
- VSDSQUADRON Mini
- Jumper wires
- Lasser Emitter
- LDR
- 10k ohm Resistor
- Buzzer
- Breadboard
- Below is the image of the program.
- Below image is the configurations of the board.
Note: If you have any problem with analogRead() in Arduino IDE, follow below steps.(for Windows OS) -> Go to home directory
-> Search for variants.
-> You may see this "Documents\ArduinoData\packages\WCH\hardware\ch32v\1.0.4\variants".
-> Now, go into variants > CH32V00x > CH32V003F4 and open " variant_CH32V003F4 "
-> Then, remove comments on ADC_module and SPI_module.
-> Save and close and problem is cleared(for me, it helped)
vsdsquadron.ldr.mp4
I would like to thank Mr. Kunal Ghosh and his team for providing me this wonderful internship experience on RISC-V using VSDSQUADRON Mini.I have learnt to do things by learning rather than remembering.I have experienced many obstructions throughtout the internship but I didn't give up until last moment.I can say again that I have learnt many things from this course and learnt to do things without giving up.
I would also like to thank the people who had helped me with my doubts and gave me a push forward.