Verilog Code for counter increment on button press
We will present an important verilog code that will form the basis of some more important verilog topics. We will discuss how a push button press can increment counter and display it on a 7 segment display.
This is how it looks like..
There are two inputs to the circuit - a button_in
and a n_reset
. On pressing button_in
the counter increments by 1. On pressing n_reset
the counter resets to 0.
If you wish to understand the code, we strongly recommend that you go though the following posts ( in that order)
1. Binary to 7 Segment Display
2. Implementation of Key Debounce
- The key debounce code will ensure that we have a stable input, otherwise, our counter will increment several times on pressing key once.
3. Level Change detection in Verilog
- We monitor the level change of the debounced output of the key.
If you understand the above three, it will be easy for you to follow the code below.
module counterdisplay ( input clk, n_reset, button_in, // inputs output leda, output ledb, output ledc, output ledd, output lede, output ledf, output ledg ); reg DB_out; reg [3:0] counter; reg [6:0] seg_data; reg [3:0] counter_reg; /* Parameter N defines the debounce time. Assuming 50 KHz clock, the debounce time is 2^(11-1)/ 50 KHz = 20 ms For 50 MHz clock increase value of N accordingly to 21. */ parameter N = 11 ; reg [N-1 : 0] delaycount_reg; reg [N-1 : 0] delaycount_next; reg DFF1, DFF2; wire q_add; wire q_reset; reg delay_reg ; // Registers for detecting level change of DB_out wire level_out; always @ ( posedge clk or negedge n_reset ) begin if(n_reset == 0) // At reset initialize FF and counter begin DFF1 <= 1'b0; DFF2 <= 1'b0; // For level change detection delay_reg <= 1'b0; delaycount_reg <= { N {1'b0} }; end else begin DFF1 <= button_in; DFF2 <= DFF1; delaycount_reg <= delaycount_next; delay_reg <= DB_out;// to detect level change end end assign q_reset = (DFF1 ^ DFF2); // Ex OR button_in on conecutive clocks // to detect level change assign q_add = ~(delaycount_reg[N-1]); // Check count using MSB of counter always @ ( q_reset, q_add, delaycount_reg) begin case( {q_reset , q_add}) 2'b00 : delaycount_next <= delaycount_reg; 2'b01 : delaycount_next <= delaycount_reg + 1; default : // In this case q_reset = 1 => change in level. Reset the counter delaycount_next <= { N {1'b0} }; endcase end always @ ( posedge clk ) begin if(delaycount_reg[N-1] == 1'b1) DB_out <= DFF2; else DB_out <= DB_out; end assign level_out = (delay_reg) & (~DB_out); always @(posedge clk ) if ( n_reset == 0) counter <= 0; else if ( level_out == 1'b1) begin if (counter < 9) counter <= counter +1; else counter <= 0; end always @(counter) case (counter) 4'b0000:seg_data=7'b1111110; 4'b0001:seg_data=7'b0110000; 4'b0010:seg_data=7'b1101101; 4'b0011:seg_data=7'b1111001; 4'b0100:seg_data=7'b0110011; 4'b0101:seg_data=7'b1011011; 4'b0110:seg_data=7'b1011111; 4'b0111:seg_data=7'b1110000; 4'b1000:seg_data=7'b1111111; 4'b1001:seg_data=7'b1111011; default:seg_data=7'b1111110; endcase assign leda=seg_data[6]; assign ledb=seg_data[5]; assign ledc=seg_data[4]; assign ledd=seg_data[3]; assign lede=seg_data[2]; assign ledf=seg_data[1]; assign ledg=seg_data[0]; endmodule
The following test bench may be used.
`timescale 1 us / 1 us module tb_counterdisplay(); reg clk; reg n_reset; reg button_in; wire DB_out; counterdisplay UUT ( .clk(clk), .n_reset(n_reset), .button_in(button_in) ); initial begin clk = 1'b0; n_reset = 1'b0; #20 n_reset = 1'b1; // at time 20 release the reset button_in = 1'b1; // We need at least twice the counter value to stabilize value of DB_out // before we change the button in #50000 button_in = 1'b0; // We pressed the key here #400 button_in = 1'b1; // Key debounce to 1 after 400 micro seconds #800 button_in = 1'b0; // Debounce after 800 ms #2000 button_in = 1'b1; // Decounce after 2 ms #800 button_in = 1'b0; #40000 button_in = 1'b1; #4000 button_in = 1'b0; #40000 button_in = 1'b1; #400 button_in = 1'b0; #800 button_in = 1'b1; #800 button_in = 1'b0; #800 button_in = 1'b1; #40000 button_in = 1'b0; #40000 button_in = 1'b0; #400 button_in = 1'b1; #800 button_in = 1'b1; #800 button_in = 1'b0; #800 button_in = 1'b1; #40000 button_in = 1'b0; #40000 button_in = 1'b0; #4000 button_in = 1'b1; $finish; end always #10 clk = ~clk; // 20 mirco seconds = 50 KHz Clock cycle initial begin $dumpfile ("debounce.vcd"); $dumpvars (0,DeBounce_tf); end endmodule
Hi, if I understood correctly, what your program does is it increments by 1 whenever you push the button. I have an almost similar task but I have no idea what to do at this point because I'm really noob toVerilog. In our homework, we are tasked to implement a basketball scoreboard using the Altera DE1.
1. The Altera DE1 we use has 4 7-segment displays.
2. In the first 2 7-segment displays, we have to show the score of the 1st team.
3. In the last 2 7-segment displays, we have to show the score of the 2nd team.
4. The Altera DE1 we use has 4 push buttons (PB0 - PB3)
5. If we push PB0, the score of the 1st team should increase by 1. If we push PB1, the score of the 1st team should decrease by 1.
6. Similar logic for the 2nd team except we should use PB2 and PB3.
How do I do this? I really you could help me. Please and Thank you.
@Andy Marty
We have to assume that the score is only up to 99.
How do you do this for 2 digits?