Button increment counter (2-bit) verilog

Status
Not open for further replies.

Spectre90

Newbie level 6
Joined
Nov 15, 2014
Messages
11
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Visit site
Activity points
85
Ok I know this might sound stupid and maybe easy, but I want to make a module in verilog that each time I press button and release once, the output will be either binary: 00,01,10,11,00,01...etc.

Basically I want to make count up once each time I press the button.
When I attempted to code it, I kept counting continuously when I press on the button. I want to press it as long as I want and the output should be only whatever comes next once

Example:
It's starts at 00
I press it for 2 seconds then release, the output will be 01, then I press for 5 seconds then release, output should be 10 and same with last one for x amount of time.


I'm guessing I need a clock and active low button trigger and also take deboucing.

Note: I have made a clock divider module to lower the board's frequency from 50Mhz to whatever Hz (made a parameter to calibrate).
 

Hello, Ill try to answer a question as I seem to only leech off the boards so forgive me if this isn't that helpful.
I'm not that well versed in Verilog, I've mostly used VHDL but this might help you.

1) yes you are quite right you will need some denouncing for your switch these are common and you can find some code for it online.
2) have a power on/reset condition for your binary output. so on start-up you'll see "00".
3) does not matter whether you make your button active high or low. you need to do an edge detect on that signal to excite your binary output. if you choose active low. (when your finger is down then the value is '0') then you do a rising edge detect. on the button signal. to do this delay your button signal by one clock cycle on your fast clock. then compare the original with the delayed. if the original is '1' and the delayed is '0' then you've got a rising edge detect. (you would do the opposite for a active high signal) in VHDL you'd have this. the principle will hold true, the syntax will change in Verilog though. sorry
if rising_edge(clk) then
N_button_signal_del <= N_button_signal;
if N_button_signal = '1' and N_button_signal_del = '0' then -- rising edge
counter <= counter + '1'; -- or something
end if;
end if;

4) have a 2 bit signal (reg in Verilog I think) as a counter that you could output. have a reset condition, but not a default. then you wont see it.

hopefully this will help and I wont get banned from the forums

the village idiot :-?
 

This is the equivalent, in Verilog, of completelyuseless's post with VHDL (with signal names changed to protect the innocent ;-)). The name sync_debounce_button_n hopefully points out that you need to both debounce and synchronize the button to clk prior to using it.

Code Verilog - [expand]
1
2
3
4
5
6
7
8
reg [1:0] sync_debounce_button_n;
reg [1:0] cntr = 0;
always @ (posedge clk) begin
  sync_debounce_button_n[1] <= sync_decbounce_button_n[0];
  if (sync_debounce_button_n == 2'b01) begin
    cntr <= cntr +1;
  end
end

 

In tried the code you have wrote (not exactly) and It shows all the count
Example: when I hold down the button, the outputs (in LEDs) will count binary 0-3 until I release the button.

I am trying to get a button to toggle with 00,01,10,11 (in a loop) each time I press it.

:/
 

Then post all your code. You probably have an issue with the way you are implementing the debounce or the synchronization or did something different than what I posted, which breaks it.
 

Here's what i came up with:



module state(
input btn, clk, rst,
output [1:0]ld
);

reg [1:0]count = 0; //gives values from binary 0-3

reg enable = 1; //enable whenever the button is released

always@(posedge clk)
begin
if(rst)
count = 0;

if(btn)begin
if(enable)begin
count = count+1;
enable = 0;
if(count>3)
count = 0;
end
end
else
enable = 1;
end

assign ld = count;

endmodule
 

How about you take a look at this link:

**broken link removed**

Then you can copy/paste the syntax tag style for future posts of your code.

That and the traditional laundry list of usual stuff is wrong with your design. Short version: Get rid of the block assignments. And bonus points for verilog-2001 port style. Oh, and you currently have no debounce whatsoever, so you can start with those two things.

block vs non-block: https://www.asic-world.com/tidbits/blocking.html
debounce: see previous posts by ads-ee & completelyuseless as a starting point.
 

Ripping into what you've written...


Code Verilog - [expand]
1
2
3
4
module state (
  input           btn, clk, rst,
  output  [1:0]   ld
);


It's better to use one port on separate lines, primarily because you can then add comments describing the function of each port. Also lining things up in collumns makes reading things easier:

Code Verilog - [expand]
1
2
3
4
5
6
module state (
  input           btn,  // async button press, active ___?___
  input           clk,  // ?? MHz clock input
  input           rst,  // async/sync reset
  output  [1:0]   ld    // led output count value, in binary
);


See, this means your code is becoming self documenting and when you or someone else picks it up later they can easily see what you are doing.


Code Verilog - [expand]
1
2
reg   [1:0] count = 0; //gives values from binary 0-3
  reg         enable = 1; //enable whenever the button is released


enable is not necessary for the functioning of this circuit, and is just making things more complicated.


Code Verilog - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
always @ (posedge clk) begin
    if (rst)  // synchronous reset! I hope there is an upper level file, which syncrhonizes this to clk!!
      count <= 0;
 
    if (btn) begin  // Need to debounce and syncrhonize to clk!!
      if (enable) begin
        count <= count+1;
        enable <= 0; 
        if (count > 3)  // Uh, count can never reach a value greater than 3 and will rollover to 0 anyway.
          count <= 0;
      end
    end else  // pet peave, I can't stand mixed use of begin/end and none used. I always use them.
      enable <= 1;
  end
 
  assign ld = count; 
 
endmodule


You were using blocking assignments (I fixed that).

The problems here are the lack of synchnization of rst and btn to clk, unless that is done in a file that you did not include (I did say post all your code).

The if (rst) should be part include as part of the code that follows if (btn) begin. As it is written now the synthesis tool has to determine if the reset is priority encoded over the if (btn) begin code as they both affect the count value generated. Also if the two if statements were separated into different always blocks you would end up with a multiple driver error in your code. This might synthesize right now but is bad coding practice IMO.

The enable isn't helping and is actually making this more complicated looking. The original code I posted contains a rising edge detector, which generates a single clock cycle pulse (which is embedded in the compare) from the level output of a debounce circuit that uses a synchronized button press.

As I noted in the code the count > 3 does nothing and will be removed by synthesis. I've been seeing a lot of problems with being able to count and decide when to stop counting or rollover these past couple of months. Are schools not teaching students how to count anymore!?
 

don't trigger each time btn is a logic '1', instead trigger off an edge

always @(btn, btn_prev)
btn_re = btn & ~btn_prev;

always @(posedge clk)
btn_prev <= btn;

if (btn_re) begin...
 

Status
Not open for further replies.
Cookies are required to use this site. You must accept them to continue using the site. Learn more…