Skip to content

spdy1895/RTL_synthesis_using_sky130

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

26 Commits
 
 
 
 

Repository files navigation

RTL Design, Synthesis and Optimization using Yosys and SKYWATER130 PDKs

Verilog-flyer

In VLSI industry Front-end digital design inlcudes RTL design, synthesis, optimization and verification. In the current repository i have included the deisgn, synthesis and optimization work on various digital modules, from very simple digital logic (mux, decoder, encoder etc.) to complex designs(barrel shifter, booth multiplier, dual port ram etc). All the work has been done using open source tools:-

  • iverilog for RTL simulation.
  • gtkwave for reading .vcd file and waveform generation.
  • yosys for synthesis and netlist generation.
  • skywater 130nm open source pdk.

Introduction Of OPEN-SOURCE HARDWARE And TOOLS

With the introduction of open-source tools in the ASIC flow, now VLSI engineers have opportunity to design and craft their own ideas starting from RTL 2 GDSII. Moreover further inclusion of VLSI enthusiast and learners have propelled the need of open-source community for hardware also. Organizations such as:-

  • open source hardware association
  • SiFive
  • FOSSI
  • OpenPOWER Foundation
  • VSD
  • RISCV
  • Redwood EDA
  • Efabless etc

are committed to bring revolution in the Silicon industry.

RTL DESIGN AND SYNTHESIS USING SKYWATER130 PDK


I have categorized my work in day wise learning, according to the workshop conducted by VSD.


Table of Contents


DAY 01

Introduction to verilog RTL design and synthesis

RTL Design

It's a way of writng hdl code for digital design in a way to exploit the behavioral features offered by the language and also utilizing the structural description for design accuracy. So it's a trade off between behavioral constructs and structural description while writing hardware code.

Synthesis

Translation and optimization of the RTL code into the gate level netlist. The synthesis tool(yosys) takes hdl code, liberty file(.lib) and design constraints to generate gate level netlist.

Netlist

Representation of the design in terms of actual standard cells and their connections.

Lib file

Liberty Timing file(.lib) consist of timing and power parameters associated with standard cells specific to a particular technology node. Generally it includes definition of an inverter, nand2, nand3, nand4, nor2, nor3, nor4, aoi12, aoi22, oai12, oai22, mux, dff etc.

NOTE

Why Standard Cell library includes various(in terms of PPA) types of gate cells?

In the digital circuit some combinational paths requires cells that are very fast in performance(but requires more area and power) and likewise some combinational paths requires cells that are slower in performance(but better in terms of area and power). So adhering to the timing conditions, which standard cells are to be used the decision is made. These decisions are written in constraint file and are passed to synthesis tool(yosys) for guided synthesis.

Synthesis using yosys

Invoke yosys shell

   $ yosys

shubh_yosys_invoke

yosys>

Commands for synthesis using yosys

    yosys> read_liberty -lib ../../path_to_the_standard_library_file.lib         // reading the liberty file.
    yosys> read_verilog ../../path_to_verilog_file_that_is_to_be_synthesized.v   // reading the verilog file.
    yosys> synth -top module_name                                                // the module name that is to be synthesized.
    yosys> abc -liberty  ../../path_to_to_liberty_file.lib                       // netlist generation.
    yosys> show                                                                  // a gui based representation of logic synthesized.
    yosys> write_verilog file_name.v                                             // write the generated netlist to new a module/verilog
                                                                                 // file for verification.

Results

result of the command "yosys> synth -top module_name"

shubh_synth_result

  • result of the command "yosys> abc -liberty ../../path_to_liberty_file.lib" NOTE
  • the difference in synthesis performed by various version of yosys.
  • synthesis performed by yosys 0.7.

shubh_abc_result

  • logical representation of the deisgn by yosys 0.7.

shubh_show

  • synthesis performed by yosys 0.9.

shubh_abc_01

  • logical representation of the design by yosys 0.9.

shubh_show_01 4

NOTE

the synthesis performed by yosys 0.7 is choosing different standard cells as compared to synthesis by yosys 0.9.

  • netlist generated by yosys 0.7.

netlist_generated


Day 02

Timing library hierarchical vs flat synthesis and efficient flop coding styles


Introduction to timing library

skywater-pdk-logo

sky130_fd_sc_hd_tt_025C_1v80.lib

