Field Programmable Gate Arrays (FPGA)

ETE 499

Course Description:

These classes (Lecture and Lab) explore the design techniques and applications that use Field Programmable Gate Arrays (FPGAs). The objectives of the course are that the students will have an understanding of various FPGA design techniques and concepts with practices that are widely used today in industry. The courses will focus on developing various designs techniques typically using a High-Level Description Language (HDL) such as Verilog, and will also exploring additional design methodologies.

8-bit adder        3

Objective        3

I/O        3

InputRead        3

EightBitAdder        4

AdderTop        4

Test Results 8-bit Adder        5

Compare/adder Block        6

Objective        6

Comparison_Adder        6

Test Simulation        8

Test Results        9

Develop a simple system        9

Objective        9

Verilog:        10

Top        10

Sw_dec        10

Num Generator        11

Two Digit Compare        11

Seven Segment        12

Pulse counter        14

Objective        14

Verilog        14

Test Simulation Code        14

Test Results        15

Multiple clock signals out of phase        16

Objective        16

Verilog        16

Test Simulation Code        17

Test Results        17

State machine        18

Verilog        18

Test Simulation        18

8-bit adder

Objective

I/O

SW[16:0] 17 input switches

SW[7:0] representing (InputX)  8-bit number

SW[15:7] representing (InputY)  8-bit number

SW[16] Carryin input as (Btn0)

Output [8:0] vector

        Output [8] - cout output

        Output [7:0] - result of addition (InputX) + (InputY)

InputRead

module InputRead(Sw, Btn0, InputX, InputY, Cin);
        input         
[15:0]          Sw;
        input                 
Btn0;
        output         
[7:0]          InputX;
        output         
[7:0]          InputY;
        output                
Cin;

        assign
InputX[7:0] = Sw[7:0];

        assign
InputY[7:0] = Sw[15:8];

        
not(Cin,Btn0);

endmodule

EightBitAdder

module EightBitAdder( RCOSum, RCOCarryOut, RCOAddX, RCOAddY, RCOCarryIn);

        output         
[7:0]          RCOSum;
        output                 
RCOCarryOut;
        input         
[7:0]           RCOAddX;
        input         
[7:0]           RCOAddY;

input                RCOCarryIn;

// create wires for intermediate carries

        wire         C0
;

// instantiate the set of full adders
// FourBitAdder(Sum, Cout, Xin, Yin, Cin);


        
FourBitAdder        Add1(RCOSum[3:0], C0, RCOAddX[3:0], RCOAddY[3:0], RCOCarryIn),
                               
Add2(RCOSum[7:4], RCOCarryOut, RCOAddX[7:4], RCOAddY[7:4], C0);
                                

endmodule

AdderTop

module AdderTop(Output,Sw, Btn0 );
        output         
[8:0]          Output;
        input         
[15:0] Sw;

input                Btn0;  // carry in
// create wires
        wire         
[7:0]         OpX; // 8 bits from the 16 discrete inputs

wire         [7:0]         OpY; // 8 bits from the 16 discrete inputs

wire         [7:0]         Sum; // 8 sum bits from the RCO Adder
wire                    
Cout; // adder carry out

wire               Cin;  // adder carry in
wire         
[8:0]         DispData;

// Assign the carry in into the adder to zero

        assign DispData[8] = Cout;

        assign DispData[7:0] = Sum;

// modules in this design.


        
InputRead         In0(Sw,Btn0,OpX,OpY,Cin); 
        
EightBitAdder        Add1(Sum, Cout, OpX, OpY, Cin);
        
DispOut                DO(Output,DispData);

endmodule

Test Results 8-bit Adder


Compare/adder Block

Objective

Create a behavior to perform the following:

Comparison_Adder

