Skip to content

Latest commit

 

History

142 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Verilog-flyer

RTL_Design_Using_Verilog_with_SKY130_Technology_Workshop

This is a repository on RTL Design using Verilog with Sky130 Technology workshop conducted by VSD.It is a day by day log including examples from Lab sessions and Theory sessions

Table of Content

Introduction

This Workshop intends to teach basics of digital design using verilog language, various RTL coding styles,synthesis and problems faced by industry and how to solve them in Verilog using SKY130 Technology.
Some of the open source eda tools used in this Workshop are

  1. iverilog : It is Simulator which used for RTL Simulations and Gate Level Simulations.
  2. yosys : It is a open source Synthesis tool used for synthesis of RTL Design.
  3. Skywater: It is used as 130nm Standard Cell Libraries.

Day 1 Introduction to Verilog RTL Design and Synthesis

Introduction to open source simulator iverilog

Simulator
RTL design is checked adherence to the spec by simulating the design.Simulator is the tool used for simulating this design.
We have used iverilog in this workshop for simulation.
Design
Design is the actual Verilog Code or set of verilog codes which has the intended functionality to meet with the required specifications. TestBench
TestBench is setup toapply stimulus (test vectors) to the design to check its Functionality.
How the Simulator Works ?

  • Simulator looks for changes in input signal.
  • Upon change in input the output is observed.
    • If there is no change to the input there will be no change to the output.
  • Simultor looks for changes in the Value of input.

The TestBench looks something like this

day1_1

Note:

Design may have 1 or more primary inputs,1 or more primary outputs. TestBench doesn't have a Primary inputs or a primary outputs.

iverilog Based Simulation

  • Design and Testbench are given to iverilog.(As we know any simulator looks for the changes in input.)
  • The output of iverilog simulator is vcd file.
    • Here vcd stands for Value Change Dump format.
  • To view the vcd file we use another tool called GTKWave which is used for viewing the waveforms.

LAB Session
Lab 1

It is introductory lab session in which we look at environment setup for running the labs.
Before cloning we can create directory vsd and inside it another directory VLSI using the mkdir command as demonstrated below

day1_3

After creating the VLSI directory. We have to clone a repository named sky130RTLDesignAndSynthesisWorkshop which contains the required library files and verilog design files to perform the simulations and logic synthesis parts of the workshop. It can be done using by using basic linux command git clone git clone https://github.com/kunalg123/sky130RTLDesignAndSynthesisWorkshop.git as demonstrated

day1_4
After succesfully cloning it creates a sky130RTLDesignAndSynthesisWorkshop directory inside the VLSI directory. It contains various files required for this workshop you can explore the files such as my_lib which contains the library files lib and verilog_model.verilog_files which contains various verilog codes and its testbench files for all the lab expirements.

day1_5

day1_6

day1_7

Lab2
In this Lab we are introduced to iverilog and GTKwave.

Step 1 : We use the command iverilog to load the simulator follwed by the verilog file and testbench name. a.out file is created in the verilog_files folder

day1_8

Step 2 : After creating a.out file we execute it using ./a.out it is going to dump the vcd file

day1_9

Step 3 : Then we write the command gtkwave followed by the vcd file name like gtkwave tb_good_mux.vcd

day1_10

We get the following waveform of a 2:1 Multiplexer when sel = 0 output follows i0 and when sel = 1 output follows i1 in the GTKWaveform viewer

day1_11

We also observe the verilog code of the good_mux.v and tb_good_mux.v by using the command gedit (also vim and gvim can be used in systems where gvim it is installed)

day1_12

We get the good_mux.v verilog code .There are various codes to generate a MUX we have used the if statement for it

day1_13

and the testbench tb_good_mux.v we can see the instantiation of design and the stimulus generator and it runs for 300ns.

day1_14

Introduction to yosys
Sythesizer
It is a tool used for converting RTL to Netlist . We use Yosys synthsizer used in this course.
How does Yosys work ?
We have a design and .lib file and it is given to the yosys tool which gives out the netlist.

Commands for using Yosys

  • read_verilog --> To read the design.
  • read_liberty --> To read the .lib.
  • write_verilog --> To write out the netlist file.

Note

Netlist file is the representation of design in the form of Standard Cells present in the .lib .

Verification of Synthesis

The GTKwave should be as we found in the case of design simulation as Netlist is just the cell representation of design they both are basically the same.
Note

The set of Primary inputs/primary outputs will remain same between RTL design and Synthesized Netlist --> Same Testbench can be used.

Logic Synthesis
RTL design
It is the Behavioral Representation of required specification like the verilog HDL code below

module sample_code(
input clk,rst,
output result,done);