the liberty timing file(.lib) is an ASCII file consists of detailed information of timing and power parameters about any standard cell of a particular technology node. The parameters are affected by PVT variations (process, voltage, temperature). These variations are factorized while designing IC. So the Standard Cell library is characterized to model these variations. The feature size in this technology node is 130nm. The terms in the .lib file are:-

  • fd - the skywater foundary
  • sc - digital standard cell
  • hd - high density
  • tt - typical process
  • 025C - temperature
  • 1v - voltage

library in the sky130 pdk are named using the following scheme:

"" Process name _ Library Source Abbreviation _ Library Type Abbreviation _ Library Name ""

Library Source Abbreviation
The SkyWater Foundary fd
Efabless ef
Oklahoma State University osu
Library Type Abbreviation
Primitive Cells pr
Digital Standard Cells sc
Build Space(Flash, SRAM, etc) sp
IO and Periphery io
High Densiry hd

Skywater Foundary provided standard cell libraries

  • sky130_fd_sc_hd - High Density Standard Cell Library.
  • sky130_fd_sc_hdll - High Density, Low Leakage Standard Cell Library.
  • sky130_fd_sc_hs - Low Voltage (<2.0V), High Speed, Standard Cell Library.
  • sky130_fd_sc_ms - Low Voltage (<2.0V), Medium Speed, Standard Cell Library.
  • sky130_fd_sc_ls - Low Voltage (<2.0V), Low Speed, Standard Cell Library.
  • sky130_fd_sc_lp - Low Voltage (<2.0V), Low Power, Standard Cell Library.
  • sky130_fd_sc_hvl - High Voltage (5V), Standard Cell Library.

more details can be found at skywater-pdf.

standard cell definition of and3_or1_invert:-

standard_cell_definition

area comparison of different types of and cells.

area_comparison

Hierarchical vs Flat Synthesis


hierarchical synthesis

the synthesis results obtained after hierarchical synthesis shows that the sub-modules and the hierarchy of it's instantiation is preserved. The design is partitioned into a much higher level of abstraction. synth_multiple_module

logical description of hierarchical synthesis

show_hierar

netlist of hierarchical synthesis

netlist_noattr

Note: in the Hierarchical Synthesis the design is partitioned into sub-modules hence it becomes easy to trace back each component of the design. Also the design complexity is less and easy to comprehend.

flat synthesis

$ yosys> flatten                                            // to invoke flat synthesis after netlist generation
$ yosys> write_verilog -noattr multiple_modules_flat.v      // to write verilog netlist without attributes(clean)

in the flat synthesis, instantiation of standard cells take place and the design is partitioned into a much lower level of abstraction.

logical description of flat synthesis

show_flattened

netlist comparison of flat synthesis vs hierarchical synthesis

netlist_hie_flat

Sub-module level synthesis

$ yosys> synth -top sub_module1           // to synthesize only the submodule
  • sub-module synthesis is preferred if:
    • there are multiple instances of same module. So it's better to synthesize the module once and then use it multiple times.
    • if desing and conquer approach is required i.e. if the design is very massive and complex, so it's better to synthesize module by module and then finally stitch together all the modules into the top module.

Various Flip Flop coding styles and optimization


asynchronous reset dff

always@(posedge clk or posedge async_reset) begin 
    if(async_reset)  q<= 1'b0;
    else              q<= d_in;
end

async_rst_01 asyn_rst_show

asynchronous set dff

always@(posedge clk or posedge async_set) begin
    if(async_set)  q<= 1'b1;
    else           q<= d_in;
end

async_set async_set_show_synth

asynchronous-synchronous reset dff

always@(posedge clk or posedge async_reset) begin
    if(async_reset)     q<= 1'b0;
    else if(sync_reset) q<= 1'b0;
    else                q<= d_in;
end

dff_asyncres_syncres_vcd asyncres_synres_show_abc

synchronous reset dff

always@(posedge clk) beign
    if(sync_reset)  q<= 1'b0;
    else            q<= d_in;
 end

syncres_waveform dff_synres_show

Note

  • Asynchronous reset pin is directly synthesized on the flip flop.
  • Synchronous reset signal is passed through a combinational logic to the flip flop.

Optimization in constant multiplier circuit

module mul2(
  output wire y[3:0],
  input wire in[2:0]
);
    assign y= a * 2;
endmodule
// there is an interesting optimiztion taking place here instead of generating any hardware for the logic.

