Leds
Leds are the simplest of the output devices. A led is basically a “light bulb” with two pins. One of the pins is known as “cathode”, the other pin is called “anode”. The longer leg is the anode.
A led will emit light only when the anode is 1 and cathode is zero. In all the other cases, it will not emit light.
Anode | Cathode | Will it emit light? |
0 | 0 | no |
0 | 1 | no |
1 | 0 | YES |
1 | 0 | no |
In most cases, cathode of the diode is permanently connected to zero.
Switches and Buttons
Switches and buttons are the simplest input devices.
A button is a hardwire device with a 1-bit output. This output becomes 1 when the button is pressed. It is 0 when the button is released.
A switch is a button with two positions. In one position, its output is permanently 1. In the other position, its output is permanently 0. Pressing the switch (or shifting it to left or right) will change its output. Switches can be said to be “buttons with memory”.
Using Leds and buttons in Verilog
During the pin assignment stage,
- A button must be connected to an input variable
- A led must be connected to an output variable.
Then, that input variable’s value will follow button’s value: Whenever the button is pressed, the input variable will take the vaule 1. Otherwise, it will be zero. An the led will get on or off depending on the value of the output variable to which it was assigned. Whenever the output variable becomes 1, it will get on. Otherwise, it will get off.
Example 1: Let us write a module module which will burn a led if a button is pressed
module button_to_led(sw,led); input logic sw; //during pin assignment, assign to a button output logic led; //during pin assignment, assign to a led assign led = sw; endmodule
Example 2: Let us write a module which will count how many times a button is pressed and display the result as a 4-bit binary number. Note that a buttonpress is defined as pressing and releasing a button.
module bounced_switch(sw,led,clk); input logic sw; //during pin assignment, assign to a button output logic [3:0] count; //during pin assignment, assign each bit to a led logic old; always_ff @posedge(clk) begin old <= x; if ( old == 1'b0 & x == 1'b1 ) //detect the edge count <= count+ 4'b1; end endmodule
Debouncing
In most cases, example 1 will not work properly.
DIP Switches and Buttons
A DIP switch is a set of electric switches that are packaged together dual in-line package (DIP).
Debouncing Problem
All mechanical components (DIP-switches, pushbuttons etc) suffer from debouncing problem. Whenewer the position of a switch is changed or a button is pushed, it takes approximately 20ms for the switch/button output to settle into its new value.
Let us try to clarify this problem by means of an example: Assume that the output of the unpressed button is 0. Now somebody presses the button and its output eventually settle at 1. But immediately after it is being pressed, its output will oscillate between 0 and 1 before being settled into 1. This is called “bouncing”. In practical terms, we can say that after being pressed, the output of the button will be unavailable for 20 ms.
Now assume that the person who pressed the button released it. The button output will eventually settle to 0. But immediately after it is being released, its output will oscillate between 0 and 1 before being settled into 0. In practical terms, we can say that after being pressed, the output of the button will be unavailable for 20 ms.
It is possible to buy “debounced switches and buttons” in the market. These components have additional hardware ingredients inside them which filter out the 20ms oscillations and give a clean 0-1 or 1-0 transition to the user. The four buttons on your De0-nano kits are all debounced. Naturally, such components are more expensive..
In sequential designs working under a clock, bouncing buttons werak havoc. Such buttons must be “debounced” before use. We will se how this is done in a future chapter.
module debounced_switch(ds,clk,display,grounds); input logic ds; input clk; output logic [6:0] display; output logic [3:0] grounds; logic [15:0] number; logic [31:0] buffer; logic state; logic [25:0]clk1; //clk1 signal oscilates with 50MHz/2^16 = 775 Hz //which means, a period of clk1 is 0.0013 sec //as the debounce period is 20ms, we need to wait 20 clocks //for a clean signal always_ff @(posedge clk)// clk1<=clk1+1; always_ff @(posedge clk1[15]) begin buffer <= {buffer[30:0],ds}; case (state) 1'b0: begin if(&(buffer)== 1) // or if(buffer == 32'b1) begin number<=number + 1; state<=1; end end 1'b1: begin if(|(buffer) == 0) // or if(buffer == 32'b0) state<=0; end endcase end sevensegment ss1 (.datain(number), .grounds(grounds), .display(display), .clk(clk)); initial begin number=0; state=0; buffer = 32'b0; end endmodule