`timescale 1ns / 1ps

module Comparison_adder(sum,A_gt_B,A_lt_B,A_eq_B,A,B);

   output [7:0] sum,
       A_gt_B,
       A_lt_B,
       A_eq_B;
       
   input [7:0] A;
   input [7:0] B;    
         
   assign A_gt_B= (A > B),
          A_lt_B= (A<B),
          A_eq_B= (A==B),
          sum= A+B;
                   
endmodule


Test Simulation

`timescale 1ns / 1ps
module Test;
 
   reg [7:0] A;
   reg [7:0] B;
   

    wire [7:0] sum;
 
        
Comparation_adder uut (
                
.sum,           
                
.A_gt_B(A_gt_B), 
                
.A_lt_B(A_lt_B), 
                
.A_eq_B(A_eq_B), 
                
.A,             
                
.B              
        
);

initial begin
// Initialize Inputs
        A
= 0;
        B
= 0;
// Wait 100 ns for global reset to finish
        
#100;    
//begin testing parameters
        
#1000
// where A > B
                A
= 5; B = 1;
        
#2000
//where A == B
        A
= 0; B = 0;
        
#2000
//where A < B
        A
= 2; B = 30;
        
#2000
//where cout = 1
        A
= 50;
        B
= 28;
        
#2000
//reset to 0
        A
= 0;
        B
= 0;                
end
     
endmodule


        

Test Results


Develop a simple system

Objective

Use the Xilinx Zybo board to develop a system using the onboard switches, LEDs, and an external Seven segment display.

Verilog:

Top

`timescale 1ns / 1ps

module top(led,pin_data_out,cat,sw,btn,clk);

    output  [3:0]   led;

    output  [7:1]   pin_data_out;

    output          cat;

    input   [3:0]   sw;

    input           btn;

    input           clk;

    wire            w_clk1, w_clk2;

    wire    [3:0]   digit_1, digit_2;

   

    sw_digit            sw_digit1(digit_1,sw);

    clk                 clk1(w_clk1,w_clk2,locked,clk);

    num_generator       num_generator1(digit_2, btn, w_clk2); //runs on clk 2

    two_digit_compare   two_digit_compare1(led, digit_1, digit_2,btn);

    dbl_seven_seg       dbl_seven_seg1(pin_data_out,cat,digit_1,digit_2,w_clk1);//runs on clk1

endmodule

Sw_dec

`timescale 1ns / 1ps

module sw_digit(digit,sw);

    input   [3:0]   sw;

    output  [3:0]   digit;

   

    reg     [3:0]   digit;

   

    always @ (sw)

        case (sw)

            0:  digit = 0;

            1:  digit = 1;

            2:  digit = 2;

            3:  digit = 3;

            4:  digit = 4;

            5:  digit = 5;

            6:  digit = 6;

            7:  digit = 7;

            8:  digit = 8;

            9:  digit = 9;

            10: digit = 10;

            11: digit = 11;

            12: digit = 12;

            13: digit = 13;

            14: digit = 14;

            default: digit = 0;

        endcase

       

endmodule

Num Generator

`timescale 1ns / 1ps

module num_generator(digit, btn, clk);

    input clk;

    input btn;

    output [3:0] digit;

   

    reg [3:0] digit;

   

    always @ (posedge clk)

        begin

            if (~btn) //count to 14 and reset if button NOT pushed

                begin

                    if (digit <= 14)

                        digit = digit + 1;

                    else

                        digit = 0;

                end

            else //hold if button pushed

                digit = digit;

        end

endmodule

Two Digit Compare

`timescale 1ns / 1ps

module two_digit_compare( led, digit_1, digit_2,btn);

    output [3:0] led;

    input  [3:0] digit_1,digit_2;

    input  btn;

   

   

    reg [3:0] led;

   

    always @ (digit_1,digit_2,btn)

        begin

           if (btn)

                begin

                    if (digit_1 == digit_2)

                        begin

                            repeat (16) // if digits equal LEDS flash

                                begin

                                   led = 4'b1;

                                   #1000

                                   led = 4'b0;

                                   #1000

                                   led = 4'b1;

                                end           

                               

                        end

                    else

                        led = 4'b0;

               end

           else

                led = 4'b0;

        end

endmodule

Seven Segment

`timescale 1ns / 1ps

module dbl_seven_seg(pin_data_out,cat,digit_1,digit_2,clk);

    output  [7:1]   pin_data_out; // 7:1 AA AB AC AD AE AF AG

    output          cat; // selects which display to use

    input   [3:0]   digit_1,digit_2;

    input           clk;

    reg     [7:1]   pin_data_out;

    reg             cat;

    always@(clk,digit_1,digit_2)

    begin

        if (clk == 1)

            begin

                case(digit_1)

                    0: pin_data_out = 7'b111_1110;//0

                    1: pin_data_out = 7'b011_0000;//1

                    2: pin_data_out = 7'b110_1101;//2

                    3: pin_data_out = 7'b111_1001;//3

                    4: pin_data_out = 7'b011_0011;//4

                    5: pin_data_out = 7'b101_1011;//5

                    6: pin_data_out = 7'b101_1111;//6

                    7: pin_data_out = 7'b111_0000;//7

                    8: pin_data_out = 7'b111_1111;//8

                    9: pin_data_out = 7'b111_1011;//9

                    10: pin_data_out = 7'b111_0111;//a

                    11: pin_data_out = 7'b001_1111;//b

                    12: pin_data_out = 7'b100_1111;//c

                    13: pin_data_out = 7'b011_1101;//d

                    14: pin_data_out = 7'b100_1111;//e

                    default: pin_data_out = 7'b0;//display off

                endcase

                cat = 1'b1;

            end

        else

             begin

                   case(digit_2)

                       0: pin_data_out = 7'b111_1110;//0

                       1: pin_data_out = 7'b011_0000;//1

                       2: pin_data_out = 7'b110_1101;//2

                       3: pin_data_out = 7'b111_1001;//3

                       4: pin_data_out = 7'b011_0011;//4

                       5: pin_data_out = 7'b101_1011;//5

                       6: pin_data_out = 7'b101_1111;//6

                       7: pin_data_out = 7'b111_0000;//7

                       8: pin_data_out = 7'b111_1111;//8

                       9: pin_data_out = 7'b111_1011;//9

                       10: pin_data_out = 7'b111_0111;//a

                       11: pin_data_out = 7'b001_1111;//b

                       12: pin_data_out = 7'b100_1111;//c

                       13: pin_data_out = 7'b011_1101;//d

                       14: pin_data_out = 7'b100_1111;//e

                       default: pin_data_out = 7'b0;//display off

                   endcase

                   cat = 1'b0;

               end

    end

endmodule

Pulse counter

Objective

The pulse measurement block provides the number of clock counts when the pulse is high from the quadrature decoder.  Construct a simple pulse counter that provides as the output the number of counts when clocked by the clk_ph1 signal.  Again use an asynchronous negative edge reset.

Verilog

`timescale 1ns / 1ps

module question_1(input clk_ph1, input signal, input rst_n, output reg [7:0] counts  );

always @(negedge signal)
begin
   counts = 0;
end

always @ (negedge clk_ph1,rst_n)
   begin
       if (~rst_n)
           counts = 0;
       else
           if (signal ==1)
               counts = counts +1;
           
   end
endmodule

Test Simulation Code

`timescale 1ns / 1ps

module test_q1;

reg  clk_ph1 = 0, signal, rst_n;

wire [7:0] counts;

question_1 uut (
           .clk_ph1(clk_ph1),
           .signal,
           .rst_n,
           .counts(counts));

always #10  clk_ph1 = ~clk_ph1;

initial begin
    signal
= 0;
    rst_n
= 1;
   
#100;
    signal
= 0;
    rst_n
= 1;
   
#100
    signal
= 1;
   
#100
    rst_n
= 0;
   
#100
    signal
= 0;

end
endmodule

Test Results

First we have reset set to 1 thus  Signal is 0 so no counting is happening. Next we turn on signal for 200ns while reset = 1 we start counting.Set reset to 0 thus resetting the count back to 0 even though signal is high.


Multiple clock signals out of phase

Objective

The System requires multiple clock signals to be produced from a 32MHz input system clock.

Assume that each clock signal developed is attached to a clock driving capable internal route.

Develop Verilog code for the clock system that produces the clocks as follows:

Each one has an overall period of ~125KHz.  The duty cycle of each clock is 25%.  

Assume that clk_ph1 is the reference with no phase shift while clk_ph2 has a phase shift of 25%,

    clk_ph3 has a phase shift of 50%, and clk_ph4 has a phase shift of 75%.

Verilog

`timescale 1ns / 1ps

