Sie sind auf Seite 1von 13

Lab 9: Counters, Clock

Dividers, and Debounce


Circuits
Deanna Sessions
ECEN 248-511
TA: Priya Venkatas
Date: November 6, 2013

Objectives:
The purpose of this lab is to solidify our understanding of sequential circuits and behavioral
Verilog by introducing the binary counter. This will be built via the usage of previously
configured circuits and calling their functions. This will demonstrate the usage of binary counters
on the Xilinx board and use them to perform clock frequency division and I/O debouncing.
Clock frequency division is the process by which we can generate a slower clock from a faster
clock and thereby allow for two circuits running at different speeds to be run by the same clock.
Signal debouncing refers to being able to have a circuit that runs in non-ideal conditions. Mainly
these non-ideal conditions refer to electrical chatter caused when buttons are pushed producing
electric pulses or a bouncing signal so debouncing refers to alleviating the circuit outputs of
this problem.

Design:
Below are the source codes for all of the circuits we simulated as well as the .ucf code we had to
write ourselves.
//clock divider
`timescale 1ns / 1ps
`default_nettype none
module clock_divider(ClkOut, ClkIn);
//this program takes the clock signal and divides it
output wire [3:0] ClkOut;
//divided signal
input wire ClkIn;
//initial clock
parameter n = 5;
reg [n-1:0] Count;
//Counter
always@(posedge ClkIn)
Count <= Count + 1;

//Count when the input has a positive edge

assign ClkOut[3:0] = Count[n-1:n-4];


endmodule
//half adder
`timescale 1ns / 1ps
`default_nettype none
module half_adder(S, Cout, A, B);
// first we declare the variables
input wire A, B;
output wire S, Cout;
assign S = A ^ B;
assign Cout = B & A;
endmodule

// output for the S


// output for Cout function

//up counter
`timescale 1ns / 1ps
`default_nettype none
module up_counter(Count, Carry3, En, Clk, Rst);
output reg [3:0] Count;
output wire Carry3;
input wire En, Clk, Rst;
wire [3:0] Carry, Sum;

//output counter
//final carry output
//Enable, Clock, Reset
//Four carry and sum within the circuit

half_adder half0(Sum[0], Carry[0], En, Count[0]);


half_adder half1(Sum[1], Carry[1], Carry[0], Count[1]);
half_adder half2(Sum[2], Carry[2], Carry[1], Count[2]);
half_adder half3(Sum[3], Carry[3], Carry[2], Count[3]);

//define the half adders that are used

assign Carry3 = Carry[3];


always@(posedge Clk or posedge Rst)
if(Rst)
Count <= 0;
else
Count <= Sum;

//Do this when the clock or reset goes from low to high
//If it is the reset then set count to zero

//if it is the clock then set the count to the sum

endmodule
//top level
`timescale 1 ns/ 1 ps
`default_nettype none
module top_level (LEDs, SWs, North, South, FastClk);
output wire [4:0] LEDs;
//the LEDs show the outputs
input wire [1:0] SWs;
//Switches
input wire North, South, FastClk;
//North button, south button, faster clock (original clock)
reg SlowClk;
//slow clock (derived from fast clock)
wire [3:0] Clocks;
//each clock
always@(*)
case(SWs)
2'b00: SlowClk =Clocks[0];
2'b01: SlowClk =Clocks[1];
2'b10: SlowClk =Clocks[2];
2'b11: SlowClk =Clocks[3];
endcase

//sets the clocks based on binary input of switches

up_counter upcounter0(LEDs[3:0], LEDs[4], North, FastClk, South); //calls the up counter


clock_divider clk_div0( //calls the clock divider
.ClkOut(Clocks),
.ClkIn(FastClk)
);
endmodule

//top level ucf


#switches
NET "SWs[0]" LOC="L13" | IOSTANDARD = LVTTL;
NET "SWs[1]" LOC="L14" | IOSTANDARD = LVTTL;

//Sets the switches to certain parts on the board

#Push buttons
NET "North" LOC = "V4" |IOSTANDARD = LVTTL | PULLDOWN; //assigns the north and south commands to buttons
NET "South" LOC = "K17" |IOSTANDARD = LVTTL | PULLDOWN;
#LEDs
NET "LEDs[0]" LOC = "F12" | IOSTANDARD = LVTTL;
NET "LEDs[1]" LOC = "E12" | IOSTANDARD = LVTTL;
NET "LEDs[2]" LOC = "E11" | IOSTANDARD = LVTTL;
NET "LEDs[3]" LOC = "F11" | IOSTANDARD = LVTTL;
NET "LEDs[4]" LOC = "C11" | IOSTANDARD = LVTTL;
NET "FastClk" LOC ="C9" | IOSTANDARD = LVTTL;

