Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

push button to select a number verilog

Status
Not open for further replies.

antlhem

Member level 1
Joined
Dec 8, 2016
Messages
41
Helped
0
Reputation
0
Reaction score
0
Trophy points
6
Activity points
364
Hello, I need some help on pressing a button to select a number, but only when I press the button (negedge), the button can be pressed long time with no more changes on the number selected. So far what I get is that when I press the button for 4 clk cycles (in the simulator) it immediately select 4 numbers, or verilog (Quartus 13) assumes that the button is activated always and automatically select the for numbers. What I need is to select the number only when I press the button. The code is the following:


Code Verilog - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
module num_selec(clk, select, num, led);
input wire clk, select;
input wire [6:0] num;
output reg led;
 
reg [6:0] a = 7'd10, b = 7'd10, c = 7'd10, d = 7'd10;
reg [6:0] a2 = 7'd10, b2 = 7'd10, c2 = 7'd10, d2 = 7'd10;
 
reg [27:0] y, y2; 
reg [6:0] num2 [3:0];
reg [2:0] i = 3'd0; 
reg select2 = 1'b0;
 
//code in this question**********
always @ (negedge select)
    if(!select) select2 <= 1'b1;
    else select2 <= 1'b0;
//*******************************
 
always @ (posedge clk) begin //when I put 'negedge select' it does nothing 
//still need to add rst
y = {a,b,c,d};
y2 = {num2[0],num2[1],num2[2],num2[3]};
    if(i==4) begin
        if(y == y2)//comparing two concatenated values
            led = 1'b1;//the numbers are the same
        else
            led = 1'b0;//not the same
    end
    else begin
        if(select2) begin //changed from select
            num2[i] <= num;
            i = i + 3'd1;//index register
        end
    end
end
endmodule

 
Last edited by a moderator:

Hi,

Your explanation isn't clear to me:
* do you just want edge detect of your key?
* or level triggered?
* do you want radio button function?

A simple timing diagram could clarify this.
****
You talk about 4 clock cycles. If the clock is higher than some 100 Hz, then you need extra debounce logic for a mechancal key to avoid multiple triggering.

Klaus
 

First of all buttons will have contacts that bounce when being closed and many times when being opened too.

You need to debounce your select input. You need to make sure the value you are waiting for is there for at least 10-20 ms before generating a debounced output (db_select) that indicates the switch has changed to a new level. This will give you a clean transition in real hardware.

Next what you want is a falling edge detect. Delay the db_select signal (the debounced switch output) and check the state of both the delayed and the select signal for a falling edge you look for:
db_select == 0
delayed_input == 1

when you see that condition you have found the leading falling edge of the button input.

Don't use the select as a clock that pretty much guarantees your design will misbehave in hardware.

Don't use blocking (=) assignments in an edge triggered always block if used incorrectly (i.e. with feedback they can result in simulation synthesis mismatches, your simulated working code does not work in hardware).

The rest of your code doesn't make much sense as it doesn't seem to do what you've described in your question. It looks like with the counter you are making a shift register but using software concepts instead of hardware concepts to do so. You need to understand Verilog is a hardware description language, so parallel structures like shift registers can be implemented directly instead of using software style array indexing to do the same thing. It also seems like the entire code is implemented sort of like a direct translation of software.

Code Verilog - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
assign y2 = {num[0], num[1], num[2], num[3]};
 
always @(posedge clk) begin
  // four 7-bit value shift register
  num[3] <= num;  // use non-blocking (<=) assignments in posedge/negedge always blocks
  num[2] <= num[3];
  num[1] <= num[2];
  num[0] <= num[1];
end
 
// or using a generate, makes it easier if the array size changes
genvar n;
generate
for (n=0, n<4;n=n+1) begin : GEN_NUM
  if (n=0) num[n] <= num;
  else num[n] <= num[n-1];
end
endgenerate


in either case after 4 clocks the num values will have been loaded in the same order as your code 0,1,2,3.

- - - Updated - - -

Reading you question over again, you definitely have a problems with the concept of time in a clocked always block, every clock the stuff inside the always block is scheduled. therefore as soon as select2 goes active the next 4 clocks will result in the if statement taking the select2 branch and incrementing and assigning the four num[#] locations with the num value. Which is what you are getting.

Like I said this is not software.
 

Hi,

Your explanation isn't clear to me:
* do you just want edge detect of your key?
* or level triggered?
* do you want radio button function?

A simple timing diagram could clarify this.
****
You talk about 4 clock cycles. If the clock is higher than some 100 Hz, then you need extra debounce logic for a mechancal key to avoid multiple triggering.

Klaus

Hi KlausST, thank you for replying

I want edge detect, because I want to select a number just in each edge.
About the clock, yes, is actually 50MHz, and what I want is to select only when I press the button, not in each edge clk.

- - - Updated - - -

- - - Updated - - -

@ads-ee thanks for your replying.

I will add the code to debounce the button. And indeed I just started to learn Verilog using Quartus from some days ago.
Describing the code, what I am trying to do is to select 4 numbers (only when I press select) from the input, concatenate them in 'y2', when 4 numbers have been selected I check if they match with 'y' (another concatenated) and only if they match the LED turns on.

Exactly what I want to avoid is that the if statement executes all the time, but only I press the button.

I tried to use 'assign y2 = ...' but I get the error of: object "y2" on left-hand side of assignment must have a net type. Should I use another type instead of 'reg'?
 
Last edited:

Wire is used with assign, but in your case you need to use the edge detected signal as an enable for all your registers. The one that holds the concatenated y2 should only be updated on the count of 3 when the enable comes in (the first 3 enables would be ignored)
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top