當(dāng)前位置:首頁 > 公眾號精選 > FPGA技術(shù)江湖

功能說明:

1. 搶答器為四人搶答器。


2. 利用六位數(shù)碼管進行顯示搶答器相關(guān)信息。


3. 第一個數(shù)碼管顯示搶答器的狀態(tài),第二個數(shù)碼管顯示搶到的編號,沒有搶答成功前顯示數(shù)字0;第三至六顯示搶答用的時間(以百分秒進行顯示)。


4. 板卡默認空閑狀態(tài)(第一個數(shù)碼管顯示字母A(空閑狀態(tài)),第二個數(shù)碼管顯示數(shù)字0),當(dāng)主持人按下?lián)尨鸢粹o后,進入搶答狀態(tài)(第一個數(shù)碼管顯示字母C(搶答狀態(tài)),第二個數(shù)碼管顯示0,第三至六數(shù)碼管開始記錄時間)


5. 在空閑狀態(tài)期間,選手按下按鍵沒有作用,當(dāng)進入搶答狀態(tài)后,選手誰先按下按鍵,第二個數(shù)碼管顯示對應(yīng)的編號(1、2、3、4)。


6. 當(dāng)選手搶答成功后,進入搶答成功狀態(tài)(第一個數(shù)碼管顯示F),但是第二個數(shù)碼管一直顯示上一次搶答成功的編號,第三至六顯示上一次搶答運行的時間。


7. 主持人按下復(fù)位按鈕后,再次進入空閑狀態(tài),第二個數(shù)碼顯示0,時間清除。


8. 每次主持人按下?lián)尨鸢粹o或者其他四人搶答成功時,蜂鳴器“叮”一聲。


使用平臺:本次設(shè)計應(yīng)用Altera的平臺設(shè)計(芯片:EP4CE10F17C8N)。

仿真平臺:Modelsim。

作者QQ:746833924

說明:本篇設(shè)計中不涉及到IP和原語,代碼在其他平臺依然可以適用;當(dāng)其他板卡電路不同時,會導(dǎo)致不同的現(xiàn)象出現(xiàn),如有需要修改代碼請聯(lián)系作者;如需作者使用的板卡,請聯(lián)系作者;


設(shè)計思想如下:



module responder (  input     wire                clk, // 50MHz input     wire                rst_n,  input     wire                key_reset, // 主持人復(fù)位按鈕 input     wire                key_start, // 主持人開始搶答按鈕  input     wire                key_1, //第一組的搶答按鈕 input     wire                key_2, //第二組的搶答按鈕 input     wire                key_3, //第三組的搶答按鈕 input     wire                key_4, //第四組的搶答按鈕  output    wire    [5:0]       sel, //數(shù)碼管的位選信號 output    wire    [7:0]       seg, //數(shù)碼管的段選信號  output    wire                beep //蜂鳴器驅(qū)動信號);  wire                          flag_reset; //  主持人復(fù)位脈沖 wire                          flag_start; // 主持人開始搶答脈沖 wire                          flag_1; //第一組搶答脈沖 wire                          flag_2; //第二組搶答脈沖 wire                          flag_3; //第三組搶答脈沖 wire                          flag_4; //第四組搶答脈沖  wire              [23:0]      show_data; // 顯示數(shù)據(jù)  wire                          flag_beep; // 蜂鳴器“叮”一聲的脈沖


key_ctrl模塊負責(zé)將外部的按鍵信號進行消抖,并且產(chǎn)生對應(yīng)邊沿變化時的脈沖;responder_ctrl模塊負責(zé)根據(jù)脈沖信號和設(shè)計邏輯產(chǎn)生對應(yīng)數(shù)字邏輯;seven_tube_drive(七段數(shù)碼管驅(qū)動)模塊負責(zé)將responder_ctrl模塊產(chǎn)生的數(shù)字邏輯顯示到數(shù)碼管上;beep_ctrl模塊負責(zé)根據(jù)一個脈沖驅(qū)動蜂鳴器“?!币宦暋?


key_ctrl模塊設(shè)計思想為:按鍵信號是由外部機械式按鍵產(chǎn)生,每次按下或者抬起時,會產(chǎn)生一定的抖動。如果直接對其進行邊沿檢測就會導(dǎo)致多次觸發(fā)。故而需要設(shè)計按鍵消抖,進而對消抖之后的波形進行邊沿檢測。消抖原理為:外部按鍵信號發(fā)生改變后,如果能夠持續(xù)20ms,沒有新的改變,就認為此次改變不是抖動,而是真正的按下,然后進行采樣即可。


// 記錄任意邊沿之后沒有遇到新的邊沿的時間長度是否達到20Ms

//---------------------------------------------------------------------------------------

always@(posedgeclk)begin

if(rst_n ==1'b0)

     cnt_20ms <=20'd0;

else

if(pulse_key_negedge ==1'b1||pulse_key_posedge ==1'b1)

       cnt_20ms <=20'd1;

else

if(cnt_20ms >20'd0&&cnt_20ms <T_20ms)

         cnt_20ms <=cnt_20ms +1'b1;

else

           cnt_20ms <=20'd0;

end

// ---------------------------------------------------------------------------------------

// 任意邊沿之后沒有遇到新的邊沿的時間長度達到20Ms,認為按鍵穩(wěn)定,此時采樣

//--------------------------------------------------------------------------------------

always@(posedgeclk)begin

if(rst_n ==1'b0)

     key_wave <=1'b1;

else

if(cnt_20ms ==T_20ms)

       key_wave <=key_rr;

else

       key_wave <=key_wave;

end

//--------------------------------------------------------------------------------------

// 對消抖之后的按鍵信號進行邊沿檢測

//---------------------------------------------------------------------------------------------

initialkey_wave_r =1'b1;

always@(posedgeclk)key_wave_r <=key_wave;

assignflag_neg =(key_wave_r ==1'b1&&key_wave ==1'b0)?1'b1:1'b0;

assignflag_pos =(key_wave_r ==1'b0&&key_wave ==1'b1)?1'b1:1'b0;

//--------------------------------------------------------------------------------------------


responder_ctrl模塊的設(shè)計思想:首先根據(jù)主持人復(fù)位、起始脈沖和四組搶答脈沖,確定運行的模式。

reg               [1:0]         state; // 00: 空閑狀態(tài)  01:搶答狀態(tài) 10:搶答成功狀態(tài) // 根據(jù)按鍵進行狀態(tài)切換  always @ (posedge clk) begin if (rst_n == 1'b0) state <= 2'd0; else if (flag_reset == 1'b1) state <= 2'd0; else if (state == 2'd0 && flag_start == 1'b1) state <= 2'd1; else if (state == 2'd1 && flag_1234 == 1'b1) state <= 2'd2; else state <= state; end 


根據(jù)運行的模式,以及顯示的規(guī)則。


// 根據(jù)狀態(tài)進行對應(yīng)的顯示 initial show_data[23:20] = 4'ha; always @ (posedge clk) begin if (rst_n == 1'b0)  show_data[23:20] <= 4'ha; else if (state == 2'd0) show_data[23:20] <= 4'ha; else if (state == 2'd1) show_data[23:20] <= 4'hc; else show_data[23:20] <= 4'hf; end


根據(jù)狀態(tài)和外部按鍵,記錄搶到的組號 ;

在空閑狀態(tài),顯示組號為0;在搶答狀態(tài),那個脈沖有效,顯示對應(yīng)的組號;在搶答成功狀態(tài),保持搶答成功的組號即可。


 always @ (posedge clk) begin if (rst_n == 1'b0) show_data[19:16] <= 4'd0; else if (state == 2'd0) show_data[19:16] <= 4'd0; else if (state == 2'd1) begin if (flag_1 == 1'b1) show_data[19:16] <= 4'd1; if (flag_2 == 1'b1) show_data[19:16] <= 4'd2; if (flag_3 == 1'b1) show_data[19:16] <= 4'd3; if (flag_4 == 1'b1) show_data[19:16] <= 4'd4; end else  show_data[19:16] <= show_data[19:16]; end


在空閑狀態(tài)中,10ms計時器清零,10ms的記錄次數(shù)也清零;在搶答狀態(tài)中,循環(huán)計時10ms,并且記錄10ms的次數(shù);在搶答成功狀態(tài),保持記錄10ms的次數(shù)。


// 在搶答狀態(tài)中,循環(huán)記錄10ms  always @ (posedge clk) begin if (rst_n == 1'b0) cnt_10ms <= 19'd0; else if (state == 2'd1 && cnt_10ms < T_10ms - 1'b1) cnt_10ms <= cnt_10ms + 1'b1; else  cnt_10ms <= 19'd0; end // 在搶答狀態(tài)中,記錄經(jīng)過了多少個10ms  always @ (posedge clk) begin if (rst_n == 1'b0) counter <= 32'd0; else if (state == 2'd0) counter <= 32'd0; else if (cnt_10ms == T_10ms - 1'b1) if (counter < 32'd9999) counter <= counter + 1'b1; else counter <= counter; else counter <= counter; end


將記錄的10ms的次數(shù),轉(zhuǎn)變?yōu)锽CD碼,輸出給數(shù)碼管的驅(qū)動模塊。


 // 將記錄10ms的個數(shù)轉(zhuǎn)換為BCD碼輸出  always @ (posedge clk) begin if (rst_n == 1'b0) show_data[15:0] <= 16'd0; else show_data[3:0] <= counter%10; show_data[7:4] <= counter/10 % 10; show_data[11:8] <= counter/100 % 10; show_data[15:12] <= counter/1000; end


每次主持人按下?lián)尨鸢粹o(在空閑狀態(tài))或者其他四人搶答成功(在搶答狀態(tài))時,產(chǎn)生一個蜂鳴器“?!币宦暤拿}沖。