Note

  • there are only wire components in the circuit. Also note the comment by the synthesis tool(yosys) while mapping.

mult2_abc

  • netlist mult2_netlist
  • logical description mult2_show
Similar optimization
module mul8(
    output wire y[5:0],
    input wire in[2:0]
    );
        assign y= a * 9;
endmodule

Note

  • here replication of input takes place.

mult8_abc_response

  • netlist mult8_netlist
  • logical description mult8_show

Day 03

Combinational and Sequential optimization


Introduction to optimization

command to perform optimization

$ yosys > opt_clean -purge        // all optimizations are done with this
                                  // enter this command after "synth"

Combinational logic optimization

  • case 1
module opt_check(                             

  output wire y,
  input wire a,
  input wire b
);
    assign y= a ? b : 0;
endmodule
  • expected optimization by tool.

opt1_theory

  • result obtained.

opt1_show

  • Case 2
module opt_check2(
  output wire y,
  input wire a,
  input wire b
);
    assign y= a ? 1 : b;
endmodule
  • expected optimization by tool.

opt2_theory

  • result obtained.

opt2_show

  • Case 3
module opt_check3(
  output wire y,
  input wire a,
  input wire b,
  input wire c
);
  assign y= a ? ( C ? b : 0 ) : 0;
endmodule
  • expected optmization by tool.
  • result obtained.

opt_check3_show

  • Case 4
module opt_check4(
  output wire y,
  input wire a,
  input wire b,
  input wire c
);
    assign y= a ? ( b ? ( a & c ) : c ) : ( !c );
endmodule
  • expected optimization by tool.

result obtained.

opt_check4

Multiple module optimization

Note

before running optimization command, first flatten the design.

$ yosys > synth -top module_name              // synthesizing the top module
$ yosys > flatten                               // flattening the entire design and removing the hierarchy
$ yosys > opt_clean -purge                      // running optimization
$ yosys > abc -liberty /path_to_.lib            // mapping into the liberty file standard cells
$ yosys > write_verilog file.v                  // writing netlist
  • Case 5
module sub_module1(input a , input b , output y);
  assign y = a & b;
endmodule


module sub_module2(input a , input b , output y);
  assign y = a^b;
endmodule


