Verilog: Adders, Ports, Gate Level Modeling, Multiplexer

Do I like studying like this? No.
Do I have to if I want to clear this course? Yes.

https://media.giphy.com/media/ZE3RMacA3g7fi/giphy.gif

These are my notes of Third and Fourth chapter from  Verilog HDL: A Guide to Digital Design and Synthesis, Second Edition. By Samir Palnitkar.

Revision : Full Adder

Image result for fulladder
Full Adder is basically two half adders. ref
Image result for fulladder
Ref

Let’s go through the steps

  1. We know Full Adder is two Half Adder
    1. There will me a Module fulladder which will have to instances of module halfadder
    2. We will also require or gate
  2. Half adder is combination of xor and and

Let’s look at some code

module full_adder
  (a,
   b,
   cin,
   sum, 
   carry); 
  input a, b, cin; 
  output sum, carry;
  wire s1, c1, c2;
  
  half_adder h1
  (
    .a(a),
    .b(b),
    .sum(s1),
    .carry(c1)
  );
  half_adder h2
  (
    .a(cin),
    .b(s1),
    .sum(sum),
    .carry(c2)
  );
  or or1(carry, c1, c2); 
endmodule

//testbench
module full_adder_tb;
 
  reg A = 0;
  reg B = 0;
  reg C = 0;
  wire SUM;
  wire CARRY;
   
  full_adder full_adder_inst
    (
      .a(A),
      .b(B),
      .cin(C),
     .sum(SUM),
     .carry(CARRY)
     );
 
  initial
    begin
      $display("Full Adder");
      A = 1'b1;
      B = 1'b1;
      C = 1'b1;
      #10;
      $display("A %b \nB %b \nC %b \nSum %b \nCarry %b",A, B,C, SUM, CARRY);

    end 
 
endmodule // full_adder_tb

Let’s build Half Adders

module half_adder 
  (
   a,
   b,
   sum,
   carry
   );
 
  input  a, b;
  output sum;
  output carry;
 
  assign sum   = a ^ b;  // bitwise xor
  assign carry = a & b;  // bitwise and
 
endmodule // half_adder
module half_adder_tb;
 
  reg A = 0;
  reg B = 0;
  wire SUM;
  wire CARRY;
   
  half_adder half_adder_inst
    (
      .a(A),
      .b(B),
     .sum(SUM),
     .carry(CARRY)
     );
 
  initial
    begin
      A = 1'b1;
      B = 4'b1;
      #10;
      $display("A %b \nB %b \nSum %b \nCarry %b",A, B,SUM, CARRY);

    end 
 
endmodule // half_adder_tb

How to make connections (long lasting?)

https://media.giphy.com/media/d2Z8Ob1chcNW5S1i/giphy.gif

Connection by Ordered List

This is pretty straightforward. You remember the list of things that you wanted to be connected and create instance with the same order.

full_adder(a, b, c_in, sum, c_out);

Connection by Port Names

This might not really work when there are like a hundred ports and many of them are optional. Here we use port names.

full_adder fa_byname(.carry(C_OUT)), .a(A), .b(B), .c_in(C_IN), .sum(SUM);

it’s like keyword-argument passing in python (again, just drawing analogies so that I am able to remember it better)

Link to annotated notes for

Conclusion

  • We went through basics of verilog.
  • Designed a fulladder (sort of?)
  • Realised how to connect port.

Stay with me guys, we will eventually learn how to write something useful in verilog (I hope)

https://media.giphy.com/media/5iW8199bTMtC8/giphy.gif

4 bit full adder

Image result for 4 bit ripple carry adder

Now let’s work on this

For this, we need to create 4 instances of a normal singlebit full adder. Then use the carries wisely

Our inputs are going to be 4 bit except the carry

input [3:0]a;
input [3:0]b; 
input cin;

Sum will be a 4bit sum and carry will be one bit

output [3:0]sum;
output carry;

So, eventually according to the diagram our four full adders will be

  full_adder f0(
    a[0],
    b[0],
    cin, 
    sum[0],
    c1);
  full_adder f1(
    a[1],
    b[1],
    c1, 
    sum[1],
    c2);
  full_adder f2(
    a[2],
    b[2],
    c2, 
    sum[2],
    c3);
  full_adder f3(
    a[3],
    b[3],
    c2, 
    sum[3],
    carry);

4 bit ripple carry adder

module half_adder 
  (
   a,
   b,
   sum,
   carry
   );
 
  input  a, b;
  output sum;
  output carry;
 
  assign sum   = a ^ b;  // bitwise xor
  assign carry = a & b;  // bitwise and
 
endmodule // half_adder

module full_adder
  (a,
   b,
   cin,
   sum, 
   carry); 
  input a, b, cin; 
  output sum, carry;
  wire s1, c1, c2;
  
  half_adder h1
  (
    .a(a),
    .b(b),
    .sum(s1),
    .carry(c1)
  );
  half_adder h2
  (
    .a(cin),
    .b(s1),
    .sum(sum),
    .carry(c2)
  );
  or or1(carry, c1, c2); 
