在verilog中记录按钮点击次数

在verilog中记录按钮点击次数,verilog,state,Verilog,State,我正在用verilog创建一台自动售货机。FPGA板上有一个按钮用作硬币插入器,每次按下该按钮,用户可以花费的总金额将增加一个“四分之一”,并在左侧和右侧七段显示屏上显示总金额 前。 第一次按键:25美分 按第二个按钮:50美分 第三次按键:75美分 第四个按钮:1.00美元(七段显示屏上为10美元)。 在第四次按下按钮后不会增加 input quarterIn, output reg [4:0] state, output reg [4:0] next_state, output re

我正在用verilog创建一台自动售货机。FPGA板上有一个按钮用作硬币插入器,每次按下该按钮,用户可以花费的总金额将增加一个“四分之一”,并在左侧和右侧七段显示屏上显示总金额

前。 第一次按键:25美分 按第二个按钮:50美分 第三次按键:75美分 第四个按钮:1.00美元(七段显示屏上为10美元)。 在第四次按下按钮后不会增加

 input quarterIn,
 output reg [4:0] state,
 output reg [4:0] next_state,
 output reg totalChange,
output reg [7:0] RSSD,
output reg [7:0] LSSD
);

 /***coin implementation***/
 parameter
    c0 = 0,
    c1 = 1,
    c2 = 2,
    c3 = 3,
    c4 = 4;
始终@(posedge时钟)
开始
状态=下一个状态;
结束

 always @ (quarterIn or totalChange)
 begin
    case(totalChange)
    0: begin if(quarterIn == 1) totalChange = 1; state = c1; end
    1: begin if(quarterIn == 1) totalChange = 2; state = c2; end
    2: begin if(quarterIn == 1) totalChange = 3; state = c3; end
    3: begin if(quarterIn == 1) totalChange = 4; state = c4; end
    4: begin if(quarterIn == 1) totalChange = 4; state = c4; end
    endcase
 end

我被困在如何计算按钮点击次数的问题上。我可以在七段式显示屏上看到第一个值,但不确定如何增加总硬币数。我无法通过自己的研究找到任何关于这方面的信息

据我所知,您需要一个饱和计数器来跟踪按钮的按下情况

为了计数,系统中需要一个时钟:

input clock;
您需要一个复位信号来将计数器初始化为已知值,在这种情况下为零:

input reset;
计数器(相当于
状态
变量,我把它称为
num\u push
):

饱和计数器可通过以下方式指定:

always @(posedge clock) begin
    if (reset) begin                     // Active high, synchronous reset
        num_push <= 3'b0;
    end else begin
        if (quarterIn == 1'b1 && num_push != 3'b100) begin
            num_push <= num_push + 3'b1;
        end
    end
end
我们应该在设计中只使用
quartin\u sync
,而不要直接使用
quartin
。对于
重置
信号,也应执行相同的操作

其次,来自按键的信号需要去抖动。去Bouncing本身就是一个完整的主题,所以我暂时跳过它:(

另一件事是,
时钟
需要从车载时钟发生器电路中拉出,该时钟将以几MHz的频率运行。典型的按钮按下持续约500毫秒,这意味着我们的计数器将在一次按下中采样几十万次按键。为了避免这种情况,我们应该计算
四分之一的边缘n_sync
,而不是级别:

wire quarterIn_edge;
req  quarterIn_sync_f;

always @(posedge clock) begin
    if (reset) begin
        quarterIn_sync_f <= 1'b0;
    end else begin
        quarterIn_sync_f <= quarterIn_sync;
    end
end

assign quarterIn_edge = quarterIn_sync & ~quarterIn_sync_f; // Detects rising edge

我们完成了!

状态必须保存在寄存器中。这需要触发器,即通常在“posedge clk”上更新的代码。@JohanL诸如此类?'always@(posedge时钟)begin state=next_state;end’好吧,您存储的状态本质上是
totalChange
,所以这就是需要存储的状态。
reg quarterIn_f;
reg quarterIn_sync;

always @(posedge clock) begin
    quarterIn_f    <= quarterIn;
    quarterIn_sync <= quarterIn_f;
end
wire quarterIn_edge;
req  quarterIn_sync_f;

always @(posedge clock) begin
    if (reset) begin
        quarterIn_sync_f <= 1'b0;
    end else begin
        quarterIn_sync_f <= quarterIn_sync;
    end
end

assign quarterIn_edge = quarterIn_sync & ~quarterIn_sync_f; // Detects rising edge
always @(posedge clock) begin
    if (reset) begin
        num_push <= 3'b0;
    end else begin
        if (quarterIn_edge == 1'b1 && num_push != 3'b100) begin
            num_push <= num_push + 3'b1;
        end
    end
end