always @ (posedge clk,posedge rst)
if(rst)
---
else
---
endmodule
--------------
--------------

Synthesis

  • RTL to Gate Level Translation
  • The design is converted into the gates and connections are made between the gates.
  • This is given out as the file called Netlist.

.lib file

  • It is the collection of the logical modules
  • Includes basic gates such as And,Or,Not etc.
  • Different flavour of same gate
    • 2 input And Gat
      • slow
      • medium
      • fast
    • 3 input And Gate
      • slow
      • medium
      • fast
    • 4 input And Gate ....

Why Do we need different flavours of gates
As the combinational delay in the logic path determinesthe maximum speed of operation of digital logic circuit i.e
Tclk > TCQ_A + Tcombi+TSetup_B we need cells to work fast
And to ensure that there is no hold issue in the next flop we need slow cell and as hold time is given by
THold_B < TCQ_A + Tcombi we need cell that work slowly.
We need cells that work fast to meet performance and cells that work slow to meet Hold time. So we need different flavours of gate to meet this requirement.The Collection forms .lib.

Note

Load in Digital Logic Circuit --> Capacitance
Faster the charging/discharging --> Lesser the cell delay

  • To Charge/Discharge the capacitance fast, we need Transistors capable of sourcing more current.
  • Wider Transistor --> Low Delay --> More Area and Power.

Selection of Cells

  • Need to guide the synthesizer to select he cells that are optimum for implementation of logic design.
  • More use of Faster cells results in bad circuit in terms of area and power and also might voilet the Hold time.
  • More use of slower cells results in sluggish circuit.
  • The Guidance given to the synthesizer is known as 'contraints'.

Lab 3
Synthsis using Yosys
Step 1 : First we Invoke the Yosys by simply typing the command yosys.

day1_18

Step 2 : We are in the yosys prompt now, then we read the library using read_liberty -lib followed by path of the library it will import the library

day1_19

Step 3 : Then read the design using the command read_verilog.

day1_20

Step 4 : After the design is read successfully we use use the command synth -top for telling what module to synthsize

day1_21

day1_22

Step 5 : Now to generate the netlist we use the command abc -liberty followed by the location of .lib file.

day1_23

We can see what all internal signals ,input and output cells it has inferred

day1_24

Step 6 : Now to see the Logic it has realised type the command show

day1_25

We get the following Logic Implementation.

day1_26

In the Logic Circuit generated we observe

  • nand2_1 --> 2 input Nand gate
  • o21ai_0 --> or and inverter
  • clkinv_1 --> inverter

We get the Output from the logic circuit as y = i1 sel +i0 sel' which is the logic for 2 input Multiplexer.

Day 2 Timing libs Hierarical vs Flat Synthesis and efficient Flop Coding Styles

Introduction to .lib

We have used sky130_fd_sc_hd__tt_025C_1v80 for which meaning of each abbreviation is given below

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

Note

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

process name _ library source _ library type _ library name

Here is sample of .lib file

day2_25

day2_26

Some details which are provided in the .lib file are

  • Power
    • Internal Power
    • Leakage Power
  • Area
  • Pin details
  • Timings
  • Capacitance

Comparison between different Cells in terms of there Area


day2_24

Note

Here we observe that

area(and2_4) >area(and2_2)>area(and2_0)

power(and2_4)>power(and2_2)>power(and2_0)

Hierarchical vs Flat Synthesis

In this section we explore through the Hierarical and Flat synthesis.
Let us go through one of the examples through a Lab session to understand the difference between hierarchical and Flat Synthesis.

LAB Session
Lab 1
For this we are going to consider the multiple_modules.v code.\

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

module sub_module1 (input a, input b, output y);
	assign y = a&b;
endmodule


module multiple_modules (input a, input b, input c , output y);
	wire net1;
	sub_module1 u1(.a(a),.b(b),.y(net1));  //net1 = a&b
	sub_module2 u2(.a(net1),.b(c),.y(y));  //y = net1|c ,ie y = a&b + c;
endmodule

Step 1 : Invoke yosys using yosys

day4_5

Step 2 : Read liberty file using read_liberty

day4_6

Step 3 : Read verilog file using read_verilog

day2_27

Step 4 : For starting the synthsis process use synth -top and also observe the inferences

day2_28

day2_29

Step 5 : Now to map to standard cell we use abc -liberty

day2_30

Step 6 : Now to see the Logic design we give the command show

day2_31

day2_32

We observe that it does not show 'and' gate or 'or' gate but instead shows the 2 sub modules u1 and u2.This is what we call the Hierarical design.

Step 7 : Now to get the netlist we give the write_verilog -attr command

day2_33

day2_34

We see that all the hierarchies are preserved and to avoid stacked PMOS the logic is implemented using NAND gates.

