在verilog中保持按钮点击次数

时间:2017-04-26 14:22:15

标签: verilog state

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

实施例。 第一按钮:25美分 第二个按钮:50美分 第三按钮:75美分 第4个按钮:$ 1.00(七段显示器上10个)。 按下第4个按钮后不会增加。

 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;

always @(posedge clock) begin state = next_state; end

 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

我对如何记录按钮点击次数感到困惑。我可以看到七段显示的第一个值,但我不确定如何增加总硬币。我试图自己研究,无法找到任何关于此的信息。

1 个答案:

答案 0 :(得分:0)

根据我的理解,你需要一个饱和的计数器来跟踪按钮按下。

为了计算,您需要系统中的时钟:

input clock;

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

input reset;

和计数器(相当于state变量,让我称之为num_push):

reg [2:0] num_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

这将合成到FPGA上具有计数使能的计数器,并且使能将等于quarterIn == 1'b1 && num_push != 3'b100。您可以按reset重新开始。

现在,在我们将它放在FPGA上之前,有一些问题需要解决。首先,quarterIn需要与亚稳态同步:

reg quarterIn_f;
reg quarterIn_sync;

always @(posedge clock) begin
    quarterIn_f    <= quarterIn;
    quarterIn_sync <= quarterIn_f;
end

我们应该只在设计中使用quarterIn_sync,而不是直接使用quarterIn。您也应该对reset信号执行相同的操作。

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

另一件事是clock需要从板载时钟发生器电路中拉出,这个时钟将以几MHz运行。一个典型的按钮按下持续约500毫秒,这意味着我们的计数器将在一次按下采样几十万个按键。为避免这种情况,我们应该计算quarterIn_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

现在,将饱和计数器代码中的quarterIn替换为quarterIn_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

我们已经完成了!