Digital Electronics
Sequential Circuits
Play with the circuit here
http://www.facweb.iitkgp.ac.in/~avishek/DigitalElectronics2024.html
Home Work: Design a Modulo 10 counter
Application: A Digital Metronome with variable number of beats
Let us first make a 4-bit down counter with the provision for loading the initial values
When Load = 1,
then at the next positive CLK edge I3, I2, I1, and I0 are copied to Q3, Q2, Q1, and Q0 respectively.
When Load = 0,
then down counting continues with positive CLK edges
4-bit down counter with the provision for loading the initial values
Now we use the above counter to make a digital metronome with variable number of beats
4-bit down counter with
the provision for
loading the initial values
Demonstration is here: http://www.facweb.iitkgp.ac.in/~avishek/DigitalElectronics2024.html
Now we make a register that can be loaded either serially or parallely, and can be read either serially or parallely
We can use the above circuit as a PISO register. If we connect the SO output back to SI input, then it would be possible
to read-out the data more than once.
Verilog HDL through examples
HDL : Hardware Description Language
Most used HDLs : (1) Verilog, (2) System Verilog, and (3) VHDL
VHDL : Very-High-Speed-Integrated-Circuit Hardware Description Language
(It's not that Verilog is for slow speed ICs)
Half adder
module HalfAdder(input X, input Y, output S, output Cout);
xor(S,X,Y);//S=X xor Y
and(Cout,X,Y);
endmodule
Half adder: Alternative approach
module HalfAdder(input X, input Y, output S, output Cout);
assign S = (~X)&Y | X&(~Y);
assign Cout = X&Y;
endmodule
Half adder: Leaving the logic design to the computer
module HalfAdder(input X, input Y, output S, output Cout);
assign {Cout, S} = X + Y;
endmodule
Full adder: Using two half adders
module FullAdder(input A, input B, input Cin, output Sum, output Cout);
HalfAdder HA1(A,B,S1,C1);
HalfAdder HA2(Cin,S1,Sum,C2);
assign Cout = C1|C2;
endmodule
Full adder: Leaving the logic design to the computer
module FullAdder(input A, input B, input Cin, output Sum, output Cout);
assign {Cout, Sum} = A+B+Cin;
endmodule
Four bit adder: Leaving the logic design to the computer
module FourbitAdder(input [3:0] X, input [3:0] Y, input Cin, output [3:0] Sum, output Cout);
assign {Cout,Sum} = X+Y+Cin;
endmodule;
Four bit adder: Using 4 FAs
module FourbitAdder(input [3:0] X, input [3:0] Y, input Cin, output [3:0] Sum, output Cout);
FullAdder FA0(X[0], Y[0], Cin, Sum[0], Cout0);
FullAdder FA1(X[1], Y[1], Cout0, Sum[1], Cout1);
FullAdder FA2(X[2], Y[2], Cout1, Sum[2], Cout2);
FullAdder FA3(X[3], Y[3], Cout2, Sum[3], Cout);
endmodule;
Four bit AdderSubtractor
module FourbitAdderSubtractor(input [3:0] X, input [3:0] Y, input CorBin, input Control,
output [3:0] SumOrDiff, output CorBout);
// If Control = 0, then the module adds the two numbers
// If Control =1, then the module subtracts Y from X
assign {CorBout,SumOrDiff} = (Control==0)? X+Y+CorBin : X-Y-CorBin;
endmodule
Note the syntax of the conditional assignment
Negative numbers are represented in 2's complement form
Example Problems: Just describe what to do to the computer and leave the design to the compueter
Design a logic circuit to convert BCD to Excess-3 for the numbers zero to nine
module BCDtoExcess3(input [3:0] BCD, output [3:0] Excess3);
assign Excess3 = BCD+3;
endmodule
Design a circuit to implement the logical expression x' y' + y(x+z)
module myModule(input x, input y, input z, output out);
assign out = (~x)&(~y) | y&(x|z);
endmodule
Consider a circuit that accepts a 3-bit binary number X and
outputs a 2-bit binary number Y that is equal to the number of 1’s that appear in X.
For example,
(a) X=000 contains no 1’s and Y=00,
(b) X=110 contains two 1’s and Y=10,
(c) X=111 contains three 1’s and Y=11, etc
Design this circuit using Verilog.
module countOnes(input [2:0] X, output [1:0] Y);
assign Y = X[0]+X[1]+X[2];
endmodule
Note how the individual bits are referred
Design a three-input circuit that yields an output 1 when exactly one of its inputs is 1
module isSingleOne(input [2:0] X, output Z);
wire [1:0] Y;
assign Y = X[0]+X[1]+X[2];
assign Z = (Y==1)? 1:0;
endmodule
Note the syntax of the conditional assignment
Design a BCD to Seven Segment Display Decoder.
module BCDto7Segment(input [3:0] X, output reg [6:0] Y);
always @(X)
begin
case(X)
0: begin Y = 7'b1111110; end
4'd1: Y = 7'b0110000;
4'b10: Y = 7'b1101101;
4'h3: Y = 7'b1111001;
4: Y = 7'b0110111;
5: Y = 7'b1011011;
6: Y = 7'b1011111;
7: Y = 7'b1110000;
8: Y = 7'b1111111;
9: Y = 7'b1111011;
default: Y = 0;
endcase
end
endmodule
Two types of variables: wires and reg
module DataLatch(input D, output Q); module DataLatch(input wire D, output wire Q);
assign Q = D; assign Q = D;
endmodule endmodule
module DFF(input wire clk, input wire D, output reg Q); module DFF(input clk, input D, output reg Q);
always @(posedge clk) always @(posedge clk)
Q <= D; Q <= D;
endmodule endmodule
module DFF(input wire clk, input wire D, output reg Q = 0);
always @(posedge clk)
Q <= D;
endmodule
`timescale 1ns / 1ps
module TB_DFF();
reg clk = 0;
reg D = 0;
wire Q;
DFF dff1(clk, D, Q);
always begin #5 clk = ~clk; end
initial begin
#3 D= ~D;
#3 D = ~D;
#2 D = 1;
#4 D = 0;
#6 D = 1;
#3 D = 0;
#5 D = 1;
#4 D = 0;
#2 D = 1;
end
endmodule
module JKFF(input clk, input J, input K, output reg Q = 0);
always @(posedge clk) begin
if(J==1 && K==0) begin
Q <= 1;
end
else if(J==0 && K==1) begin
Q <= 0;
end
else if(J==1 && K==1) begin
Q <= ~Q;
end
else begin
Q <= Q;
end
end
endmodule
module TFF(input clk, input T, output reg Q = 0);
always @(negedge clk) begin
if(T == 1) begin
Q <= ~Q;
end
end
endmodule
module TB_TFF();
reg myclk = 0;
reg T = 0;
wire myQ;
TFF tff1(.T(T), .clk(myclk), .Q(myQ));
always begin #5 myclk <= ~myclk; end
initial begin
$dumpfile("dump.vcd");
$dumpvars(1);
#3 T= ~T;
#3 T = ~T;
#2 T = 1;
#4 T = 0;
#6 T = 1;
#3 T = 0;
#5 T = 1;
#4 T = 0;
#2 T = 1;
#5 $finish();
end
endmodule
4-bit Up Counter
`timescale 1ns / 1ps module UpCounter(input clk, output reg [3:0] Q = 0);
always @(posedge clk) begin
module TB_UpCounter(); Q <= Q+1;
reg clk = 0; end
wire [3:0] Q; endmodule
UpCounter uut(.clk(clk), .Q(Q));
always begin
#5 clk <= ~clk;
end
endmodule
Modulo 10 Counter
module Mod10Counter(input clk, output reg [3:0] Q = 0);
always @(posedge clk) begin
if(Q<9)begin
Q <= Q+1;
end
else begin
Q <= 0;
end
end
endmodule
Clocked JK Flip-flop with asynchronous Reset
module ClockedJKFF(input clk, input J, input K, input Reset, output reg signed Q = 0);
always @(posedge clk or negedge Reset) begin
if(Reset==0) begin
Q<=0;
end
else if (J==0 && K==0) begin
end
else if (J==1 && K==0) begin
Q<=1;
end
else if (J==0 && K==1) begin
Q<=0;
end
else if (J==1 && K==1) begin
Q<=~Q;
end
end
endmodule
Inside an always (or initial) block, we can use two symbols for data assignment:
(1) <= : This is called non-blocking assignment
(2) = : This is called blocking assignment
Let us see the difference with examples
A ring counter
module RingCounter(input clk, output reg [3:0] Q = 1); module RingCounter(input clk, output reg [3:0] Q = 1);
always @(posedge clk) begin always @(posedge clk) begin
Q[0] <= Q[1]; Q[3] <= Q[0];
Q[1] <= Q[2]; Q[2] <= Q[3];
Q[2] <= Q[3]; Q[1] <= Q[2];
Q[3] <= Q[0]; Q[0] <= Q[1];
end end
endmodule
endmodule
module RingCounter(input clk, output reg [3:0] Q = 1); module RingCounter(input clk, output reg [3:0] Q = 1);
always @(posedge clk) begin always @(posedge clk) begin
Q[0] = Q[1]; Q[3] = Q[0];
Q[1] = Q[2]; Q[2] = Q[3];
Q[2] = Q[3]; Q[1] = Q[2];
Q[3] = Q[0]; Q[0] = Q[1];
end end
endmodule endmodule
module RingCounter(input clk, output reg [3:0] Q = 1); module RingCounter(input clk, output reg [3:0] Q = 1);
always @(posedge clk) begin always @(posedge clk) begin
Q[0] <= Q[1]; Q[0] = Q[1];
Q[1] <= Q[2]; Q[1] = Q[2];
Q[2] <= Q[3]; Q[2] = Q[3];
Q[3] <= Q[0]; Q[3] = Q[0];
end
end
endmodule
endmodule
Verilog variables are of two types: unsigned and signed.
By default all variables are treated as unsigned.
If we declare a variable to be signed,
then negative numbers are represented in 2's complement form
module Counter(input clk, output reg signed [2:0] Q = 0, reg s);
//s should be 0 if Q is negative, s should be 1 otherwise
always @(posedge clk) begin
Q = Q+1;
if(Q>=0) begin
s <= 1;
end
else begin
s <= 0;
end
end
endmodule
module Counter(input clk, output reg [2:0] Q = 0, reg s);
//s should be 0 if Q is negative, s should be 1 otherwise
always @(posedge clk) begin
Q = Q+1;
if(Q>=0) begin
s <= 1;
end
else begin
s <= 0;
end
end
endmodule
module Counter(input clk, output reg signed [2:0] Q = 0, reg s);
//s should be 0 if Q is negative, s should be 1 otherwise
always @(posedge clk) begin
Q <= Q+1;
if(Q>=0) begin
s <= 1;
end
else begin
s <= 0;
end
end
endmodule
Finite State Machine (FSM)
Some common general architectures
Outputs
Qn, ...................., Q0 Qn, ...................., Q0 Ym, .........., Y0
Memory or Latch or Memory or Latch or
Clocked PIPO register Outputs Clocked PIPO register
Dn, ....................,D0 Ym, .........., Y0 Dn, ....................,D0 PIPO registe
Combinational Combinational
circuit circuit
Xp, .........., X0 Xp, .........., X0
Inputs Inputs
Qn, ..., Q0 are called state variables Here the next state is a function of the present state and inputs.
Outputs are functions of inputs and state variables Outputs are functions of inputs and state variables.
The next state is a function of the present state and inputs Here outputs are synchronous (or clocked or registered)
This structure is called a Mealy machine and can change only at a clock edge
Here outputs are not synchronous (not clocked) This structure is called a
and can change anytime without requiring a clock edge Synchronous or Registered Mealy machine
Outputs
Ym, .........., Y0
Combinational
circuit
Qn, ...................., Q0
Memory or Latch or
Clocked PIPO register
Dn, ....................,D0
Combinational
circuit
Xp, .........., X0
Inputs
Qn, ..., Q0 are called state variables
Outputs are functions of state variables and do not depend on inputs directly
The next state is a function of the present state and inputs
This structure is called a Moore Machine
Here outputs can change only when state variables change,
i.e. at a appropriate clock edge