VLSIDesignChain: 2 - Static Timing Analysis by OpenTimer
Published:
Static Timing Analysis by OpenTimer
OpenTimer is a static timing analysis tool and it is a part of the OpenROAD suite of tools. But today we will use OpenTimer standalone.
Preparing the Synthesis Result for STA
This time we will write a simple counter to test the timing of the design.
// counter.v
module counter (clk, rst, en, count);
input clk, rst, en;
output reg [1:0] count;
always @(posedge clk)
if (rst)
count <= 2'd0;
else if (en)
count <= count + 2'd1;
endmodule
From the last post, we synthesized the design step by step in Yosys. Yosys supports executing scripts, so here we combine the commmands into a script
# synth_asic.ys
read_verilog counter.v
hierarchy -check -top counter
proc; opt
memory; opt
fsm; opt
techmap; opt
# change the path based on your file location
dfflibmap -liberty /mnt/linuxstorage/vlsi-open-source-tool/case_study/freepdk-45nm/pkgs/base/stdcells.lib
abc -liberty /mnt/linuxstorage/vlsi-open-source-tool/case_study/freepdk-45nm/pkgs/base/stdcells.lib
clean
write_verilog -noexpr -noattr counter_asic_FreePDK45.v
To run the script
yosys -s synth_asic.ys
You will get a synthesized Verilog file counter_asic_FreePDK45.v
.
However, we need to remove assign statements in the Verilog file. This is because OpenTimer reads gate-level (aka structural) verilog files (.v) to initialize circuit netlists. Logics are described by gates and modules only. There are no always blocks or assign statements. Source. So we need to remove the assign statements in the last line of the Verilog file.
DFF_X1 _15_ (
.CK(clk),
.D(_01_),
.Q(count[1]),
.QN(_06_)
);
// assign _07_[1] = count[1];
Composing a SDC file
SDC is a timing constraint file that describes the timing requirements of the design. Here I follow the example SDC file provided by OpenTimer Link. You can refer back to the synthesized verilog file privided by OpenTimer to see more details.
# counter.sdc
# -----------------------------------------------------------------------------
# SDC constraints for the counter module (mimicking the provided SDC style)
# -----------------------------------------------------------------------------
# Create a clock named "clk" with a 50 ns period.
create_clock -period 50 -name clk [get_ports clk]
# Set input delay constraints for the clock port "clk"
set_input_delay 0 -min -rise [get_ports clk] -clock clk
set_input_delay 25 -min -fall [get_ports clk] -clock clk
set_input_delay 0 -max -rise [get_ports clk] -clock clk
set_input_delay 25 -max -fall [get_ports clk] -clock clk
# Set input delay constraints for "rst"
set_input_delay 0 -min -rise [get_ports rst] -clock clk
set_input_delay 0 -min -fall [get_ports rst] -clock clk
set_input_delay 5 -max -rise [get_ports rst] -clock clk
set_input_delay 5 -max -fall [get_ports rst] -clock clk
# Set input delay constraints for "en"
set_input_delay 0 -min -rise [get_ports en] -clock clk
set_input_delay 0 -min -fall [get_ports en] -clock clk
set_input_delay 1 -max -rise [get_ports en] -clock clk
set_input_delay 1 -max -fall [get_ports en] -clock clk
# Set input transition constraints for "rst"
set_input_transition 10 -min -rise [get_ports rst] -clock clk
set_input_transition 15 -min -fall [get_ports rst] -clock clk
set_input_transition 20 -max -rise [get_ports rst] -clock clk
set_input_transition 25 -max -fall [get_ports rst] -clock clk
# Set input transition constraints for "en"
set_input_transition 30 -min -rise [get_ports en] -clock clk
set_input_transition 30 -min -fall [get_ports en] -clock clk
set_input_transition 40 -max -rise [get_ports en] -clock clk
set_input_transition 40 -max -fall [get_ports en] -clock clk
# Set input transition constraints for the clock "clk"
set_input_transition 10 -min -rise [get_ports clk] -clock clk
set_input_transition 15 -min -fall [get_ports clk] -clock clk
set_input_transition 10 -max -rise [get_ports clk] -clock clk
set_input_transition 15 -max -fall [get_ports clk] -clock clk
# Set a load constraint for the output port "count"
set_load -pin_load 4 [get_ports count]
# Set output delay constraints for "count"
set_output_delay -10 -min -rise [get_ports count] -clock clk
set_output_delay -10 -min -fall [get_ports count] -clock clk
set_output_delay 30 -max -rise [get_ports count] -clock clk
set_output_delay 30 -max -fall [get_ports count] -clock clk
Generate STA by OpenTimer
Now we have everything read for OpenTimer to generate a STA report.
~$ ./bin/ot-shell
____ _______
/ __ \___ ___ ___/_ __(_)_ _ ___ ____
/ /_/ / _ \/ -_) _ \/ / / / ' \/ -_) __/
\____/ .__/\__/_//_/_/ /_/_/_/_/\__/_/ v2
/_/
MIT License: type "license" to see more details.
For help, type "help".
For bug reports, issues, and manual, please see:
<https://github.com/OpenTimer/OpenTimer>.
ot>
# change the path based on your file location
ot> read_celllib /mnt/linuxstorage/vlsi-open-source-tool/case_study/freepdk-45nm/pkgs/base/stdcells.lib
ot> read_verilog /mnt/linuxstorage/vlsi-open-source-tool/case_study/fifo/counter_asic_FreePDK45.v
ot> read_sdc /mnt/linuxstorage/vlsi-open-source-tool/case_study/freepdk-45nm/pkgs/base/counter.sdc
ot> report_timing
Here is the output of the STA report.
I 50752 25-04-15 15:43:38 sdc.cpp:35] loading sdc "/mnt/linuxstorage/vlsi-open-source-tool/case_study/freepdk-45nm/pkgs/base/counter.sdc" ...
I 50752 25-04-15 15:43:38 sdc.cpp:21] added 30 sdc commands
Startpoint : rst
Endpoint : _15_:D
Analysis type : max
------------------------------------------------------
Type Delay Time Dir Description
------------------------------------------------------
port 5.000 5.000 0.000 fall rst
pin 0.000 5.000 0.000 fall _13_:A1 (NOR3_X1)
pin 7.183 12.183 330.287 rise _13_:ZN (NOR3_X1)
pin 0.000 12.183 0.000 rise _15_:D (DFF_X1)
arrival 12.183 data arrival time
related pin 10.000 10.000 rise _15_:CK (DFF_X1)
constraint 2.486 12.486 library setup_rising
required 12.486 data required time
------------------------------------------------------
slack 0.303 MET