module multiple_module_opt(input a , input b , input c , input d , output y);
  wire n1,n2,n3;

  sub_module1 U1 (.a(a) , .b(1'b1) , .y(n1));
  sub_module2 U2 (.a(n1), .b(1'b0) , .y(n2));
  sub_module2 U3 (.a(b), .b(d) , .y(n3));

  assign y = c | (b & n1); 


endmodule

expected optimization by tool.

result obtained after optimization.

multiple_module_opt1 netlist of the optimized design. multiple_module_opt_netlist

  • Case 6
module sub_module(input a , input b , output y);
  assign y = a & b;
endmodule

module multiple_module_opt2(input a , input b , input c , input d , output y);
  wire n1,n2,n3;

    sub_module U1 (.a(a) , .b(1'b0) , .y(n1));
    sub_module U2 (.a(b), .b(c) , .y(n2));
    sub_module U3 (.a(n2), .b(d) , .y(n3));
    sub_module U4 (.a(n3), .b(n1) , .y(y));
endmodule

expected optimization by tool.

result obtained after optimization.

multiple_module_opt2_show

netlist of the optimized design.

multiple_module_opt2_newopt_netlist

Sequential logic optimization

  • Case 1
module dff_const1(
  output reg q,
  input wire clk,
  input wire reset
);
  always @(posedge clk or posedge reset)
    begin
        if(reset)
	          q <= 1'b0;
        else
	          q <= 1'b1;
    end
endmodule

statistics after synth command.

dff_const1_synth

result after optmization.

dff_const1_show

  • Case 2
module dff_const2(
  output reg q,
  input wire clk,
  input wire reset
);

always@(posdge clk or posedge reset) begin
    if(reset) q<= 1'b1;
    else      q<= 1'b1;
end
endmodule

statistics after synth command.

dff_const2_synth

result after optimization.

dff_const2_show

  • Case 3
module dff_const3(
  output reg q,
  input wire clk,
  input wire reset
  );
    reg q1;
    
    always@(posedge clk or posedge reset) begin
    if(reset) begin
            q<= 1'b1;
            q1<= 1'b0;
    end
    else begin
          q1<= 1'b1;
          q<= q1;
    end
    end
    endmodule

statistics after synth command.

dff_const3_synth

result after optimization.

dff_const3_show

  • Case 4
module dff_const4(
  output reg q,
  input wire clk,
  input wire reset
  );
  reg q1;
    always@(posedge clk or posedge reset) begin
      if(reset) begin
        q<= 1'b1;
        q1<= 1'b1;
      end
    else begin
        q1<= 1'b1;
        q<= q1;
      end
    end
endmodule

statistics after synth command.

dff_const4_synth

result after optimization.

dff_const4_show

  • Case 5
module dff_const5(
  output reg q,
  input wire clk,
  input wire reset
  );
    reg q1;
    always@(posedge clk or posedge reset) begin
        if(reset) begin
            q<= 1'b0;
            q1<= 1'b0;
            end
         else begin
            q1<= 1'b1;
            q<= q1;
            end
     end
endmodule

statistics after synth command.

dff_const5_synth

result after optimization.

dff_const5_show

Sequential optimization for unused outputs

  • Case 1 : 3 bit up-counter
module counter_opt(
  output reg q,
  input wire clk,
  input wire reset
);
    reg [2:0] count;
    assign q= count[0];
    
      always@(posedge clk or posege reset) begin
        if(reset) count< =3'b000;
        else      count<= count + 1;
      end
endmodule

statistics after synth command.

counter_opt1_synth

result after optimization.

counter_opt1_show

  • Case 2 : 3 bit up-counter
module counter_opt(
  output reg q,
  	  wire clk,
  	  wire reset
	);
        reg [2:0] count;
        assign q= (count[2:0]== 3'b000);
    
          always@(posedge clk or posege reset) begin
            if(reset)  count< =3'b000;
             else      count<= count + 1;
           end
	endmodule

statistics after synth command.

counter_opt_3_synth

result after optimization.

counter_opt_3_show


Day 04

GLS, blocking vs non-blocking and synthesis-simulation mismatch


Gate level simulation

using netlist generated by the synthesis tool as DUT and test bench(same test bench i.e. used for RTL simulation) the simulation tool iverilog can perform a logical simulation called as Gate level simulation. It is performed to verify the logical correctness of the design after synthesis.

Comparing RTL simulation and Gate level simulation

  • case 1:
assign y= sel ? i1 : i0;		// infers a 2:1 mux

statistics after synth command.

ternary_mux_synth

logical description.

ternary_mux_show

RTL simulation.

ternary_mux_waveform

Gate level simulation.

gls_waveform_ternary_mux

  • Case 2:
always@(sel) begin
	if(sel) y<= i1;
	else	y<= i0;	
end

statistics after synth command.

bad_mux_synth

RTL simulation.

bad_mux_waveform_before_synth

Gate level simulation.

bad_mux_waveform_after_synth

Synthesis-Simulation mismatch

module blocking_caveat(
   output reg d,
   input wire a,
   input wire b,
   input wire c
);
	reg x;
	always @(*) begin
	   d= x & c;
	   x= a | b;
end
endmodule

statistics after synth command.

blocking_caveat_stats

RTL simulation.

blocking_caveat_rtl_waveform

Gate level simulation.

blocking_caveat_gsl_synth_waveform


Day 05

If, case, for loop and for generate


incomplete "if" constructs

  • case 1:

    module incomp_if( output reg y, input wire i0, input wire i1, input wire i2, );

     always@(*) begin
     	if(i0) y<= i1;
     end
    

    endmodule

statistics after synth command.

incomplete_if_synth

logical description.

incomplete_if_show

RTL simulation.

incomplete_if_rtl_waveform

  • case 2:

    module incomp_if2(
      output reg y,
      input wire i0,
      input wire i1,
      input wire i2,
      input wire i3
      );
      
      always@(*) begin
      	if(i0)  y<= i1;
      	else if y<= i3;
      end
    endmodule
    

statistics after synth command.

incomple_if2_synth

logical description.

incomplete_if2_show

RTL simulation.

incomplete_if2_rtl_waveform2

incomplete "case" constructs

module incomp_case(
	output reg y,
	input wire i0,
	input wire i1,
	input wire i2,
	input wire [1:0] sel
	);
	
	always@(*) begin
		case(sel)
			2'b00: y= i0;
			2'b01: y= i1;
		endcase
	end
endmodule

statistics after synth command.

incomplete_case_synth

logical description.

incomplete_case_show

RTL simulation.

incomplete_case_rtl_waveform

complete "case" constructs

module comp_case(
	output reg y,
	input wire i0,
	input wire i1,
	input wire i2,
	input wire [1:0] sel
	);
	
	always@(*) begin
		case(sel)
			2'b00:     y= i0;
			2'b01: 	   y= i1;
			default:   y= i2;
		endcase
	end
endmodule

statistics after synth command.

complete_case_synth

logical description.

complete_case_show

RTL simulation.

complete_casse_rtl_waveform

partial "case" constructs

module partial_case_assign(
	output reg y,
	output reg x,
	input wire i0,
	input wire i1,
	input wire i2,
	input wire [1:0] sel
	);
		always@(*) begin
			case(sel)
				2'b00: begin
					y= i0;
					x= i2;
					end
				2'b01: y= i1;
				default: begin
					x= i1;
					y= i2;
					end
			endcase
		end
	endmodule

statistics after synth command.

partial_case_synth

logical description.

partial_case_show

bad "case" constructs

module bad_case(
	output reg y,
	input wire i0,
	input wire i1,
	input wire i2,
	input wire i3,
	input wire [1:0] sel
	);
	
	always@(*) begin
		case(sel)
			2'b00: y= i0;
			2'b01: y= i1;
			2'b10: y= i2;
			2'b1?: y= i3;
		endcase
	end
enmodule

statistics after synth command.

bad_case_synth

logical description.

bad_case_show

RTL simulaiton

bad_case_rtl_waveform

Gate level simulation. bad_case_gls_waveform

generate constructs

mux using for loop inside always block

module mux_generate(
	output reg y,
	input wire i0,
	input wire i1,
	input wire i2,
	input wire i3,
	input wire [1:0] sel
	);
	
	wire [3:0] i_int;
	assign i_int= {i3, i2, i1, i0};
	intege k;
	always@(*) begin
		for(k=0; k< 4; k= k+1) begin
			if(k == sel) y= i_int[k];
		end
	end
endmodule

statistics after synth command.

mux_generate_synth

logical description.

generate_mux_show

RTl simulation.

mux_generate_rtl_waveform

demux using case inside always block

module demux_case(
	output wire o0,
	output wire o1,
	output wire o2,
	output wire o3,
	output wire o4,
	output wire o5,
	output wire o6,
	output wire o7,
	input wire i
	);
	
	reg [7:0] y_int;
	assign {o7, o6, o5, o4, o3, o2, o1, o0}= y_int;
	intege k;
	always@(*) begin
		y_int= 8'b0;
		case(sel)
			3'b000: y_int[0]= i;
			3'b001: y_int[1]= i;
			3'b010: y_int[2]= i;
			3'b011: y_int[3]= i;
			3'b100: y_int[4]= i;
			3'b101: y_int[5]= i;
			3'b110: y_int[6]= i;
			3'b111: y_int[7]= i;
		endcase
	end
endmodule

statistics after synth command.

demux_case_synth

logical description.

demux_case_show

RTL simulation.

demux_case_rtl

Gate level simulation.

demux_case_gls

for inside generate block

module fa(
	output wire sum,
	output wire co,
	input wire a,
	input wire b,
	input wire c,
	);
	assign {co, sum}= a + b + c;
endmodule

module rca(
	output [8:0] sum,
	input wire [7:0] num1,
	input wire [7:0] num2,
	);
	
	wire [7:0] int_sum;
	wire [7:0] int_co;
	
	genvar i;
	generate
		for(i= 1: i<8; i= i+1) begin
			fa u_fa_1(
				.a(num1[i]),
				.b(num2[i]),
				.c(int_co[i-1]),
				.sum(int_sum[i])
				);
		end
	endgenerate
	
	fa u_fa_0 (
		.a(num1[0]),
		.b(num2[0]),
		.c(1'b0),
		.co(int_co[0]),
		.sum(int_sum[0])
	);
	
	assign sum[7:0] = int_sum;
	assign sum[8]= int_co[7];
endmodule

statistics after synth command.

rca_synth

logical description.

show_rca_fa show_fa

RTL simulation.

for_rca_rtl_waveform

Gate level simulation.

rca_netlist_gls

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published