Note

Stacked PMOS is always bad because PMOS has poor mobility and to improve this we have to make the cell alot wide cell to get good logical effort.

Step 8 : We use flatten to write out he flat netlist.And again use write_verilog -attr to get the flattened netlist.

day2_35

In this case the hierarchy is not preserved but are flattened out. We can see the logic diagram flattened as below

day2_36

We do not see u1 and u2 but the sub-modules completely flattened.

Now to do a sub module level synthesis we follow the same procedure until Step 3

Step 4 : Instead of synth -top to get sub module level syntheies we give the command synth -top sub_module1

day2_37

again follow the Step 5 and Step 6.We get the logic diagram of sub_module1.

day2_38

day2_39

Why we use Sub Module level synthesis
  • When we want to use multiple instances of the same module.
  • We want to do divide and conquer approch if we have a massive design.

Note

Synth -top controls which module to synthesis.
flatten is used for flattening the netlist.

Various Flop Coding Styles and Optimization.

Let us understand this concept using an example.
Take dff_asynres.v

module dff_asyncres ( input clk ,  input async_reset , input d , output reg q );
always @ (posedge clk , posedge async_reset)
begin
	if(async_reset)
		q <= 1'b0;
	else	
		q <= d;
end
endmodule

Now let simulate it using the same steps above

After Simulation we get the following waveform

day2_40

We observe from the waveform that when reset went zero the output q did not wait for the rising edge of the clock to change its value to 0 it immediately became 0.

Now let us take the dff_syncres.v

module dff_syncres ( input clk , input async_reset , input sync_reset , input d , output reg q );
always @ (posedge clk )
begin
	if (sync_reset)
		q <= 1'b0;
	else	
		q <= d;
end
endmodule

Now let simulate it using the same steps above

After Simulation we get the following waveform

day2_41

We observe that after output q waits for rising edge of clk to change the value after reset is high.

Day 3 Combinational and sequential optimization

Introduction to Logic Optimisation

Logic Optimisation contains mainly 2 parts

  1. Combination Logic Optimisation
  2. Sequential Logic Optimisation

Combinational Logic optimisation

  • We need combinational logic optimisation to squeeze the logic to get the most optimised design
    • Mainly for Area and Power Saving
  • Constant Propogation is one of the technique used for Combinational Logic Optimisation
    • It is a Direct Optimisation in which the value of one input is propogated to the next stage to get the most optimised logic.
  • Another Technique Used is the Boolean Logic Optimisation in which we use and other tools to get the most optimised logic.

Sequential Logic optimisation

In Sequential Logic Optimisation there are 2 Techniques

  1. Basic
  • Sequential Constant Propogation
    • Some of the Sequential design in which D input is tied off the Squential Constant is propogated to give Q pin as a Constant and gives the most optmised design of the Squential Circuits.
    • The Sequential Design in which Q does not remains as constant cannot be optimised and flop needs to be retained in the circuit.
    • Note

      Every flop in which the D input is tied off is a sequential constant for the flop to become sequential constant the Q pin should always take a constant value.

  1. Advanced (not a part of the workshop)
  • State Optimisation
    • Optimisation of unused states.
  • Retiming
    • It is a Technique to improve the Performance of the Circuit.
  • Sequential Logic Cloning (Floor Plan Aware Synthesis)
    • It is done when we are doing a Physical Aware Synthesis.

LAB Session
Lab 1
Combinational Logic Optimisation
In this Lab we are going to use all the 'opt_check' files which can be found by typing the commandls *opt_check*
Let us first see the code for opt_check.v and opt_check2.v by opening it using gedit

day3_1

The opt_check is simplified as y = ab (And Logic gate)
The opt_check2 is simplified as y = a+b (Or logic gate)

Step 1 : Now we invoke Yosys using the command yosys
Step 2 : Load the Libraries using read_liberty -lib
Step 3 : Now read the verilog file using read_verilog

day3_2

Step 4 : Now synthesizing the device using synth -top

day3_3

day3_4

Step 5 : The Command to do the constant propogation and all the optimisation is opt_clean -purge

day3_5

Step 6 : Now Link it to the liberty using abc -liberty and then show

day3_6

As we already concluded earlier for opt_check.v we are getting an And gate we see the same being implemented.
Similarly we check the implementation for opt_check2.v.

day3_7

As we already concluded earlier for opt_check2.v it should be a 2 input Or gate we get the same being implemented.
As Or gate involves Nor gate and it uses a stacked PMOS which is bad due its mobility and various other reasons the so the Tool does a Nand Realisation of Or gate.It a inverter -inverter followed by a Nand.

day3_8

Similarly we observe opt_check3.v.

day3_9

