开云-基于FPGA的多人抢答器设计(附源码工程)

基在FPGA的多人抢答器设计(附源码工程) 时候:2024-12-13 14:30:13 手机看文章

扫描二维码随时随地手机看文章

功能申明:

1. 抢答器为四人抢答器。

2. 操纵六位数码管进行显示抢答器相干信息。

3. 第一个数码管显示抢答器的状况,第二个数码管显示抢到的编号,没有抢答成功前显示数字0;第三至六显示抢答用的时候(以百分秒进行显示)。

4. 板卡默许余暇状况(第一个数码管显示字母A(余暇状况),第二个数码管显示数字0),当主持人按下抢答按钮后,进入抢答状况(第一个数码管显示字母C(抢答状况),第二个数码管显示0,第三至六数码管最先记实时候)

5. 在余暇状况时代,选手按下按键没有感化,当进入抢答状况后,选手谁先按下按键,第二个数码管显示对应的编号(1、2、3、4)。

6. 被选手抢答成功后,进入抢答成功状况(第一个数码管显示F),可是第二个数码管一向显示上一次抢答成功的编号,第三至六显示上一次抢答运行的时候。

7. 主持人按下复位按钮后,再次进入余暇状况,第二个数码显示0,时候断根。

8. 每次主持人按下抢答按钮或其他四人抢答成功时,蜂鸣器“叮”一声。

利用平台:本次设计利用Altera的平台设计(芯片:EP4CE10F17C8N)。

仿真平台:Modelsim。

作者QQ:746833924

申明:本篇设计中不触及到IP和原语,代码在其他平台仍然可以合用;当其他板卡电路分歧时,会致使分歧的现象呈现,若有需要点窜代码请联系作者;如需作者利用的板卡,请联系作者;

设计思惟以下:

module responder ( input wire clk, // 50MHz input wire rst_n, input wire key_reset, // 主持人复位按钮 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, //数码管的位选旌旗灯号 output wire [7:0] seg, //数码管的段选旌旗灯号 output wire beep //蜂鸣器驱动旌旗灯号); wire flag_reset; // 主持人复位脉冲 wire flag_start; // 主持人最先抢答脉冲 wire flag_1; //第一组抢答脉冲 wire flag_2; //第二组抢答脉冲 wire flag_3; //第三组抢答脉冲 wire flag_4; //第四组抢答脉冲 wire [23:0] show_data; // 显示数据 wireflag_beep; //蜂鸣器“叮”一声的脉冲

key_ctrl模块负责将外部的按键旌旗灯号进行消抖,而且发生对应边缘转变时的脉冲;responder_ctrl模块负责按照脉冲旌旗灯号和设计逻辑发生对应数字逻辑;seven_tube_drive(七段数码管驱动)模块负责将responder_ctrl模块发生的数字逻辑显示到数码管上;beep_ctrl模块负责按照一个脉冲驱动蜂鸣器“叮”一声。

key_ctrl模块设计思惟为:按键旌旗灯号是由外部机械式按键发生,每次按下或抬起时,会发生必然的发抖。假如直接对其进行边缘检测就会致使屡次触发。故而需要设计按键消抖,进而对消抖以后的波形进行边缘检测。消抖道理为:外部按键旌旗灯号产生改变后,假如可以或许延续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,认为按键不变,此时采样

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

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模块的设计思惟:起首按照主持人复位、肇端脉冲和四组抢答脉冲,肯定运行的模式。

reg [1:0] state; // 00: 余暇状况 01:抢答状况 10:抢答成功状况 // 按照按键进行状况切换 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 

按照运行的模式,和显示的法则。

// 按照状况进行对应的显示 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

按照状况和外部按键,记实抢到的组号 ;

在余暇状况,显示组号为0;在抢答状况,阿谁脉冲有用,显示对应的组号;在抢答成功状况,连结抢答成功的组号便可。

 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

在余暇状况中,10ms计时器清零,10ms的记实次数也清零;在抢答状况中,轮回计时10ms,而且记实10ms的次数;在抢答成功状况,连结记实10ms的次数。

// 在抢答状况中,轮回记实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 // 在抢答状况中,记实颠末了几多个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的次数,改变为BCD码,输出给数码管的驱动模块。

 // 将记实10ms的个数转换为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

每次主持人按下抢答按钮(在余暇状况)或其他四人抢答成功(在抢答状况)时,发生一个蜂鸣器“叮”一声的脉冲。

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

beep_ctrl模块的设计道理为:蜂鸣器为无源蜂鸣器,需要给必然频率的方波才可以作声音。

// 设计道理:外部输入脉冲,蜂鸣器作声音200ms(正好是“叮”一声)。

// 蜂鸣器作声音预备采取500hz的方波来驱动无源蜂鸣器。

起首设计一个脉冲有用后,记实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时代,驱动蜂鸣器发生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模块的设计思惟;

七段数码管为通俗六位一体的共阳极数码,采取动态驱动的体例,在此不再赘述。

下板后,我们也能够利用按键进行主持人复位、主持人抢答最先、四组抢答,不雅测运行环境。余暇状况以下:

抢答状况中,百分秒最先运行。

当有抢答按键按下后,进入抢答成功状况,锁定组号和抢答运行的时候。

主持人再次按下复位按键,回到余暇状况,便可以反复以上进程。

下板后,演示视频(链接)以下:https://www.bilibili.com/video/BV1vnYFeNEfK/?vd_source=b5405faeab8632f02533bcbfc5e52e55 本设计所有内容(设计代码、设计工程)链接为:

链接:https://pan.百度.com/s/1PAv-4N10u7K3EZQLdayxlA 提取码:m3xw

END

欲知详情,请下载word文档 下载文档

上一篇:开云-485差分信号不对称,到底加不加上下拉电阻?加多大? 下一篇:开云-从技术赋能到能力外溢,华为要让数智制造 一触即达