标题: 基于FPGA的抢答器 包含源码、演示、文档 [打印本页]
作者: cc12138 时间: 2020-1-2 21:03
标题: 基于FPGA的抢答器 包含源码、演示、文档
设计要求:
根据所学知识和试验板的资源,使用Verilog HDL语言设计一个四路抢答器。
抢答器可供四组抢答,且有鉴别第一信号和锁存功能,主持人按下复位键后开始抢答,并在数码管显示10秒的倒计时,当有人抢答时,数码管计时消失,对应选手的LED灯将亮起,且蜂鸣器发出响声,此时电路自锁,其他选手抢答无效。
如果10秒内无人抢答,相应的LED灯亮起,表示此轮抢答作废。
设计代码及说明:
qiangda模块:该模块具备鉴别第一信号和锁存的功能。精确的鉴别出第一信号之后将输入端封锁,使其他组的抢答无效。设置4个输入端num1,num2,num3,num4(4个独立按键),并设置pd8做主持人复位键rst。当rst=1,抢答开始,当rst=0时,抢答电路复位。
module qiangda(num1, num2, num3, num4, clk, rst_n, led1, led2, led3, led4,sec_h, beep);
input num1, num2, num3, num4, clk, rst_n, sec_h;
output led1, led2, led3, led4, beep;
reg startflag=1, beepflag=0;
reg led1, led2, led3, led4, beep;
always@(posedge clk)
begin
//-------------复位操作,当复位键置0时,led1-4都不亮,蜂鸣器不叫--------
if(rst_n==0)
begin
startflag<=1;
led1=0;
led2=0;
led3=0;
led4=0;
beep<=0;
end
//-------------抢答操作,共4种情况--------------------
if(startflag==1&&!(sec_h==0))
begin
if(num1==0)
begin
startflag<=0;
led1=1;
beepflag<=1;
end
else if(num2==0)
begin
startflag<=0;
led2=1;
beepflag<=1;
end
else if(num3==0)
begin
startflag<=0;
led3=1;
beepflag<=1;
end
else if(num4==0)
begin
startflag<=0;
led4=1;
beepflag<=1;
end
end
if(beepflag==1)
begin
beep<=1;
beepflag<=0;
end
end
Endmodule
time_counter模块:该模块实现了10秒倒计时的计数功能,通过1000ms进位1秒,倒数10秒后可通过主持人的复位键重新复位计时。
module time_counter( rst_n, clk, sec_h, sec_l, display_flag, led8);
parameter CLK_CYCLE = 20;
parameter T0 = 1000000;
parameter T0_VAL = T0/CLK_CYCLE;
input clk;
input rst_n;
output reg led8;
output reg[2:0] sec_h; //数码管的十位
output reg[3:0] sec_l; //数码管的个位
output display_flag; //数码管动态扫描标志位
//-----------------------------------1ms延时------
reg[15:0] cnt;
always@(posedge clk or negedge rst_n)
begin
if(rst_n == 1'b0)
cnt <= (0);
else if(cnt < T0_VAL)
cnt <= cnt + 1'b1;
else
cnt <= (0);
end
assign delay_1ms = (cnt == T0_VAL); //1ms延时完成标志位
assign display_flag = delay_1ms; //数码管动态扫描标志位
//------------------------------------1s延时------
reg[9:0] mse;
always@(posedge clk or negedge rst_n)
begin
if(rst_n == 1'b0)
mse <= (0);
else
begin
if(delay_1ms == 1'b1)
begin
if(mse < 10'd1000)
mse <= mse + 10'd1;
else
mse <= (0);
end
end
end
wire sec_l_flag = ((mse == 10'd999) && (delay_1ms == 1'b1));//1s延时完成标志位
//------------------------------------秒个位数计数------
always@(posedge clk or negedge rst_n) //时钟和复位
begin
if(rst_n == 1'b0) //复位后数码管低位等于0
sec_l <= 0;
else
begin
if(sec_l_flag ==1'b1) //1s延时完成标志位等于1
begin
if(sec_h!=3'd0 && sec_l==0) //高位不等于0并且低位等于0
sec_l<=9; //让低位等于9
else if(sec_l >4'd0) //低位大于0
sec_l <= sec_l - 4'd1; //低位进行减一操作
else
sec_l <= 0; //低位等于0
end
end
end
wire sec_h_flag = ((sec_l == 4'd0) && (sec_l_flag == 1'b1)); //sec_h_flag是秒个位数进位标志位
//------------------------------------秒十位数计数------
always@(posedge clk or negedge rst_n) //时钟和复位
begin
if(rst_n == 1'b0) //复位后,如果高位等于1,led8不亮
begin
sec_h <= 1;
led8=0;
end
else
begin
if(sec_h_flag == 1'b1) //如果秒个位数进位标志位等于1
begin
if(sec_h > 0 && sec_l==0) //高位大于0且低位等于0
sec_h <= sec_h - 3'd1; //高位减1
else
begin
sec_h <= 3'd0; //高位等于0
led8=1; //led8灯亮
end
end
end
end
endmodule
display模块:该模块包含了数码管的编码函数,数码管动态显示的计数器,数码管的编码输出,并将模块2的计数结果动态显示在数码管上。
module display(rst_n, clk, sec_h, sec_l, led1, led2, led3, led4, display_flag, seg, sel);
input rst_n;
input clk;
input led1, led2, led3, led4;
input[2:0] sec_h;
input[3:0] sec_l;
input[3:0] display_flag;
output reg[7:0] seg;
output reg[3:0] sel;
function [7:0] seg_data;
input[3:0] din;
input dp;
begin
case(din)
4'd0 : seg_data = {7'b1111110,dp};
4'd1 : seg_data = {7'b0110000,dp};
4'd2 : seg_data = {7'b1101101,dp};
4'd3 : seg_data = {7'b1111001,dp};
4'd4 : seg_data = {7'b0110011,dp};
4'd5 : seg_data = {7'b1011011,dp};
4'd6 : seg_data = {7'b1011111,dp};
4'd7 : seg_data = {7'b1110000,dp};
4'd8 : seg_data = {7'b1111111,dp};
4'd9 : seg_data = {7'b1111011,dp};
4'd10 : seg_data = {7'b0000000,dp};
endcase
end
endfunction
//-------------------------------------数码管动态显示的计数器
reg[1:0] cnt;
always @(posedge clk or negedge rst_n)
begin
if(rst_n == 1'b0)
cnt <= (0);
else if(display_flag == 1'b1)
cnt <= cnt + 1'b1;
else
cnt <= cnt;
end
//-------------------------------------编码输出
always @(posedge clk or negedge rst_n)
begin
if(rst_n == 1'b0)
begin
seg <=7'b0000000; //执行复位按键后,清0
sel <=4'b0000;
end
else
begin
case(cnt)
2'b00 :
begin
if(led1==1||led2==1||led3==1||led4==1)
begin
seg<=7'b0000000;
sel<=4'b0000;
end
else
seg <= seg_data(sec_l,1'b0);
sel <= 4'b1000;
end
2'b01 :
begin
if(led1==1||led2==1||led3==1||led4==1)
begin
seg<=7'b0000000;
sel<=4'b0000;
end
else
seg <= seg_data({1'b0,sec_h},1'b0);
sel <= 4'b0100;
end
endcase
end
end
endmodule
main模块:调用其他模块实现整体功能
module main(num1, num2, num3, num4, led1, led2, led3, led4, led8, rst_n, clk,Pd0, Pd1, seg, sel,beep);
//参数定义
parameter CLK_CYCLE = 20;
parameter T0 = 1000_000;
//端口定义
input rst_n;
input clk;
input Pd0;
input Pd1;
input num1,num2,num3,num4;
output led1,led2,led3,led4,led8;
output[7:0] seg;
output[3:0] sel;
output beep;
// 变量定义
wire[2:0] sec_h;
wire[3:0] sec_l;
wire display_flag;
//----------------模块例化--------------------
//例化qiangda模块
qiangda u_qiangda (
.rst_n ( rst_n ),
.clk ( clk ),
.led1 ( led1 ),
.led2 ( led2 ),
.led3 ( led3 ),
.led4 ( led4 ),
.sec_h ( sec_h ),
.num1 ( num1 ),
.num2 ( num2 ),
.num3 ( num3 ),
.num4 ( num4 ),
.beep ( beep ));
//例化time_counter模块
time_counter #(
.CLK_CYCLE ( CLK_CYCLE ),
.T0 ( T0 ))
u_time_counter (
.rst_n ( rst_n ),
.clk ( clk ),
.sec_h ( sec_h ),
.sec_l ( sec_l ),
.display_flag ( display_flag ),
.led8 ( led8 ));
//例化display模块
display u_display(
.rst_n ( rst_n ),
.clk ( clk ),
.sec_h ( sec_h ),
.sec_l ( sec_l ),
.display_flag ( display_flag ),
.seg ( seg ),
.led1 ( led1 ),
.led2 ( led2 ),
.led3 ( led3 ),
.led4 ( led4 ),
.sel ( sel ));
endmodule
硬件效果:
将设计好的代码下载到试验板里,实现了相应的功能,效果如图
(1)抢答开始,倒计时进行中
(2)抢答时间到仍然没有人抢答,裁判灯亮
(3)三号选手抢答成功,倒计时停止,对应的led灯亮
完整的Word格式文档51黑下载地址:
文档.doc
(613.27 KB, 下载次数: 45)
欢迎光临 (http://www.51hei.com/bbs/) |
Powered by Discuz! X3.1 |