endmodule

module full_adder_4bit
  (
    a,
    b, 
    cin,
    sum, 
    carry
  );
  input [3:0]a;
  input [3:0]b;
  input cin;
  
  output [3:0]sum;
  output carry;
  
  wire c1, c2, c3;
  
  full_adder f0(
    a[0],
    b[0],
    cin, 
    sum[0],
    c1);
  full_adder f1(
    a[1],
    b[1],
    c1, 
    sum[1],
    c2);
  full_adder f2(
    a[2],
    b[2],
    c2, 
    sum[2],
    c3);
  full_adder f3(
    a[3],
    b[3],
    c3, 
    sum[3],
    carry);
  
endmodule

//Testbench
module full_adder_4bit_tb;
  reg [3:0]a;
  reg [3:0]b;
  reg cin;
  
  wire [3:0]sum;
  wire carry;
  
  full_adder_4bit fa4(
    a,
    b, 
    cin,
    sum, 
    carry
  );
  
  initial
    begin
      a = 4'b0001;
      b = 4'b1111;
      cin = 0;
      #10;
      $display("a = %b\n b = %b\n cin = %b\n sum = %b\n carry = %b\n", a, b, cin, sum, carry);
    end
endmodule
a = 0001
b = 1111
cin = 0
sum = 0000
carry = 1

Both of these are gate level behavioural models

Behavioural vs Dataflow

Dataflow modeling in Verilog allows a digital system to be designed in terms of it’s function. Dataflow modeling utilizes Boolean equations, and uses a number of operators that can acton inputs to produce outputs operators like + – && & ! ~ || | << >> {} so if i want to describe a 2 to 4 decoder in dataflow modeling i would be like this

module decoder2to4 ( e , a, b, do, dl, d2, d3);
input e, a, b;
output do, dl, d2, d3;
assign dO = ( e & ~a & ~b); //00
assign dl = (e & ~a & b);   //01
assign d2 = (e & a & ~b);   //10
assign d3 = ( e & a & b);   //11
endmodu1e

on the other hand The Behavioral modeling in Verilog is used to describe the function of a design in an algorithmic manner so if i want to describe a 2 to 4 decoder in dataflow modeling i would be like this

module decoder2to4 (e, i, d);
output [3:0] d;
input [l:0]i;
input e;
reg [3:0] d;
    always @ (i or e) begin
            if (e==l) begin
                case (i)
                       0: d = 4'b 0001;
                       1: d = 4'b 0010;
                       2: d = 4'b 0100;
                       3: d = 4'b 1000;
                      default d = 4'b xxxx;
               endcase
            end
            else
               d = 4'b0000;
    end
endmodule

Reference Difference between behavioral and dataflow in verilog

Side note: I never thought I would find VLSI so interesting ! I am actually enjoying this subject.

These are my notes of fifth chapter from  Verilog HDL: A Guide to Digital Design and Synthesis, Second Edition. By Samir Palnitkar.

Gates!

https://media.giphy.com/media/3oz8xPyx3qgq5jAmMo/giphy.gif

Not that one!

https://media.giphy.com/media/Mrwin3qN8f8kw/giphy.gif

I surely do love adders.

Logic Gates

  • Important the first argument is always the output then followed by inputs
and ANDGATE(out, a, b);

You can do this for and, or, nand, nor, xor, xnor

Then there are two more gates, buf which is buffer gate and not which is a not gate(negates the input)

they have single input and output

Multiplexer Design

My brain mush

Okay , I know this is just bunch of scribbling, and I will explain what I was trying to do there.

break down a multiplexer in it’s smallest indivisible pieces- gates. There are four and gates and one or

Input to the Mux will I0, I1, I2, I3, S0, S1.

What we won’t have is S0bar, S1bar, Y0, Y1, Y2, Y3– So let’s declare them.

wire s0bar, s1bar;
wire y0, y1, y2, y3;

not(s0bar, s0);
not(s1bar, s1);

How do we pass this to and gate. Let’s try generating y0

and (y0, i0, s1bar, s0bar);

Thus the overall code looks something like

module mux(input i0, i1, i2, i3; 
           input s0, s1, 
           output out);


wire s0bar, s1bar;
wire y0, y1, y2, y3;

not(s0bar, s0);
not(s1bar, s1);

and (y0, i0, s1bar, s0bar);
and (y1, i0, s1bar, s0);
and (y3, i0, s1, s0bar);
and (y2, i0, s1, s0);

or (out, y0, y1, y2, y3);

endmodule

Additional functionality : Gate Delays

You can add delay using #(number) after the gate keyword.

add #(5) a1(out, a, b); //5sec delay for and gate

Annotates notes on Chapter 5: Gate Level Modeling

Conclusion

  • We not know about basic gates in Verilog and how to create a multiplexer in Verilog
  • Also turns out, I actually like VSLI and Verilog!

One thought on “Verilog: Adders, Ports, Gate Level Modeling, Multiplexer

Leave a Reply

%d bloggers like this: