Showing posts with label verilog. Show all posts
Showing posts with label verilog. Show all posts

Wednesday, June 13, 2007

Veilog Basics (II)

Issues with Verilog:

Incomplete Specification of Conditions
(if-else or case) leads to 'Latches' (described later)

module mux_3to1(a,b,c,sel,out);
input [0:1] sel;
input a,b,c;
output out;
always@(a or b or c or sel) begin
case (sel)
2'b0: a;
2'b1: b;
2'b2: c; // what happens when 3 occurs????
endcase

endmodule
  • Thus for handling the case of 'three' as sel input a latch is introduced (which is unnecessary) to store the previous value.
  • The same is the case with a 'if' condition without a 'else'
  • To avoid this either precede the condition with default value for output or handle all the cases
    • Each if with a else condition
    • Each case with a default condition
CASE1:
always@(a or b or c or sel) begin
out = 1'b1;
case (sel)
2'b0: out = a;
2'b1: out = b;
2'b2: out = c;
endcase

CASE2:
always@(a or b or c or sel) begin
case (sel)
2'b0: out = a;
2'b1: out = b;
2'b2: out = c;
default: out = 1'b1;
endcase

Priority Logic:
Consider a case of 4 to 2 encoder, the truth table looks like
(I3,I2,I1,I0|E1,E2),
(0,0,0,1|0,0),(0,0,1,0|0,1),(0,1,0,0|1,0),(1,0,0,0|1,1),
For all others(x,x,x,x|x,x)
The code for such a module may look like

module may_encode_4to2(i,e);
input [0:3] i;
output [0:1] e;

always @ (i) begin
if(i[0]==1) e=2'b00;
else if(i[1]==1) e=2'b'01;
else if(i[2]==1) e =2'b'10;
else if(i[3]==1) e=2'b'11;
else e=2'bxx;
end

endmodule
  • Intension: Whenever two inputs are '1' the output must be don't care
  • Consider the input: i[0:4] = (1,0,0,1), the resultant output must be a don't care but unfortunately the output is a (0,0).
  • Reason: Since (i[0]==1) takes higher priority compared to the final else condition and so may fail. If-else and case statements are interpreted literally
  • Resulting Circuit: A serial bit comparison circuit.
  • Prevention: Try to give mutually exclusive inputs for comparison functions as demonstrated below so that the logic evaluated is simpler and circuit implemented would be in parallel
module encoder_4to2(i,3);
input [0:3] i;
output [0:1] o;
reg e;

always @ (i) begin
if (i=4'b0001) e=0;
else if (i=4'b0010) e=1;
else if (i=4'b0100) e=2;
else if (i=4'b1000) e=3;
else e=2'bxx
end

endmodule

Interconnecting Modules:
To maintain large designs modularity plays a important role. Verilog supports higher modules which contain sub-modules interconnected to each other. Lets consider a example of a ALU which does the basic functionalities of addition, subtraction and multiplication on the two input 32 bit values (in case of multiplication lets assume input to be 16 bits) and outputs the requested functionality.
The table for functionality may look like (assume F0 and F1 to be selectors and A and B be the input)

(F0,F1,Func)(0,0,A+B)(0,1,A-B)(1,1,A*B)

The below is a example of the ALU with the test setup. The test setup consists of initializing the registers with the required input and modifying the input after delays.

// Individual Components
module mux32three(i1,i2,i3,sel,out); // 32 bit 3 to 1 mux
input [31:0] i1,i2,i3;
input [1:0] sel;
output [31:0] out;
reg [31:0] out;

always @ (i1 or i2 or i3) begin
case (sel)
2'b00: out=i1;
2'b01: out=i2;
2'b10: out=i3;
default: out=32'bx;
endcase
end
endmodule

module add32(i1,i2,o); // 32 bit adder
input [31:0] i1,i2;
output [31:0] o;
assign o = i1+i2;
endmodule

module sub32(i1,i2,o); // 32 bit subtraction module
input [31:0] i1,i2;
output [31:0] o;
assign o = i1-i2;
endmodule

module mul16(i1,i2,o); // 16 bit multiplier
input [15:0] i1,i2;
output [31:0] o;
assign o = i1*i2;
endmodule

// ALU Module formed by inter-connecting modules
module alu(a,b,sel,alu_out); // ALU Module
input [31:0] a,b;
input [1:0] sel;
output [31:0] alu_out;

wire [31:0] add_out, sub_out, mul_out; // Intermediate wires to connect sub-modules

add32 adder(a,b,add_out);
sub32 subtract(a,b,sub_out);
mul16 multiply(a[15:0],b[15:0],mul_out);
mux32three out_mux(add_out,sub_out,mul_out,sel,alu_out);

endmodule

// Test Workspace which instantiates the alu and gives test input
module test_alu;
reg [31:0] a,b;
reg [1:0] func;

wire [31:0] our_alu_out;

initial // This sub-routine is called only once
begin
a = 32'd10;
b = 32'd10;
func = 2'd0;
#2 // Delay element (2 cycle delay)
func = 2'd1;
#2
func = 2'd2;
end

alu our_alu(a,b,func,our_alu_out);

endmodule

Modules Can be interconnected by specifying the ports as ordered or associate the port with the input/outputs.

alu our_alu(a,b,func,our_alu_out);// Can also be called as
alu our_alu(.a(a),.alu_out(our_alu_out),.b(b),.sel(func));
// in which case the order of inputs need not be maintained

Also the Verilog has primitive routines which need not be instantiated and must be ordered.
eg: and(in1,in2,in3,out)


Useful Boolean Functions:
  • Bitwise Operator: Operates on individual bits of a vector
    • ~a(NOT), a&b(AND), a|b(OR), a^b(XOR), a~^b(XNOR)
  • Logical Operator: Acts on the vector as a whole
    • !a(NOT), a&&b(AND), a||b(OR)
  • Reduction Operator: Acts on each bit of a single input
    • &a (AND), ~&a(NAND), |a(OR), ~|a(NOR), ^a(XOR)
    • &(4'b0110) = 0&1&1&0=1'b0
  • Comparison Operator:
    • ab,a<=b,a>=b - Relational Operator
    • a==b , a!=b - logical equality (whenever a or b contains x or z the result is unknown else return 0 or 1based on comparison)
    • a===b,a!==b - Case equality (does a bit by bit comparison even when x and z are present and return 1 or 0 based on comparison)
  • Note the difference between ! and ~

Verilog - Basics (I)

It is a HARDWARE DESCRIPTION LANGUAGE used to describe digital systems. It allows you to specify the digital systems at various levels of abstraction - Behavior Level, Register Transfer Level (RTL), Gate Level, Switch Level.

Design Styles:
A system, traditionally, can be designed by either Bottom Up or Top Down. Bottom up is where we start with the lowest of modules and add make complex modules from lower modules. This is usually done for smaller electronic circuits but for huge systems the Top Down approach is preferred. Since this allows the flexibility of early testing and easy change of technologies.
The basic Top Down Approach followed is as follows:
Specification ->
High Level Design ->
Low Level Design ->
RTL Coding ->
Functionality Verification -> Gate Level Simulation ->RTL Coding
Logic Synthesis -> Gate Level Simulation ->RTL Coding
Place and Route ->
Fabrication ->
Post Si Validation

Abstractions:
Behavioral:
  • System described by Concurrent Algorithms.
  • Each Algorithm consists of sequential instructions executed one after other
  • Functions, Tasks and always blocks are major components
Register Transfer Level:
  • Circuit specified by operations involving trasfer of data between registers
  • A clock is always used and RTL has strict time bounds
Gate Level:
  • Not advisable since there are tools (synthesis tools) that does this. Gate level simulation is done using the output from these tools
  • System described by logical links and timing information
  • Logic Values used : 0,1,x,z
  • Operations: AND, OR, NOT etc
Verilog Semantics:
Module:
  • Verilog design consists of inter-connection of modules
  • Modules may be an element or collection of lower level design blocks
An example of a simple module would be,

module mux_2_to_1(a,b,out,outbar,sel);
// 'module' keyword starts a module. definition ends in a semicolon
// Comments start with a double slash
input a,b,sel; // ports are defined at the beginning of module
output out, outbar; // direction is given by input, output, inout (bi-directional)

assign out = sel?a:b; // Module behavior expressed. Each line executes parallely and order
assign outbar = ~out;

endmodule

Continuous (Data) Assignment:
  • 'assign' keyword used for continuous assignments i.e the right hand side is applied to the left hand side continuously. A simple way to express Combinatorial Logic
  • Target of Continuous Assignment is a net with Combinatorial Logic .
  • Left Side:
    • Net (Vector or Scalar / Concatenated or not)
  • Right Side:
    • Net or Register / Vector or Scalar / Concatenated or not
  • Data flow Operators
    • Conditional Assignment: (condition)?(value-if-true):(value-if-false)
    • Boolean Logic: ~,&,|
    • Arithmetic: +,-,*
    • Nested Condition:
      • assign out = s1?(s0?i3:i2):(s0?i1:i0); //4:1 Mux
Gate Level Description:
The same mux if implemented at gate level would look like,

module muxgate(a,b,sel,out,outbar);
input a,b,sel;
output out,outbar;
wire out1,out2,selb;
and a1(out1,sel,a); //
and b1(out2,selb,b);
not n1(selb,sel);
or o1(out,out1,out2);
assign outbar=~out;
endmodule
  • Nets represents the connection between hardware elements. 'wire' is the keyword for Nets
  • Each module can be instantiated by . details discussed later.
  • Verilog Library supports basic logic gates as primitives
    • and or not nand nor xor xnor not buf
    • can be extended to multiple inputs.eg: nand n4(out,in1,in2,in3,in4)
    • bufif0 and bufif1 are tri-state buffers
    • Primitives do not require instance variable eg and(out,in1,in2,in3)
Procedural Assignments:
As said earlier each description of the module (or statements) execute parallely and so order is not important (which is very useful in representing Combinatorial Logic) but for implementing Sequential Logic where conditions are executed one after other Procedural Assignments help.
  • Two structured procedural statements: initial and always
  • Supports richer C-like constructs like if-else, case,for,while
module mux_2_to_1(a,b,out,outbar,sel);
input a,b,sel;
output out,outbar

always @(a or b or sel) begin // always@(sensitivity list) begin execution
if(sel=0) out=a; // the region between begin to end is executed serially and order matters
else out = b;
outbar=~out;
end

endmodule

  • Conceptually, always block is called once whenever anything(since 'or' is used) in the sensitivity list is modified.
Verilog Registers:
  • Registers (reg) in Verilog corresponds to a variable which can store a value
  • Unlike digital system registers (which are memory elements which require clock and so should not be confused) registers do not require clock and value can be changed anytime.
Difference Between Procedural and Continuous Assignments:
  • Both can co-exist in the same module
  • Procedural statements update a register and this register is not modified unless another procedural statement updates it.
  • In continuous assignment, the right hand side is constantly placed on the left hand side.
Case Statement:
Case and if may be used interchangeably and Case statements helps in readability in case of long if-else statements.

module mux_2_to_1(a,b,out,outbar,sel);
input a,b,sel;
output out,outbar

always @(a or b or sel) begin
case(sel)
1'b1: a; // number representation '
1'b0: b; // e.g. 16'h4fff - 16 bit hexadecimal value
endcase
outbar=~out;
end

endmodule

N-bit Signals (Vectors) - Power of Verilog:
  • Multi-bit signals and buses are easy in Verilog
  • 2-to-1 multiplexer with 8-bit operands
module mux_2_to_1(a,b,sel,out,outbar);
input [0:7] a,b;
input sel;
output [0:7] out,outbar;
reg [0:7] out;

always @(a or b or sel) begin
case(sel)
1'b1: a;
1'b0: b;
endcase
outbar=~out;
end

endmodule
  • Here 'sel' is a scalar while a,b,out and outbar are called Vectors
  • Signals can be concatenated using a Concatenation operator {}
    • {b[0:7],b[8:15]} = { a[8:15],a[0:7]}
    • The above is a byte swap operation
Integer Arithmetic:
32 bit adder with carry:

module add32(a,b,Cin,out,Cout);
input [0:32] a,b;
input Cin;
output [0:32] out;
output Cout;
assign {Cout,out} = a+b+Cin;
endmodule