We evaluate that y = abc (3 input And gate).We apply the same process as above for opt_check.v and opt_check2.v to get the optimised output.

day3_10

As we already concluded earlier for opt_check3.v it should be a 3 input And gate we get the same being implemented.

Similary We observe multiple_modules_opt.v.

day3_11

We get the following result after we flatten the multiple_module_opt

day3_12

The resulting Circuit is Enlarged below
day3_13


Sequential Logic Optimisation
Lab 2
In this Lab we are going to use all the 'dff_const' files which can be found by typing the commandls *dff_const*
Let us take the dff_const1.v and dff-const2.v and open it

Here is the Verilog code for both
day3_14

image

Step 1 : Let us simulate before synthesizing for that we use iverilog and then excute the a.out file to get vcd file.

image
Step 2 : Use gtkwave to get the waveform

image

We observe that even after rst has become low Q waits for rising edge of the clock to go high. This circuit will infer a flop.

image

Now we Compare it with dff_const2.v

We see that Q does not depend upon clk unlike in the case of dff_const1.v

image

Now let us Synthesis both the files
As this is a sequential circuit while synthesis we have to give one more command dfflipmap for proper mapping of sequential cells in the library.

For dff_const1.v
image

image

image

We get the following logic design

image

The standard cell library is expecting the reset to be active low but we have coded a active high reset so the tool is inferring a inverter.

Now we synthesis dff_const2.v file

We observe that it has not inferred any flop in this case contradictory to dff_const2.v

day3_22

image

Now let us take dff_const.v file

day3_23

By observing the code we see that Q1 and Q both cannot be optimized so both the flops will be present in the Circuit.
So first let us simulate our design

day3_24

We can clearly see that both q and q1 do not remain constant and both change on the rising edge of the clock so the cannot be optimized

day3_25

Now let us go ahead and do the synthesis of the circuit

day3_26

We can clearly see it infers 2 flops

day3_27

day3_28

From the Logic diagram we have confirmed that 2 flops and also the 1st flop is a reset flop and the 2nd flop is a set flop.
day3_29

Not every flop which is having constant at the input gets optimized we also need to look at set and the reset connections and see if q is constant or q values is going to change.\

Lab3
Sequential Optimisation using Unused Output optimisation.
So let us consider the code counter_opt.v

day3_30

When we look at code we see that it is a up-counter whenever there is reset it reset otherwise its 3 bit up-counter.
The output of the circuit is count[2:0] but q = count[0]. count[1] and count[2] are unused. So this are not required in the logic diagram.
Let us synthesis this code.

We clearly see only 1 flop is inferred even if it is 3 bit counter it should have inferred 3 flops

day3_31

As it is a sequential circuit we should use dfflibmap -liberty ../my_lib/lib/<location of .lib file>

day3_32

We can clearly see that there is only 1 flop in the circuit design.We see count[0] is toggling so the output q is given to the inverter and feededback to the d pin.

day3_33

So we can conclude that any logic which is not resulting in any primary output is optimised away.
Now let us consider count_opt2.v
day3_34