module question_2(input clk_sr,input clk_sm,output reg clk_ph1, output reg clk_ph2, output reg clk_ph3, output reg clk_ph4  );

reg [2:0] count =0;

always @ (negedge clk_sm)
   begin
       count = count + 1;
   end
always @ (count)
   begin
       if((0 <= count)&&(count <= 1))
           clk_ph1 = 1; else  clk_ph1 = 0;
       if((1 < count)&&(count <= 3))
           clk_ph2 = 1; else  clk_ph2 = 0;
        if((3 < count)&&(count <= 5))
           clk_ph3 = 1; else  clk_ph3 = 0;
       if((5 < count)&&(count <= 7))
           clk_ph4 = 1; else  clk_ph4 = 0;
   end
endmodule

Test Simulation Code

`timescale 1ns / 1ps
module test_q2;

reg  clk_sm , clk_sr;
wire clk_ph1,clk_ph2,clk_ph3,clk_ph4;

question_2 uut (
               .clk_sr(clk_sr),
               .clk_sm(clk_sm),
               .clk_ph1(clk_ph1),
               .clk_ph2(clk_ph2),
               .clk_ph3(clk_ph3),
               .clk_ph4(clk_ph4)  );

always #8000  clk_sr = ~clk_sr;    //16000 = 16MHz
always #500  clk_sm = ~clk_sm;     //1000us = 1MHz

initial begin
    clk_sr = 0;
    clk_sm = 0;
    #100;
end
endmodule

Test Results

Here we have the sm clock at 1 MHz which is what we are using to generate the 4 phases, We have a counter that counts to 7, 3-bits at 125kHz for a full count. Thus every two counts is 25% so we start each phase at every two counts.


State machine

The serial output signal receives the 8-bit value from the state machine and sends it out serially.  The data clocked out will accompany the shift register clock. Develop a Verilog design that performs the shift operation. If any signals between the shift register and state machine are necessary, provide those in the design. Again use an asynchronous negative edge reset.

Verilog

module question_4 (input [7:0] in, input load, input clk_sr, input reset_n, output out);

reg
[7:0] stored ;
assign
out = stored[7];
always
@ (negedge load)
   stored
<= in;

always
@ (posedge clk_sr)
   
begin
       
if (~reset_n)
           stored
<= 0;
       
else
           stored
<= stored << 1;
   
end


Test Simulation

`timescale 1ns / 1ps

module test_q2;

reg [7:0] in ;

reg load , clk_sr, reset_n;

wire out;

question_4 uut (.in,

                .load,

                .clk_sr(clk_sr),

                .reset_n(reset_n),

                .out(out));

always #8000  clk_sr = ~clk_sr;    //16000 = 16MHz

initial begin

         clk_sr = 0;

         reset_n = 0;

     #100;

         reset_n = 1;

         in = 72;

         load = 1;


   
#100;
        reset_n
= 1;
       
in = 0;
        cmd
= 1;
   

     #8000
   
#8000
   
#8000
       
in = 1;
   
#8000
   
#8000
   
#8000
       
in = 0;

end
endmodule

Test Results

Here we are using the clk_sr at 16MHz. Initially load is high and in is 01001000 which then gets loaded to our Shift Register.Load becomes 0 and reset is high. Thus we get the result of out where we see a NRZ format of serial for 01001000.