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.
Multiple clock signals out of phase 16
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)
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
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
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
Create a behavior to perform the following:
`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
`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
        
Use the Xilinx Zybo board to develop a system using the onboard switches, LEDs, and an external Seven segment display.
`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
`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
`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
`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
`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
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.
`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
`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
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.
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%.
`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
`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
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.
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.
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
`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.