We have tweaked the code slightly from count_opt.v as we have changed assign q = (count[2:0] == 3'b100);
Now we expect that as all outputs are used it should have 3 flops to be present in the logic circuit.
Let us synthesis the code.

day3_35

From the Figure above we clearly see that 3 flops are inferred here.

day3_36

The logic other than the flops is the incremental logic.
The given Logic diagram contains 3 flops .We get the expression of q = count[2] . count[1]'.count[0]' so it is using all the primary outputs so it uses all the flops.
So we conclude that all the outputs that have no role in determining the primary output are optimized away using Unused Output Optimisation.

Day 4 GLS blocking vs non blocking and Synthesis Simulation mismatch

Introduction to GLS

What is GLS

  • It stands for Gate Level Simulation.
  • Running the Test Bench With Netlist as design under Test.
  • Netlist is logically same as the RTL Code.
    • Same testbench will align with the design.

Why GLS ?

  • Verify the LOgical Correctness of the design after synthesis.
  • Ensuring the Timing of design is met
    • For this GLS needs to be run with delay annotation.

GLS using iverilog

  • We give the Netlist,Gate Level Verilog Models and Testbench to the iverilog.
  • Netlist has all the standard cell instantiated and the meaning of standard cell is conveyed to the iverilog by Gate Level Verilog Models.
  • After which it has the same flow giving the vcd file using which we can generate Waveform using GTKwave.

Note

If the gate level models are delay annotated, then we can use GLS for timing validation.

Synthesis Simulation Mismatch

-Suppose we have a Netlist

  • and u_and(.a(a),.b(b))
  • or u_or (.a(a),.b(b))
  • Now to understand this we Gate level Verilog Models.They can
    • Timing Aware -->validate functionality + timing both
    • Functional --> validate functionality
Why Synthesis Simulation Mismatch happens ?
  • Missing Sensitivity List
  • Blocking Vs Non-Blocking Assignments
  • Non Standard verilog Coding

Missing Sensitivity List

Let us consider a verilog Code

module mux(
input i0,input i1
input sel,
output reg y
);
always @ (sel)
begin
   if (sel)
            y = i1;
   else 
            y = i0;
            
end
endmodule
  • Simulator works based on activity i.e the output will change only when there is a change in the input.
  • In the Code given the always block is evaluating only when the sel is changing. As the always block is not sensitive to the changes in i0 and i1.
  • Only when there is a change in sel the always block gets evaluated.
  • When we simulate it acts as a latch.But when we synthesis it will act as a Mux.
  • This is called missing elements of sensitivity list.
  • Now let us consider another code
module mux(
input i0,input i1
input sel,
output reg y
);
always @ (*)
begin
   if (sel)
            y = i1;
   else 
            y = i0;
            
end
endmodule
  • In this case always is evaluated when any signal changes.
  • So now always block will be evaluated for i1 as well as i0
  • This will simulate as Mux and also be synthesised as Mux.

Blocking and Non Blocking Statements

  • Inside always block
    • If we are using '=' to make assignments
      • Executes the Statement in the order it is written.
      • So the first statement is evaluated before the second statement.
    • If we are using '<=' to make assignments
      • Executes all the RHS when always block is enteredand assigns to LHS
      • Parallel Evaluation

Caveats with Blocking Statements

  • Let try to create a shift register
module code (input clk,input reset,
input d,
output reg q);
always @ (posedge clk,posedge reset)
begin
if(reset)
begin
        q0 = 1'b0;
        q = 1'b0;
end
else
        q = q0;
        q0 = d;
        
end
endmodule
  • In this case q0 is assigned to q and then d gets assigned to q0.So we get 2 values.
  • So it has 2 flops.
  • Now let change the code slightly
module code (input clk,input reset,
input d,
output reg q);
always @ (posedge clk,posedge reset)
begin
if(reset)
begin
        q0 = 1'b0;
        q = 1'b0;
end
else
        q0 = d;
        q = q0;
                
end
endmodule
  • In this case q0 is assigned d the q0 gets assigned to q
  • So it is as if q is getting the value of d which means it only has 1 flop
  • But if we write it with non blocking statements
module code (input clk,input reset,
input d,
output reg q);
always @ (posedge clk,posedge reset)
begin
if(reset)
begin
        q0 <= 1'b0;
        q <= 1'b0;
end
else
        q0 <= d;
        q <= q0;
                
end
endmodule
  • So we conclude that non blocking statements should be used to write Sequential Circuit Code.

Now Let us look at another code.
Our aim is to create a circuit with output as y = (a + b).c

module code (input a,b,c
output reg y);
reg q0;
always @ (*)
begin
        y = q0 & c;
        q0 = a|b ;
        
end 
endmodule
  • We assign the value of y with q0 and with c first and then assign q0 as a or b
  • So we see that q0 value is the old q0 value and is not updated.
  • When we simulate old q0 value will mimic a delay or flop but when we synthesis there will not be a flop.
  • Now let us change the order of block statement
module code (input a,b,c
output reg y);
reg q0;
always @ (*)
begin
        q0 = a|b ;
        y = q0 & c;
        
        
end 
endmodule
  • In this case there will not be any delay as the q0 is updated first then used.
  • When we simulate it will work as the given circuit.
  • In both cases above when we synthesis we get the desired circuit but in first case the simulation result differ with synthesis results.

Because of these kind of issues it becomes very important to run GLS on the Netlist and match with the expected output and see if there are no Synthesis Simulation Mismatches.

LAB Session
Lab 1
In this Session we are going to see how to invoke GLS and run some basic experiments with GLS. To Run GLS we need

  • Netlist
  • Verilog Models
  • Testbench

Let us consider the file ternary_operator_mux.v

  • Ternary Operator
    • <cond> ? <T>:<F>
    • If the condition is true the 'T' part is executed and if it is false 'F' part is executed.

Now let us have a look at the code of ternary_operator_mux.v

day4_1

The code given is basically a Mux implemented using a ternary operator.
Now let us first do the RTL simulation.
For that we first invoke iverilog and then execute the a.out file using ./a.out

day4_2

After getting the vcd file use gtkwave <file name> to see the simulation.

day4_3

day4_4

Here we observe it is clearly following the behaviour of 2:1 MUX.
Step 1 : Now let us systhesis for which we invoke yosys

day4_5

Step 2 : To Load the .lib file we use the command read_liberty -lib ../my_lib/lib/...
day4_6

Step 3 : Then we read the verilog file using read_verilog <file name>

day4_7

Step 4 : Now let us start the synthesis process using synth -top <file name>

day4_8

day4_9
We can clearly see that 1 Mux has been infered.
Step 5 : Now let us use the abc -liberty ../my_lib/lib/<.lib file>

day4_12

Step 6 : and then use show to get the logic diagram generated.

day4_10

This is the Logic Diagram generated

day4_11

If we Solve the logic diagram we get the result as y = sel .i1 + sel'.i0.Exactly

Now let us do the GLS.
Step 1 : Open iverilog with verilog models,netlist, and testbench using the command iverilog. In the lib folder you will find the verilog models of the standard cells.Execute a.out file using ./a.out

day4_13

Step 2 : Now as the vcd file is generated.Now we use GTKwave to observe the simulation by giving the command gtkwave

day4_14

We know the difference GLS and RTL as in GLS under uut there no files but in GLS we 6 , 7 , 8.

day4_15

Now let us observe the simulation. It is clearly following the MUX output.

day4_16


Now Let us take another example of bad_mux.v

day4_17

We can observe that in this case the always block going to be evaluated only upon changes in sel.
So in simulation it we work as some kind of flop.
Now let us carry out the RTL simulation using the steps we followed for simultion above

Let us observe the simulation results by giving the command gtkwave

day4_20

day4_21

So we can observe that if there is no activity on the output does not change.
This simulation shows as if the Mux is acting like a flop .

Now let us synthesis and see what happens.
Step 1 : For synthesis we invoke yosys

day4_5

Step 2 : To Load the .lib file we use the command read_liberty -lib ../my_lib/lib/...
day4_6

Step 3 : Then we read the verilog file using read_verilog <file name>

day4_22

Step 4 : Now let us start the synthesis process using synth -top <file name>

day4_23

Here are some details of which gates are inferred

day4_24

So we see it infers MUX not a latch.

Step 5 : Now let us use the abc -liberty ../my_lib/lib/<.lib file>

day4_25

Step 6 : Now to get the netlist file we use write_verilog

day4_26
Now let us do the GLS.
Step 1 : For that we need to open iverilog with verilog models,netlist, and testbench using the command iverilog. In the lib folder you will find the verilog models of the standard cells.Execute a.out file using ./a.out

day4_27

Step 2 : Now we use GTKwave to observe the simulation by giving the command gtkwave

day4_28

day4_29

Now we compare the simultion with the RTL design and after synthesis Netlist simulation.

day4_30

In the GLS simulation the activity on i1, i0 has been reflected on output whereas in the RTL simulation the output was effected by only the sel.
This is called Synthesis Simulation Mismatch.


Lab2
In this Lab we will continue to see the Synthesis Simulation Mismatch.
Now Let us take a blocking code example.

image

The aim of this code is to get the d = (a+b).c

Now because of the blocking statement first d will be assigned (x and c) then x = a or b will be executed.
So by the time the statement for d is getting evaluated we have the previous value of x .
So when we simulate it , it will look as if x is a flopped output.

Now let us do the RTL simulation using the steps we followed for different simulations

Let us observe the simulation result by giving the command gtkwave

day4_34

day4_35

We see from the simulation that the value of d = 0 but it is coming out to be 1 because the past value of (a or b) is 1 in the cycle before that value is getting anded with the present value of c.

Now let us synthesis using the steps we followed in various examples above and see what happens.
After synth -top

day4_37

Here are some details of which gates are inferred

day4_38

Step 6 : Now let us use the abc -liberty ../my_lib/lib/<.lib file>

day4_25

Step 7 : Now to get the netlist file we use write_verilog

day4_39

Before going to the GLS let us look at what logic we got by giving the command show.

day4_40

We clearly see that it is very straight forward with or 2 and gate used and no latches in the design.

Now let us do the GLS using the step we followed in above example

Let us observe the simulation results we got

day4_42

day4_43

Now we compare the simultion with the RTL design and after synthesis Netlist simulation.

day4_44

We can clearly see that the value of d = 0 for the same case where a = 0,b = 0 and c = 1.
This is Synthesis Simulation Mismatch caused by Blocking statement.
Note

Please be very carefull before using blocking statements for Sequential Circuits.

Day 5 Optimization in synthesis

In this section we will study about if and case Statement and there uses as well as there disadvantages.

If Statement

  • if is basically a priority logic
if<cond>
begin
.....
.....
end
else
begin
.....
.....
end

and if-else statement

if<cond>
begin
.....
.....
end
else if<cond2>
begin
.....
.....
end
else if<cond3>
begin
.....
.....
end
else
begin
.....
.....
end

The Hardware Implementation of these statement is as shown in the image below. day5_37

Caution with if statement

  • inferred latches --> it is a bad coding style and occurs due to incomplete if statement
    • Sometimes we need the inferred latch like in the case of counters if there is no enable the counter should latch on to the previous value.

Note

In Combinational Circuit we cannot have a inferred latch. Whatever variable you are trying to assign should be register variable.

Case Statement

  • if and case statement are used inside the always block
reg y
always @ (*)
begin
	case(sel)
		2'b00:begin
		      ....
		      end
		2'b01:begin
		      ....
		      end
		      .
		      .
		      .
	endcase	
  • Hardware implementation of Case statement is a MUX.

Caution with case statement

  • inferred latches --> it is a bad coding style and occurs due to incomplete case statements
    • The solution for inferred latches is code Case with default condition
    • With default condiation it avoids the inferred latches

LAB Session
Lab 1
In this session we will use the if statement and incomplete if statement.

We first take the code incom_if.v

module incomp_if (input i0 , input i1 , input i2 , output reg y);
always @ (*)
begin
	if(i0)
		y <= i1;
end
endmodule
  • We observe that in this code there is no else statement. Now let simulate and synthesis it.

    Step 1 : Use iverilog to generate the a.out file for simulation

    day5_1

    Step 2 : Execute the a.out file to get the vcd file

    day5_2

    Step 3 : Use gtkwave to view the waveform of gcd file

    day5_3
    We observe that whenever i0 is low the value of y is latched as it is constant.

    Now let us go for synthesis.

    Step 1 : Invoke yosys using yosys

    day4_5

    Step 2 : Read liberty file using read_liberty

    day4_6

    Step 3 : Read verilog file using read_verilog

    day5_4

    Step 4 : For starting the synthsis process use synth -top and also observe the inferences

    day5_5

    day5_6

    Step 5 : Now to map to standard cell we use abc -liberty

    day5_7

    Step 6 : Now to see the Logic design we give the command show

    day5_8

    It is a D latch. This is the danger of incomplete if we get a latch instead of mux. This is called as inferred latch.

    Lab 2
    Now let us see the case statement and incomplete case statements.

    We first take the code incom_if.v.
module incomp_case (input i0 , input i1 , input i2 , input [1:0] sel, output reg y);
always @ (*)
begin
	case(sel)
		2'b00 : y = i0;
		2'b01 : y = i1;
	endcase
end
endmodule
  • We observe that there is no case for when sel = 10 and 11. Now let simulate and synthesis it.

    Step 1 : Use iverilog to generate the a.out file for simulation

    day5_9

    Step 2 : Execute the a.out file to get the vcd file

    day5_10

    Step 3 : Use gtkwave to view the waveform of gcd file

    day5_11

    When the Value of sel = 10 and 11 it latches on to the value of previous state.

    Now let us go for synthesis.

    Step 1 : Invoke yosys using yosys

    day4_5

    Step 2 : Read liberty file using read_liberty

    day4_6

    Step 3 : Read verilog file using read_verilog

    day5_12

    Step 4 : For starting the synthsis process use synth -top and also observe the inferences

    day5_13

    day5_14

    Step 5 : Now to map to standard cell we use abc -liberty

    day5_15
    Step 6 : Now to see the Logic design we give the command show

    day5_16

    There is a D latch in the circuit.This is the danger of incomplete case we get a latch instead of mux. This is called as inferred latch.

    If we consider the comp_case.v
module comp_case (input i0 , input i1 , input i2 , input [1:0] sel, output reg y);
always @ (*)
begin
	case(sel)
		2'b00 : y = i0;
		2'b01 : y = i1;
		default : y = i2;
	endcase
end
endmodule
  • As there is a default statement there will be no latch involved in this design. Now let simulate and synthesis it using the same steps above and conclude our finding.

    After Simulation we get the following waveform

    day5_17

    This waveform clearly suggest that there is no latch involved and it a pure MUX circuit.

    After Synthesis we get the following design

    day5_18
  • Clearly we can see there is latching action when sel = 10 and 11 the output is i2.

If we consider the partial_case_assign.v

module partial_case_assign (input i0 , input i1 , input i2 , input [1:0] sel, output reg y , output reg x);
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
  • Even if assign default statement it does not gurantee that latches are not inferred. Now let synthesis it using the same steps above and conclude our finding.

    After Synthesis we get the following design

    day5_19

  • Clearly we see there no latch in the path of x but in the path of y there is latch as condition for 01 is not defined. If we consider bad_case.v

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

endmodule
  • In this case for sel = 11 there are 2 options available i.e y=i2 and y=i3 this will cause some issue while simulating and synthesising it. Now let us simulate and synthesis it using the same steps above and conclude our finding.

    After Simulation we get the following waveform

    day5_20

    The waveform clearly suggests that when sel = 11 it is getting confused and latching on to the value '1'as both condition 10 and 11 both are matching.

    After Synthesis we get the following design

    day5_21

    No latch inferred for the design

    day5_22

    Now Let us do the GLS

    Step 1 : Use write_verilog to the netlist

    day5_23

    Step 2 : Open iverilog with verilog models,netlist and testbench using the command iverilog. In the lib folder you will find the verilog models of the standard cells.Execute a.out file using ./a.out

    day5_24

    Step 3 : Now we use GTKwave to observe the simulation by giving the command gtkwave

    day5_25
  • We can clearly see that in this wave form it is not getting confused and when sel = 11 it follows i3.

Looping Constructs

There are 2 types of loops

  • For Loop
    • Used inside always block.
    • Used for evaluating expressions.
    • Not used for instantiating hardware.
  • Generate For Loop
    • Used outside always block.
    • Cannot be used inside always
    • Used for instantiating hardware

Lab 3

For Statement

Let us understand the for statement with the use of some examples.

Let us consider mux_generate.v

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

Now let simulate it using the same steps above

After Simulation we get the following waveform

day5_26

  • It is clearly behaving as a 4x1 Mux.If we write the same code using case statement the code and the value of mux input is increased the gets too complicated but using the for statement we are able to write it easily.

Now let us consider demux_case.v and demux_generate.v and compare them
demux_case.v

module demux_case (output o0 , output o1, output o2 , output o3, output o4, output o5, output o6 , output o7 , input [2:0] sel  , input i);
reg [7:0]y_int;
assign {o7,o6,o5,o4,o3,o2,o1,o0} = y_int;
integer 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

demux_generate.v

module demux_generate (output o0 , output o1, output o2 , output o3, output o4, output o5, output o6 , output o7 , input [2:0] sel  , input i);
reg [7:0]y_int;
assign {o7,o6,o5,o4,o3,o2,o1,o0} = y_int;
integer k;
always @ (*)
begin
y_int = 8'b0;
for(k = 0; k < 8; k++) begin
	if(k == sel)
		y_int[k] = i;
end
end
endmodule
  • We observe that demux_generate.v is using for statement because of which the the lenght of the code is decreased.

Now let simulate demux_case.v using the same steps above

After Simulation we get the following waveform

day5_27

  • We clearly observe from the wave the when sel = 1 o1 follows the input ,sel = 2 o2 follows the input and so on it clearly behaves as 1:8 demux.

Now let simulate demux_generate.v using the same steps above

After Simulation we get the following waveform

After Simulation we get the following waveform
day5_28

  • Both the Waveforms are exactly the same the difference is just in the coding.
  • demux_generate.v is more elegant code than demux_case.v

For generate Statement

Let us understand the for generate statement with the use of some examples.

So Let us consider rca.v and fa.v
rca.v

module rca (input [7:0] num1 , input [7:0] num2 , output [8:0] sum);
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]),.co(int_co[i]),.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