//assigns the LEDs to specific LEDs on the board

//assigns the clock

NET "FastClk" PERIOD = 20.0 ns HIGH 40%;


//clock divider ucf
NET "ClkOut[0]" LOC = "B4" | IOSTANDARD = LVTTL; #J0
NET "ClkOut[1]" LOC = "A4" | IOSTANDARD = LVTTL; #J1
NET "ClkOut[2]" LOC = "D5" | IOSTANDARD = LVTTL; #J2
NET "ClkOut[3]" LOC = "C5" | IOSTANDARD = LVTTL; #J3
NET "ClkIn" LOC = "C9" | IOSTANDARD = LVCMOS33 ;
# Define clock period for 50 MHz oscillator
NET "ClkIn" PERIOD = 20.0ns HIGH 40%;

//assigns clock outputs to certain parts on the board

//assigns clock in

//switch bounce
`timescale 1ns / 1ps
//Written to demonstrate bounce in a switch
module switch_bounce(
input wire Center,
output wire J1_0
);
assign J1_0 = Center;
endmodule
//switch bounce ucf
#UCF for observing switch bounce
NET "J1_0" LOC = "B4" | IOSTANDARD = LVTTL | SLEW = FAST; #J1_0
NET "Center" LOC = "V16" | IOSTANDARD = LVTTL | PULLDOWN | SLEW = FAST; #ROT_CENTER
//nodebounce
`timescale 1ns / 1ps
`default_nettype none
/*This module describes a counter that is triggered off of*
*the rising-edge of an signal that has not been debounced*
*in order to demonstrate the effects of switch bounce */

module noDebounce(LEDs, Center, Clk);


/*The output LEDs are of type reg because they are*
*modified using behavioral Verilog
*/
output reg [7:0] LEDs;
input wire Center, Clk;
/*intermediate nets*/
reg edge_detect0, edge_detect1;
wire rising_edge;//asserted when an edge is detected
/*describe an edge-detector circuit which detects*
*a rising-edge of an asynchronous signal. The *
*usage of two flip-flops may seem redundant but *
*is necessary for synchronization purposes! */
always@(posedge Clk)
begin
edge_detect0 <= Center;//input signal
edge_detect1 <= edge_detect0;
end
/*when older value is 0 and new value is 1, a *
*rising edge has occurred
*/
assign rising_edge = ~edge_detect1 & edge_detect0;
/*describe a counter that increments each time a*
*rising-edge of input signal is detected
*/
always@(posedge Clk)
if(rising_edge)
LEDs <= LEDs + 1;
endmodule
//nodebounce ucf
#Push-buttons
NET "Center" LOC = "V16" | IOSTANDARD = LVTTL | PULLDOWN | SLEW = FAST; #ROT_CENTER
# LEDs
NET "LEDs[0]"
NET "LEDs[1]"
NET "LEDs[2]"
NET "LEDs[3]"
NET "LEDs[4]"
NET "LEDs[5]"
NET "LEDs[6]"
NET "LEDs[7]"

LOC = "F12" | IOSTANDARD = LVTTL; #LD0


LOC = "E12" | IOSTANDARD = LVTTL; #LD1
LOC = "E11" | IOSTANDARD = LVTTL; #LD2
LOC = "F11" | IOSTANDARD = LVTTL; #LD3
LOC = "C11" | IOSTANDARD = LVTTL; #LD4
LOC = "D11" | IOSTANDARD = LVTTL; #LD5
LOC = "E9" | IOSTANDARD = LVTTL; #LD6
LOC = "F9" | IOSTANDARD = LVTTL; #LD7

#Clock constraints
NET "Clk" LOC = "C9" | IOSTANDARD = LVCMOS33 ;
# Define clock period for 50 MHz oscillator
NET "Clk" PERIOD = 20.0ns HIGH 40%;

//withDebounce
`timescale 1ns / 1ps
`default_nettype none
module withDebounce(LEDs, Center, Clk);
output reg [7:0] LEDs;
input wire Center, Clk;
/*-this is a keyword we have not seen yet!*
*-as the name implies, it is a parameter *
* that can be changed at compile time... */
parameter n = 18;
wire notMsb, Rst, En, Debounced;
reg Synchronizer0, Synchronized;
reg [n-1:0] Count;
reg edge_detect0;
wire rising_edge;
/********************************************/
/* Debounce circuitry!!!
*/
/********************************************/
always@(posedge Clk)
begin
Synchronizer0 <= Center;
Synchronized <= Synchronizer0;
end
always@(posedge Clk)
if(Rst)
Count <= 0;
else if(En)
Count <= Count + 1;
assign notMsb = ~Count[n-1];
assign En = notMsb & Synchronized;
assign Rst = ~Synchronized;
assign Debounced = Count[n-1];
/********************************************/
/* End of Debounce circuitry!!!
*/
/********************************************/
always@(posedge Clk)
edge_detect0 <= Debounced;
assign rising_edge = ~edge_detect0 & Debounced;
always@(posedge Clk)
if(rising_edge)

LEDs <= LEDs + 1;


endmodule
//withDebounce ucf
//used to demonstrate the program with the debounce program
#Push-buttons
NET "Center" LOC = "V16" | IOSTANDARD = LVTTL | PULLDOWN | SLEW = FAST; #ROT_CENTER
# LEDs
NET "LEDs[0]"
NET "LEDs[1]"
NET "LEDs[2]"
NET "LEDs[3]"
NET "LEDs[4]"
NET "LEDs[5]"
NET "LEDs[6]"
NET "LEDs[7]"

LOC = "F12" | IOSTANDARD = LVTTL; #LD0


LOC = "E12" | IOSTANDARD = LVTTL; #LD1
LOC = "E11" | IOSTANDARD = LVTTL; #LD2
LOC = "F11" | IOSTANDARD = LVTTL; #LD3
LOC = "C11" | IOSTANDARD = LVTTL; #LD4
LOC = "D11" | IOSTANDARD = LVTTL; #LD5
LOC = "E9" | IOSTANDARD = LVTTL; #LD6
LOC = "F9" | IOSTANDARD = LVTTL; #LD7

//assigns all of the LEDs

#Clock constraints
NET "Clk" LOC = "C9" | IOSTANDARD = LVCMOS33 ;
# Define clock period for 50 MHz oscillator
NET "Clk" PERIOD = 20.0ns HIGH 40%;

Results:
Below are the waveforms of the various experiments throughout the lab and they are labeled
accordingly.
Figure 1: Waveforms of Experiment 1

Figure 2: Measuring the wavelength of count 0 of Experiment 1

Figure 3: Measuring the wavelength of count 1of Experiment 1

Figure 4: Measuring the wavelength of count 2 of Experiment 1

Figure 5: Measuring the wavelength of count 3 of Experiment 1

Figure 6: Up Counter waveform

Figure 7: Top Level waveform

Figure 8: Switch Bounce

Figure 9: Switch bounce after pressing the button twice

Figure 10: Switch with debounce

Conclusion:
The code ran according to plan and I learned a bit more about the inner workings of the circuit
and this was the first time we experienced the real world time delay and bounce in the circuit.
When studying circuits it seems like a few nanoseconds of delay here and there wouldnt matter,
but it really starts to accumulate in a circuit. This means that I need to be more careful in
calculating these delays when I am designing circuits to make sure that all of the information
gets to the right place at the right time. This was also the first lab that we used the oscilloscope
with Verilog and it was really neat to see how the clocks make wave patterns and being able to
physically visualize the delays and the clock dividers.

Questions:
1.
2.
3.
4.

Source code included in the design section.


UCFs included in the design section.
Screenshots included in results.
Questions:
a. Experiment 1: Based on your measurements what frequency do you think the
input clock is running at?
i. 0 wave = 80 ns
ii. 1 wave = 160 ns

b.
c.
d.

e.

f.

g.

iii. 2 wave = 320 ns


iv. 3 wave = 640 ns
v. This insinuates that the clock is running at 12.5 MHz
Experiment 2: What is the frequency of the up-counter clock signal?
i. 100 MHz
How long is the reset interval for the up-counter?
i. 20 ns
How long does the up-counter hold the enable LOW for before allowing the
counter to run?
i. 20 ns
What is the maximum count value and what signal in the waveform can be used
to know exactly when the counter is going to roll-over?
i. The signal rolls over at the end of F (195 ns) and the signal to watch out for
is when carry 3 is high for 10 ns.
If a 50 MHz clock is used to drive the frequency divider in clock_divider, what
rate will the most significant bit of the divider oscillate at?
i. This will oscillate at 50 MHz
Experiment 3: What does switch_bounce.v and .ucf describe?
i. These two files are just a program written to demonstrate what happens
when a switch is flipped. Switch_bounce.v is a simple program which is an
input of a button being pressed and an output of a high value. This
demonstrates the interference that occurs immediately after the button is
pressed. This interference is then fixed by the debounce file.

Student Feedback:
1. I liked that we used the oscilloscope. I didnt like the partner work. I feel like I
understand much better when I am coding and doing the measurements myself, but it
would have been far too much work to finish on my own in one class period.
2. Nothing about the lab manual was unclear.
3. Minimizing partner work (if possible) would be nice. Not that I dont like Thomas, but I
would have learned more if I was doing it myself. Teamwork is great, but in coding I
think hands on is much better.

Das könnte Ihnen auch gefallen