assign flag_beep = ((state == 2'd0 && flag_start == 1'b1) || (state == 2'd1 && flag_1234 == 1'b1)) ? 1'b1 : 1'b0;


beep_ctrl模塊的設(shè)計原理為:蜂鳴器為無源蜂鳴器,需要給一定頻率的方波才可以出聲音。


// 設(shè)計原理:外部輸入脈沖,蜂鳴器出聲音200ms(正好是“?!币宦暎?

// 蜂鳴器出聲音準(zhǔn)備采用500hz的方波來驅(qū)動無源蜂鳴器。


首先設(shè)計一個脈沖有效后,記錄200ms的時間。


// 脈沖拉高后,記錄200ms  always @ (posedge clk) begin if (rst_n == 1'b0) cnt_200ms <= 24'd0; else if (flag_beep == 1'b1 && cnt_200ms == 0) cnt_200ms <= cnt_200ms + 1'b1; else if (cnt_200ms > 24'd0 && cnt_200ms < T_200ms - 1'b1) cnt_200ms <= cnt_200ms + 1'b1; else cnt_200ms <= 24'd0; end


在200ms期間,驅(qū)動蜂鳴器產(chǎn)生500hz的方波。

// 記錄1ms  always @ (posedge clk) begin if (rst_n == 1'b0) cnt_1ms <= 16'd0; else if (cnt_1ms < T_1ms - 1'b1) cnt_1ms <= cnt_1ms + 1'b1; else cnt_1ms <= 16'd0; end // 在200ms期間,每到1ms,beep進行取反  always @ (posedge clk) begin if (rst_n == 1'b0) beep <= 1'b0; else if (cnt_200ms > 24'd0 && cnt_1ms == T_1ms - 1'b1) beep <= ~beep; else beep <= beep; end

以上即為beep_ctrl模塊的設(shè)計思想;


七段數(shù)碼管為普通六位一體的共陽極數(shù)碼,采用動態(tài)驅(qū)動的方式,在此不再贅述。


下板后,我們也可以使用按鍵進行主持人復(fù)位、主持人搶答開始、四組搶答,觀測運行情況。
空閑狀態(tài)如下:


搶答狀態(tài)中,百分秒開始運行。



當(dāng)有搶答按鍵按下后,進入搶答成功狀態(tài),鎖定組號和搶答運行的時間。




主持人再次按下復(fù)位按鍵,回到空閑狀態(tài),就可以重復(fù)以上過程。


下板后,演示視頻(鏈接)如下:
https://www.bilibili.com/video/BV1vnYFeNEfK/?vd_source=b5405faeab8632f02533bcbfc5e52e55
     本設(shè)計所有內(nèi)容(設(shè)計代碼、設(shè)計工程)鏈接為:

鏈接:https://pan.baidu.com/s/1PAv-4N10u7K3EZQLdayxlA
提取碼:m3xw

END


本站聲明: 本文章由作者或相關(guān)機構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內(nèi)容真實性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時聯(lián)系本站刪除。
關(guān)閉