fa.v

module fa (input a , input b , input c, output co , output sum);
	assign {co,sum}  = a + b + c ;
endmodule
  • There is no always block used in thesen codes.
  • The variable we used here is called the genvar not an integer.

Note

Rules for addition

  • N and N bit number --> Sum will be N+1 bit
  • N and M bit number --> Sum will be Max(N,M)+1 bit

Now let simulate using the step followed above. In this case before compiling rca.v we call fa.v to specify where the defination of fa is present.

day5_29

After Simulation we get the following waveform

day5_30

Observations

Some of the observations made during the lab session and group discussion of the workshop

  • While reading the library file if we miss the keyword -lib we get this kind of error

    • day5_31
    • So we conclude that -lib keyword is used for identifying logic operations
  • In the synthesis process if we do not map it to standard cell using abc -liberty and instead give the command show

    • for example take ternary_operator_mux.v
    • without abc command and directlyshow we get
    • day5_32
    • with abc command and then show we get
    • day5_33
    • So we conclude that abc links the module to the basic logic gate using which it the module is formed.
  • When we want to see the netlist we open the _net.v file

  • write_verilog -noattr < _net.v file_name> after which if we read the file using gedit we get the netlist file

    • if we do not write -noattr we get a small difference
    • day5_36
  • dfflibmap is used to map the sequential circuit codes with standard cell library file

  • Every new version of the yosys tool comes with its own optimization techniques.So many times the implementations will differ in dfferent version.

Acknowledgements

References

About

This is a repository on RTL Design using Verilog with Sky130 Technology

Resources

Stars

2 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors