我正在用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
我对如何记录按钮点击次数感到困惑。我可以看到七段显示的第一个值,但我不确定如何增加总硬币。我试图自己研究,无法找到任何关于此的信息。
答案 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
我们已经完成了!