2017-04-26 118 views
0

我正在verilog中創建自動售貨機。 FPGA板上有一個按鈕用作硬幣插入器,每次按下按鈕時,它將爲用戶可花費的總金額增加一個「四分之一」,並將總數顯示在左側和右側七段顯示器上。在Verilog中保持按鈕點擊數

例。 第一個按鈕推動:25美分 第二個按鈕推動:50美分 第三個按鈕推動:75美分 第四個按鈕推動:$ 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

各州必須保存在登記冊中。這需要觸發器,即通常在「posedge clk」上更新的代碼。 – JohanL

+0

@JohanL所以這樣的事情? 'always @(posedge clock) \t begin \t state = next_state; \t end' – grimes88

+0

那麼,你的存儲狀態基本上是'totalChange',所以這就是需要存儲的內容。 – JohanL

回答

0

從我的理解,你需要一個飽和計數器來跟蹤按鈕按下。

爲了計算,你需要一個時鐘系統:

input clock; 

你還需要一個復位信號,在這種情況下,計數器初始化爲已知值,零:

input reset; 

,計數器(相當於state變量,讓我只是把它num_push):

reg [2:0] num_push; 

的飽和計數器可以指定這樣說:在你的FPGA

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 

這將合成與一個計數器計數啓用和啓用將等於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典型的按鍵持續時間約爲500ms,這意味着我們的計數器將在一次按鍵中採樣幾十萬按鍵。爲了避免這種情況,我們應該算邊緣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_edge更換quarterIn在飽和計數器代碼:

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 

,我們就大功告成了!