This report is the progress of making a Automatic Roof Controller RISCV based application
- 1.RTL and Functional verification
- 2.Synthesis(Yosys) and GLS
- 3.PnR OpenLane Flow
- Acknowledgemnet
- References
The objective of this is to create a Rain sensor based Automatic Roof RISCV Controller. Rain sensor-based automatic roof controllers are primarily used in buildings and structures where the roof's position needs to be adjusted in response to rain or other weather conditions. These controllers are designed to detect rain and trigger the closing of the roof to protect the interior from water damage. Here are some common applications for rain sensor-based automatic roof controllers:
- Restaurants, cafes, and outdoor dining spaces often use rain sensor-based controllers to automatically close retractable roofs or awnings when it starts raining. This allows patrons to continue dining without being affected by rain.
- To prevent the harvested crops from the heavy rain and save the rain water. The rain sensor is used for the working of roof when there is rainfall.
The working principle of the rain sensor(FC-37 rain sensor) is indeed straightforward :
- Sensing Pad: The rain sensor has a sensing pad with exposed copper traces. These traces act as a variable resistor whose resistance changes with the amount of water on its surface.
- Resistance Variation: The resistance of the sensing pad is inversely proportional to the amount of water present. In other words:
More water on the surface results in better conductivity and lower resistance.
Less water on the surface leads to poor conductivity and higher resistance. - Output Voltage: The sensor produces an output voltage that corresponds to the resistance of the sensing pad. This voltage is used to determine whether it's raining or not. When the sensing pad is wet, the output voltage will be different from when it's dry.
- Electronic Module: The sensor includes an electronic module that connects the sensing pad to a microcontroller like Arduino. This module interfaces with the sensor and provides an output voltage at an Analog Output (AO) pin. This analog signal is proportional to the resistance of the sensing pad.
- Digital Output: The sensor module also contains an LM393 High Precision Comparator, which is used to digitize the analog signal. The digitized signal is made available at a Digital Output (DO) pin.
- Sensitivity Adjustment: The sensor module typically features a built-in potentiometer that allows for sensitivity adjustment of the digital output (DO). By adjusting the potentiometer, you can set a threshold value. When the amount of water on the sensing pad exceeds this threshold, the module will output a logic LOW signal; otherwise, it will output a logic HIGH signal.
- Rain Detection: To detect rain, we monitor the digital output signal. If the signal goes LOW, it indicates that the threshold has been exceeded, and the sensor has detected rain. Conversely, a HIGH signal means no rain is detected.
Circuit Diagram
gcc arc_gcc_21oct.c
./a.out
Block Diagram
- We tested the functional simulation above but here using spike also we would be doing fuctional simulation but here the differnce is we are linking the c program with the inline assembly(asm).
Modifying C code for spike simulation and verification which can be found above as arc_spike.c
Commands to run spike:
riscv64-unknown-elf-gcc -march=rv64i -mabi=lp64 -ffreestanding -o out arc.c
spike pk out
-
Based on my application whenever the sensor reads '0' (rain_sensor_ip) which means rain is falling then the roof should be closed which is '1'(roof_status_op). We can observe the same in the above spike simulation my input is being '0' my output for that input is showing '1' and for the x30 register positions of input and output are x30[0] and x30[1] respectively for the given input and output combination my x30 register should be '2'.
-
Similarly, whenever the sensor reads '1' (rain_sensor_ip) which means rain is not falling then the roof should be opened which is '0'(roof_status_op). We can observe the same in the above spike simulation my input is being '1' ,so my output for that input is showing '0' and for the x30 register positions of input and output are x30[0] and x30[1] respectively for the given input and output combination my x30 register should be '1'. As expected, we can see the Spike simulation results from the above figure.
x30[0] - Input from the sensor
x30[1] - output to the motor
int main()
{
int rain_sensor_ip;
int roof_status_op = 0;
int roof_status_op_reg;
int mask =0xFFFFFFFD;
roof_status_op_reg = roof_status_op*2;
asm volatile(
"and x30, x30, %1\n\t"
"or x30, x30, %0\n\t"
:
: "r" (roof_status_op_reg), "r"(mask)
: "x30"
);
while(1)
{
asm volatile(
"andi %0, x30, 0x01\n\t"
: "=r" (rain_sensor_ip)
:
:);
if (rain_sensor_ip)
{
roof_status_op = 0;
mask =0xFFFFFFFD;
roof_status_op_reg = roof_status_op*2;
asm volatile(
"and x30,x30, %1\n\t"
"or x30, x30, %0\n\t"
:
: "r" (roof_status_op_reg), "r"(mask)
: "x30"
);
//printf("Rain not detected. Roof opened.\n");
//printf("roof_status_op=%d \n", roof_status_op);
}
else
{
roof_status_op = 1;
mask =0xFFFFFFFD;
roof_status_op_reg = roof_status_op*2;
asm volatile(
"and x30,x30, %1\n\t"
"or x30, x30, %0\n\t"
:
: "r" (roof_status_op_reg), "r"(mask)
: "x30"
);
//printf("Rain detected. Roof closed.\n");
// printf("roof_status_op=%d \n", roof_status_op);
}
}
return 0;
}
Converting the C code into the assebly code using the following commands:
riscv64-unknown-elf-gcc -march=rv32i -mabi=ilp32 -ffreestanding -nostdlib -o out arc.c
riscv64-unknown-elf-objdump -d -r out > asm.txt
Assembly Code
out: file format elf32-littleriscv
Disassembly of section .text:
00010054 <main>:
10054: fe010113 addi sp,sp,-32
10058: 00812e23 sw s0,28(sp)
1005c: 02010413 addi s0,sp,32
10060: fe042623 sw zero,-20(s0)
10064: ffd00793 li a5,-3
10068: fef42423 sw a5,-24(s0)
1006c: fec42783 lw a5,-20(s0)
10070: 00179793 slli a5,a5,0x1
10074: fef42223 sw a5,-28(s0)
10078: fe442783 lw a5,-28(s0)
1007c: fe842703 lw a4,-24(s0)
10080: 00ef7f33 and t5,t5,a4
10084: 00ff6f33 or t5,t5,a5
10088: 001f7793 andi a5,t5,1
1008c: fef42023 sw a5,-32(s0)
10090: fe042783 lw a5,-32(s0)
10094: 02078863 beqz a5,100c4 <main+0x70>
10098: fe042623 sw zero,-20(s0)
1009c: ffd00793 li a5,-3
100a0: fef42423 sw a5,-24(s0)
100a4: fec42783 lw a5,-20(s0)
100a8: 00179793 slli a5,a5,0x1
100ac: fef42223 sw a5,-28(s0)
100b0: fe442783 lw a5,-28(s0)
100b4: fe842703 lw a4,-24(s0)
100b8: 00ef7f33 and t5,t5,a4
100bc: 00ff6f33 or t5,t5,a5
100c0: fc9ff06f j 10088 <main+0x34>
100c4: 00100793 li a5,1
100c8: fef42623 sw a5,-20(s0)
100cc: ffd00793 li a5,-3
100d0: fef42423 sw a5,-24(s0)
100d4: fec42783 lw a5,-20(s0)
100d8: 00179793 slli a5,a5,0x1
100dc: fef42223 sw a5,-28(s0)
100e0: fe442783 lw a5,-28(s0)
100e4: fe842703 lw a4,-24(s0)
100e8: 00ef7f33 and t5,t5,a4
100ec: 00ff6f33 or t5,t5,a5
100f0: f99ff06f j 10088 <main+0x34>
To find the number of unique instructions make sure to rename the filename as assembly.txt since the python script that we are using is opening the file name with assembly.txt and both files should be in the same directory. The python script I am using is already uploaded. Now follow the command to get the number of different instructions used.
$ python3 instruction_counter.py // use this command after ensuring we are in the same directory as the script
Number of different instructions: 10
List of unique instructions:
or
j
beqz
sw
addi
andi
li
and
slli
lw
-
We will do the functional simulation for the processors that are being created for the assembly program that is being created for my application. The
processor.vand thetestbench.vis uploaded and those can be seen above. -
Commands to run the verilog file
iverilog -o test processor.v testbench.v ./test gtkwave waveform.vcd
- Since we bypassed the UART write_done is becoming at t=o itself and the ID_instruction starts executing after making the reset zero.
- In the testbench I have given the input initially as "1" and then changing the input to "0" correspondingly output is inverted. By this we verified the functional simulation and now can proceed with the gate level simulation.
- And the spikes that are visible in the output signal is due to resetting the output to zero after every cycle.
- The
$signal[31:0]is actually represents x30 register where inputs are being stored in there from the sensor retieving thoe values to compute the output and then stored back in the x30 register. - The
ID_instruction, each instruction is decoded and then only the later steps takes place one by one.
-
In the above figure when ID_instruction is being
02078863the pc is getting jumped to a particular instruction this is because at that instruction it is checking whether the input is being 1 or not since it is not '1' so the pc value is not incrementing by one instead jumping to another location.10094: 02078863 beqz a5,100c4 <main+0x70>
- Output is changing from 0 to 1 after the execution of instruction
00FF6F33
- Output is changing from 1 to 0 after the execution of instruction
00ef7f33
Commands to run synthesis
Before running the synthesis, some changes are done in the processor.v file.
-
Commenting the module definitions of both sky130_sram_2kbyte_1rw1r_32x256_8_data and sky130_sram_2kbyte_1rw1r_32x256_8_inst.
-
The already instantiated sram modules are also changed from sky130_sram_2kbyte_1rw1r_32x256_8_data and sky130_sram_2kbyte_1rw1r_32x256_8_inst to sky130_sram_1kbyte_1rw1r_32x256_8 since the processor doesnt actually neede 2k ram.
-
Running synthesis two times with
writing_inst_done=1andwriting_inst_done=0and we get two netlists and named assynth_test.vandsynth_processor.vrespectively. When writing_inst_done=1 that means we are by passing the uart so that the .vcd file doesnt takes up 20+GB and using the corresponding netlist gate level simulation is done and also verification is done.yosys read_liberty -lib sky130_fd_sc_hd__tt_025C_1v80_256.lib read_verilog processor.v synth -top wrapper dfflibmap -liberty sky130_fd_sc_hd__tt_025C_1v80_256.lib abc -liberty sky130_fd_sc_hd__tt_025C_1v80_256.lib write_verilog synth_processor.v
Invoking YOSYS and reading the .lib file
Top level module synthesis
Maping the dfflib
Logic Synthesis using abc tool
Gate level Simulation
Before doing gate level simulation using the synthesised netlist some changes are made in the synthesised netlist file
- Before doing synthesis we changed the sram module instantiation names to map it with the standard cell but now while doing simulation this is not a cell this is a module so we need to instantiate the module names as it is from the sky130_sram_1kbyte_1rw1r_32x256_8.v sine module definition is present in that file. (sky130_sram_1kbyte_1rw1r_32x256_8_inst and sky130_sram_1kbyte_1rw1r_32x256_8_data).
- And also in the sky130_sram_1kbyte_1rw1r_32x256_8.v file replace the mem instructions to our processor instructions which are taken from the processor.v.
After the changes are done run the simulation using the command given below.
iverilog -o synth_test testbench.v synth_test.v sky130_sram_1kbyte_1rw1r_32x256_8.v sky130_fd_sc_hd.v primitives.v
In the above snapshot under the dut in the left hande side we can see some numbers this indicates that we simulated using the synthesised netlist. And also the output behaviour is matching with the RTL functional simulation. Hence now we can proceed with the openlane flow.
OpenLane is an open-source digital ASIC implementation flow developed by the OpenROAD project. It automates many of the steps involved in the ASIC design process, including synthesis, floorplanning, placement, and routing. The OpenLane flow is typically used for designing and implementing digital integrated circuit.
Synthesis
- yosys/abc - Perform RTL synthesis and technology mapping.
- OpenSTA - Performs static timing analysis on the resulting netlist to generate timing reports
Floorplaning
- init_fp - Defines the core area for the macro as well as the rows (used for placement) and the tracks (used for routing)
- ioplacer - Places the macro input and output ports
- pdngen - Generates the power distribution network
- tapcell - Inserts welltap and decap cells in the floorplan
Placement
- RePLace - Performs global placement
- Resizer - Performs optional optimizations on the design
- OpenDP - Performs detailed placement to legalize the globally placed components
CTS
- TritonCTS - Synthesizes the clock distribution network (the clock tree)
Routing
- FastRoute - Performs global routing to generate a guide file for the detailed router
- TritonRoute - Performs detailed routing
- OpenRCX - Performs SPEF extraction
Tapeout
- Magic - Streams out the final GDSII layout file from the routed def
- KLayout - Streams out the final GDSII layout file from the routed def as a back-up
Signoff
- Magic - Performs DRC Checks & Antenna Checks
- KLayout - Performs DRC Checks
- Netgen - Performs LVS Checks
- CVC - Performs Circuit Validity Checks
cd Openlane
make mount
./flow.tcl -interactive
package require openlane 0.9
prep -design processor
run_synthesis
Since my macro is huge, So I set the SYNTH_NO_FLAT to 1 true (JSON), which will postpone the flattening of the design during synthesis until the very end.
Post Synthesis report
run_floorplan
Floorplan Core area
Floorplan Die area
Magic
-
After running the floorplan it will have created a def file. For viewing the floorplan run the following command.
magic -T /home/pranathi/vsdstdcelldesign/libs/sky130A.tech lef read /home/pranathi/OpenLane/designs/processor/runs/RUN_2023.11.20_19.55.38/tmp/merged.nom.lef def read /home/pranathi/OpenLane/designs/processor/runs/RUN_2023.11.20_19.55.38/results/floorplan/wrapper.def
run_placement
Magic
magic -T /home/pranathi/vsdstdcelldesign/libs/sky130A.tech lef read /home/pranathi/OpenLane/designs/processor/runs/RUN_2023.11.20_19.55.38/tmp/merged.nom.lef def read /home/pranathi/OpenLane/designs/processor/runs/RUN_2023.11.20_19.55.38/results/placement/wrapper.def
Post Placement reports
The clock period used for clocks in the design, in nanoseconds. At first when used the clock period of 15ns got the negative slack as shown in figure to make it positive clock frequency has been reduced which means increased the clock period to 20ns. These changes are made in config.json file.
"CLOCK_PERIOD": 15
"CLOCK_PERIOD":24
Power Report
Area Report
Skew Report
run_routing
Encountered violations after detailed routing
To rectify those violations some changes are done in the config.json file FP_CORE_UTIL: 10 PL_TARGET_DENSITY: 0.3 PL_MACRO_CHANNEL: "200 200"
magic -T /home/pranathi/vsdstdcelldesign/libs/sky130A.tech lef read /home/pranathi/OpenLane/designs/processor/runs/RUN_2023.11.14_12.14.14/tmp/merged.nom.lef def read /home/pranathi/OpenLane/designs/processor/runs/RUN_2023.11.14_12.14.14/results/routing/wrapper.def
No violations
Post Routing Power reports
Post Routing Timing reports
Post Routing area reports
From the config.json file the clock period is 24ns and from the timing reports we can observe the slack of 4.91ns. To calculate the maximum frequency of operation,fmax we use the formula given below.
1
fmax = -----------------------------
Tclock - slack(setup)
fmax = 52.38 MHz.
The maximum frequency of operation is 52.38 MHz.
RUN_MAGIC
Enables running magic and GDSII streaming.
RUN_MAGIC_SPICE_EXPORT
RUN_MAGIC_DRC
Enables running magic DRC on GDSII produced by magic.
RUN_ANTENNA_CHECK
- Kunal Ghosh, VSD Corp. Pvt. Ltd.
- Mayank Kabra (Founder, Chipcron Pvt. Ltd.)
- Bhargav, Colleague, IIITB











































