Aimp Verilog - Notes
Aimp Verilog - Notes
- behavioural
- procedural block
- always block
- initial block
- for output reg variable is declared
- Structural / gate
- we actually deal with primitive gates ( in built )
- Ex : and , or , not , nand , xor , nor , exnor
- we also can instantiate
- possible
- Syntax for using primitive gates
and a1 (Destination,Source);
and -> name of the gate
a1 -> instance name
Destination-o/p
Source-i/p
- Switch level
- Transistors
We are not going to deal ?
// Behavioural level
module ha (a,b,sum,carry);
input a,b;
output reg sum,carry;
always @ ( )//always @(*)// Vaibhav will answer
begin
sum=a^b;
carry=a&b; // try {carry,sum}=a+b; Assignment
end
endmodule
// Structural
module hs(a,b,sum,carry);
input a,b;
output sum,carry;
xor x1 (sum,a,b);
and a1 (carry,a,b);
endmodule
a=1'b1;// 1
b=1'b1;// 1
{a,b} = 2'b11; // 11
{a,b} = $random;
// 05 Nov
Verilog Basics
Necessity
- To model hardware ?
- Why can't we code or design using any other languages like c,c++ ?
- clk , that's where we are failing to model using any other languages (c++ ,
c ,python ,ruby , j ava)
What is comment ?
- Not read by compiler
- A single line comment starts with // and tells Verilog compiler to treat
everything after this po in t to the end of the line as a comment.
- A multiple-line comment starts with /* and ends with */ and cannot be nested
z -> -High impedance level (High resistance with min current flow)
-float condition (we have port , if port is neither driven by 1 nor 0)
-open wire (nothing is connected)
- Data types
-Net
- wire
- default value z
- Why z
- open wire , high impedance
- wand
- U should understand either by going through youtube or anywhere else
wand -> wire and
why do we use?
- whenever we have circuits with anded behaviour
- whenever we have 2 signals that has to be given to to an i/p
- we and it and we give
-Reg
- reg
- default value is x
-> reg will not be knowing the value (0 or 1)
- integer
- signed ( acn take up +ve and -ve )
- 32 bit value
- default value x
- real
- holds decimal point
- default value 0
- time
- 64 bit value
- unsigned
- default value is x
- $time - > indicates what? -> Current simulation time
- string
- what is string
- stores characters in " " (double quotes)
- reg [8*5:1] name ;
initial
begin
name = "vlsi";
- Formula is for vector length
| [MSB - LSB] | + 1
- System Tasks
$display
$monitor
$value$plusargs
$finish
$stop
$strobe
$write
$random
$urandom_range
$time
Nested condition
- if ()
-if ()
- else if ()
- else
- else
-if()
-else()
// 7/11/22
- Literals
- Rules to assign values to a variable
integer a = 32'h0;//correct
integer a=h;//wrong
reg [8*1] name;
name = "V";//yes
name = "v";//yes
name = v;//No
- Identifier
name_a;//yes
123_name;//no
$_name;//no
- Keywords
reg , wire
- Vectors
- wire a0;
- wire a1;
- wire a2;
- wire a3;
- wire a4;
- wire a5;
// instead
- MSB - 6
- LSB - 1
wire [1:6]a;
- MSB - 1
- LSB - 6
-reg [13:1]a;
- bits ? -> |MSB-LSB|+1 = |13-1|+1=13 bits
- reg [-3:-1]a;
- bits? -> 3 bits
WHich is MSB
-> -3
Which is LSB
-> -1
- reg [3:1]a;
- bits -> 3 bits
MSB -> 3
LSB -> 1
- reg [0:3];
Bits -> 4 bits
MSB - 0
LSB - 3
- reg [3:0];
Bits -> 4 bits
MSB - 3
LSB - 0
- wire [3:0]a;
- 4 wires - 4 bits
- Copy one vector value to another vector
-> reg [3:0]a;
-> reg [14:1]b;//14 bits
a=4'b1111;//4'b1111
- replicate -> repeat
b=a;//copy value of a to b whole vector copy
output :- b= 00_0000_0000_1111
b[14:11]=a;//4 bits ill be copied , other bits will be having x
output :- b= 11_11xx_xxxx_xxxx
- Vector slicing
-> b[10:7]=a[3:1];//possible? -> yes
output -> b = xx_xx01_11xx_xxxx
- Parameters
parameter WIDTH = 12;
generalisation of a constant
- assigned b/w module and endmodule
reg [WIDTH-1:0]a;
WIDTH = 50
reg [50-1:0]a;
// WIDTH--> 30,56,17...ect
- Arrays
- Syntax
<data_type><name_array><[]>
- integer
-> Ex : integer a[1:0];
-> Ex : integer a[1:0][1:0];
- wire
-> Ex : wire a[1:0];
-> Ex : wire a[1:0][1:0];
-> Ex : wire [1:0] a [1:0];
-> Ex : wire [1:0] a [1:0][1:0];
- real
-> Ex : real a[1:0];
-> Ex : real a[1:0][1:0];
-> integer a[1:0] ;// array -> memory -> 32 bits of 2 locations
-> is this a parameterisable
-> real ? // parameterisable -> memory // non synthesizable and also
not possible
Ex :
parameter DEPTH = 10;
real a[DEPTH-1:0];// 64 bits , 10 locations
- reg arr[10:0];
- arr[0] will hold a single bit?
<variable_name>RHS
- arr[0] -> this is the way of accessing
- Memory
parameter WIDTH = 4;
or
parameter width = 4;
parameter DEPTH = 5;
- reg [WIDTH-1:0]arr[DEPTH-1:0];
// reg [4-1:0]arr[5-1:0];
reg [3:0]arr[4:0]
DEPTH -> Array
WIDTH -> Vector
-> parameter is constant within the module (b/w module and endmodule)
module eg1();
parameter size = 10;//size=10
initial
begin
$display("size=%0d",size);
end
endmodule
module design();
eg1 #(.size(30)) i1();//now the eg1 size=30
eg1 #(.size(15)) i2();//size =15
eg1 i3() ;//size =10
endmodule
module design();
eg1 #(30) i1();//now the eg1 size=30
eg1 #(15) i2();//size =15
eg1 i3() ;//size =10
endmodule
Ex :-
module eg1();
parameter size = 10;//size=10
initial
begin
$display("size=%0d",size);
end
endmodule
module design();
deparam eg1.size = 100;
endmodule
size = WxD
size = 2**14
width = 2*3
depth = ?
depth = size/width
depth = 2**11 x 2**3 / 2**3
depth = 2**11
- reg [7:0]mem[0:2047];
- declare a memory of size 5kB with depth 5 bytes , width?
- declare a memory of size 5kB with width 5 bytes , depth ?
- declare a memory of depth 5 bytes , width 8 bytes , size ?
-> $display () -> display the current value irrespective of changes in i/p's
-> $monitor () -> display the current value respective of changes in i/p's
// functionality c= a+b;
initial
begin
-> based on changing the sensitivity , it will display
repeat(10)
begin
{a,b}=$random; // 32 bits
#1;
$display();
end
// 08/11/2022
Almost all Verilog data types are 4-state, which means they can take on 4 values:
0 , 1 , x ,z
- Bit Select
- selcting a single bit position in a vector and assigning value
Ex : reg [31:0]addr;
bit select -> addr[1]=0;
- Part Select
- Selecting a multiple bit positions and assigning a value
- Ex -> reg [31:0]addr;
part select -> addr[15:7]=9'hAB;
- reg [1:0]busA;
- reg [5:1]busB;
assume -> copy -> busA[1:0]=busB[5:1];//copy happens by position not by
index
busA[0]=busB[1];
busA[1]=busB[2];
*- Vector Operations
- Arithmetic operations
reg [4:0]busA;
reg [2:0]busB;
reg [9:0]busC;
busC= busA * busB;
-> a=32'hFFFF_FFFF;
-> b=32'hABCD_FFFF;
-> a && b;//logical
-> b = ~& a;//
- Operators
- Logical
-> &&, ||, !
-> logically true(1) or false(0) or unknown (x)
- Bitwise
-> & , | , ~ , ^ , ~^
-> bit by bit operations
- Unary reduction
-> & , | , ^ , ~^ , ~& , ~|
-> single operator , operand
- Shift operators
-> << , >> , >>> , <<<
-> arithmetic right shift -> / 2 (divide by 2)
-> arithmetic left shift -> x 2 (multiply by 2)
- Concatenation operator
-> {}
- Replication operator
->{n{}}
- Relational
-> return 0,1,x
- Equality
-> Logical (== , !=) -> return 0,1,x
-> case (===,!==) -> 0,1
- Conditional(Ternary)
-> Y=sel?A:B;
Ex:
reg [31:0] temp;
temp1= 20;
temp= 20;
temp =30;
Can I Store the values
temp[1]=20;
temp[2]=30;
temp[31]=40;
avg =
- we don't have any slicing like bit / part select
a[0]
a[1]
a[2]
a[3:2]=a[1:0];// not possible
- We have dimensions in array
- Real time example -> memory
reg [31:0]addr1;
addr1 = 32'hABCD;
reg [31:0]addr2;
addr2 = 32'hEEEG;
- Limitations of array
- Can't access multiple array indices at the same time,array slices or
entire array at once
reg [1:0]mem[10:0]
array -> 11 location
vector -> 2 bits
Ex :- mem[10:8]--> not possible since we are accessing 3 indices
at a time.
Tool commands
run.do
-> The file contains all these
-> vlog ts.v -> compilation , i'll have to give name of testbench
file
vsim ts // elaboration , i'll have to give module name
add wave * // add the waveform
run -all // simulation ,run till the end of simulation
vlog tst.v
vsim -novopt -suppress 12110 tst
add wave -position insertpoint sim:/tst/*
run -all
- Compiler Directives
- `define
- define text macros in verilog
Ex: -
`define WIDTH 50 ->global scope -> check this and let me know
-> define -> this in the module
-> outside the module
`define WIDTH 50
module ha(a,b,s,c);
parameter WIDTH = 50;->within the module
input [WIDTH-1:0]a,b; // a is of size WIDTH-1 : 0 and b is also
WIDTH-1:0
output reg [WIDTH-1:0]sum;
reg c;
always@(*)
begin
{c,s}=a+b;
end
endmodule
- `include
- Ex :- I have to include ha.v file in my test bench file
`include "ha.v"
Arrays
-> reg , wire , integer , real
Ex : reg a[1:0];//each location will hold how many bits -> 1
Ex : wire a[1:0];
Ex : integer a[1:0];// since integer is of 32 bits , each location will
hold 32 bits
Ex : real a[1:0];//floating values can be stored , how many bits? -> 64
or 1 bit
-> single dimension array
Ex : reg a[3:0];//4 locations with 1 bit storing capability
Ex : reg a[0];// 1 location with 1 bit storing capability
-> two dimensional array
Ex : reg a[3:0][1:0];
-> memory -> array of vectors
-> reg [WIDTH-1:0]mem[DEPTH-1:0];
Ex : reg [3:0]a[1:0];//single dimension memory
Ex : reg [3:0]a[1:0][1:0];//two dimensional memory
begin : P3.1
end
begin : P3.2
end
end
1st time -> generate some 32 bits = 2560 => o/p checked
2nd time -> generate some 32 bits = 2560 => o/p checked
seed=1234
seed=1256798
Ex : $random(seed)
seed=234567457
1st time -> generate some 32 bits = 2789 => o/p checked
seed=12345678
2nd time -> generate some 32 bist = 12378 => o/p checked
-> Replication
-> Syntax -> {n{value}} //-> n-> number of time that u wanna replicate
-> Can I replace n by a varibale
-> Not possible
-> Can I replace value by a variable
-> yes
-> Ex : {6{1'b1}} => 6'b111111
-> Syntax
-> always @(sensitivity)
begin
statement1;
statement2;
end
-> Syntax
initial
begin
a=10;
b=20;
$display();
$monitor();
$strobe();
$write();
end
-> multiple initial blocks start running concurrently , but inside each of
the initial block it executes sequentially
-> Initial will also execute at simulation time 0
-> Initial block will execute once
-> No -> because module has ports but generate doesn't have ports
Syntax :-
generate
for_loop ();
if_else();
case();
endgenerate
-> Generate if
-> When to use this ?
-> It will be used while dealing with any abstraction of
same/different combinational circuits
syntax: generate
if(condition)
statement1;
else
statement2;
endgenerate
1:statement2;
endgenerate
syntax: genvar i;
generate
for(i=0;i<N;i=i+1)
statements;
endgenerate
-> Task
-> Important points to consider in task
-> Ex where task is defined inside initial block -> Not possible
initial
begin
task display();//zero arguments
begin
$display("James_Bond");
end
endtask
display();//no arguments
end
-> Syntax :-
task name_task(ports can be i/p,inout,o/p);
begin
statement1;
statement2;
end
endtask
module tst;
initial
begin
print();//invocation of global task
end
endmodule
Ex : module tst;
initial
begin
print();
end
task print();
$display("Displaying");
entask
endmodule
module tst1;
tst u0 ();//instance of tst module
initial
begin
u0.print();
end
endmodule
module tst;
initial
begin
display();
end
task display();
begin:L1
$display("Process#1");
end
begin:L2
$display("Process#2");
end
endtask
endmodule
module tst_i;
tst t0 ();
initial
begin
#10;
disable t0.display.L1;//disable L1 -> don't display
Process#1
end
endmodule
-> Function
Syntax :
function data_type name_of_function (input []
variable_name);
begin
name_of_function = variable_name +1;
end
endfunction
initial
begin
a = name_of_function(10);//calling the
function and storing the return v alue
end
endmodule
-> Parallel case => We can define two or more conditions in one
condition
initial
begin
fork
#5 $display("A");
#5 $display("B");
#9 $display("C");
join
end
-> Structural
-> Bufif/Notif
a=10;
#5;
c=5;
Ex :
// initially clk=0 , then clk=1
module tst;
reg clk;
initial
begin
clk=0;
#50 $finish;
end
always #5
clk=~clk;//Timeperiod = 10ns -> High time=5ns , Low time=5ns
// Frequency => 1/time period
=> 100Mhz
endmodule
always #5
clk=~clk;//Timeperiod = 10ns -> High time=5ns , Low time=5ns
// Frequency => 1/time period
=> 100Mhz
endmodule
-> Blocking
Q1=d;
Q3=Q2;
Q2=Q1;//2ff's
Q3=Q2;
Q2=Q1;
Q1=d;//3ff's
a=5
b=5
c=5
- It will assign a+b to a temporary variable
(ex :- Q_t) , Q_t will be assig ned to Q at the
end of the timestep
- Non-Blocking statements are suggested to use in
sequential circuits
Q1<=d;
Q3<=Q2;
Q2<=Q1;//3 Ff's
Q3<=Q2;
Q2<=Q1;
Q1<=d;//3 FF's
-> Continuous
-> nets (vector/scalar)
-> bit select/part select
-> concatenation
- Two types
-> assign - deassign
Ex : always @(posedge Clk)
Cnt = Cnt + 1;
always @(Reset)
if (Reset)
assign Cnt = 0; // prevents
counting until Reset is 0
else
deassign Cnt; // resume
counting on next posedge Clk
initial
begin
#100 force Rst = 1'b0;
#200 release Rst;
end
-> force - release
Ex : Refer above example
Refer->
https://www.hdlworks.com/hdl_corner/verilog_ref/items/ProceduralContinuousAssignmen
t.htm
-> Timestep - This controls the step of time that the simulator uses to
determine what actions take place next (and/or simultaneously) and at what
resolution of incremental time passage.
-> Timeprecision -> Specifies the precision to which the delays are
rounded - off during simulation
-> Conclusion
At one Ex :- `timescale 100ns/100ns , or 10ns/10ns (this won't work
according to calculation), except 1ns/1ns (this works)
timestep should be greater than precision
-> Udp's are meant for modelling and not at all synthesizable.
end
- Before running the code , check the code (check the syntaxes,data
type,input,output,functionality)
- Mention the proper data type for array , according to convinience
- Use proper verilog constructs
- Make the code sythesizable , If you are developing RTL code
- Usually don't prefer to use non-synthesizable constructs when you are
developing RTL code
parameter WIDTH = 8