用FPGA实现多人抢答器

 测试题目“三人抢答器” 要求:

(1)答题开始后,由主持人按下“开始”键后进入抢答环节;

(2)每人一个抢答按钮,有人抢答成功后,其他人再抢答无效;

(3)当某人抢答成功时,抢答器系统发出半秒的低频音,并在数码管上显示该组别序号;

(4)每个人初始分数为 0,抢答成功得到一分,并在数码管上显示 3 人的得分;(每人分配 一个数码管用于显示分数,显示“0~9”)

(5)抢答成功后,10 秒倒计时,并在数码管上显示。倒计时为零,开始下一轮抢答;

(6)当主持人按下“复位”键后,数码管清零,准备开始新一轮抢答;

说明:

(1)2 个拨动开关:“复位”键和“开始”键;注意:“复位”键无效、“开始”键有效,开始抢答。

(2)3 个按键开关:3 个抢答人;

(3)6 个数码管分配:1 个用于显示抢答人序号,3 个用于显示 3 人得分,2 个用于 10 秒 倒计时;

文档要求: (1)良好的编码风格、恰当的注释; (2)系统划分:顶层文件,定义 I/O,高低电平有效;子文件,定义 I/O,高低电平有效。 利用图形展示; (3)功能说明:顶层文件和子文件的功能描述,内部变量定义和说明; (4)管脚分配图; (5)测试结果展示:图片和视频。

主模块:

module fsm_rsp(KEY,CLK,RSTn,Digitron_Out,DigitronCS_Out,Start,key_start,key_right,key_wrong,beep);

input key_start;				//主持人所持开始抢答键
input key_right,key_wrong;	//正确(或错误)回答键
input [2:0]KEY;				//各组所持抢答键
input CLK;						//时钟
input RSTn;						//总体复位键
input Start;					//开关(总)

output beep;
output [7:0]Digitron_Out;		//数码管显示
output [5:0]DigitronCS_Out;

parameter S0=1'b0,S1=1'b1;

wire beepon;
reg status;						//状态机现时状态S0/S1
reg next_state;				//状态机后一状态
wire answer;					//按回答键后取1,状态为0时清零
wire KEY_right;				//消抖回答键				
switch u1(key_right,CLK,KEY_right);		//按键消抖

wire [2:0]Q;	
latch_key u4(reset,KEY,Q,oe);				//锁存键值,oe防止在抢答开始前抢答

buzzer_m1 bee(CLK,beepon,beep);					//抢答后蜂鸣器响应
assign beepon = Q[0]|Q[1]|Q[2];

wire [11:0]Score;				//各小组分数
wire [3:0]Group;				//各小组组号

recorder u5(status,RSTn,Q,Score,Group,KEY_right,answer);		//记录得分和组号

numdisplay u6(CLK,countdown_num,Digitron_Out,DigitronCS_Out,Score,Group);//数码管显示

reg [3:0]countdown_num;			//倒计时数字(显示数码管)
wire [3:0]countdown_num0;		//三个计时器的倒计时数字
wire [3:0]countdown_num1;
wire [3:0]countdown_num2;

wire flag0;				//计时器进位信号
wire flag1;
wire flag2;

reg counter_clr0;		//计时器复位信号
reg counter_clr1;		//S0状态时计时器2,3复位,计时器1在按下key—start后开始计时(不按为复位状态)
reg counter_clr2;

wire startcounter0;
wire startcounter1;
wire startcounter2;

assign startcounter0 = (~status) & Start;			//开始条件
assign startcounter1 = status & Start;
assign startcounter2 = (~key_wrong|answer) & Start;

counter_ten u7(CLK,startcounter0,counter_clr0,countdown_num0,flag0); //准备抢答 倒计时
counter_ten u8(CLK,startcounter1,counter_clr1,countdown_num1,flag1); //答题倒计时
counter_ten u9(CLK,startcounter2,counter_clr2,countdown_num2,flag2);	 //答题后等待进入下一轮

always @ (posedge CLK or negedge RSTn)	//三段式
begin 
	if(!RSTn)begin
	status<=S0;
	end
	else status<=next_state;
end

always @ (status or Q or flag1 or flag2 or flag0)	//define state of fsm
begin
	case(status)
	S0:
	begin
		if(Q) next_state = S1;
		else next_state = S0;
	end
	S1:
	begin
		if(flag1|flag2) next_state= S0;
		else next_state = S1; 
	end
	default: next_state= S0;
	endcase
end

always @ (*)			//define output of fsm
begin
	case(status)
	S0:
	begin		
		 countdown_num<=countdown_num0;
		 counter_clr1<=1;
		 counter_clr2<=1;			 //将其余两个钟复位
		if(oe) counter_clr0<=0;
		else counter_clr0 <= 1;
	end
	S1:
	begin
		counter_clr0<=1;				//复位第一个钟
		counter_clr2<=0;
		if(!answer)						//按下正确的答题键
		begin
			countdown_num<=countdown_num1;
			counter_clr1<=0;
		end
		else
		begin
			countdown_num<=countdown_num2;
			counter_clr1<=1;
		end
	end
	default:
	begin 
		countdown_num<=4'b0;
	end
	endcase
end

assign reset = flag1|flag2|~RSTn;		//锁存器复位信号

reg oe;
always@(negedge key_start or negedge RSTn or posedge flag1 or posedge flag2 or posedge flag0)	//主持人抢答开始
begin	
if(!RSTn)
	oe<=0;
else
begin
	if(flag1|flag0|flag2)			//计时器进位信号到来时复位
	oe<=0;
	else 
	oe<=1;
end
end

endmodule
	

数码管显示模块:

module numdisplay(CLK, countdown, Digitron_Out, DigitronCS_Out,score,group);
	 input CLK;
	 input [3:0]countdown; 
	 input [11:0]score;
	 input [3:0]group;
	 output [7:0]Digitron_Out;
	 output [5:0]DigitronCS_Out;	 
  
	 reg [3:0]Result1;
	 reg [3:0]Result2;
	 reg [7:0]Count;
	 reg [3:0]SingleNum;
	 reg [7:0]W_Digitron_Out;
	 reg [5:0]W_DigitronCS_Out;
	 
	 parameter _0 = 8'b00111111, _1 = 8'b00000110, _2 = 8'b01011011,
			 	  _3 = 8'b01001111, _4 = 8'b01100110, _5 = 8'b01101101,
			 	  _6 = 8'b01111101, _7 = 8'b00000111, _8 = 8'b01111111,
				  _9 = 8'b01101111;
	 parameter Timex = 8'd200;			//divide frequency for select_signal(wei)
	 
	always @ ( posedge CLK )
	begin
			if( Count == Timex )			//this is also clock'count',its frequency is very fast 
				begin							//controls the transfrom of select_signal 
					Count <= 8'd0;
					case(W_DigitronCS_Out)
					6'b111110:W_DigitronCS_Out<=6'b111101;
					6'b111101:W_DigitronCS_Out<=6'b111011;
					6'b111011:W_DigitronCS_Out<=6'b110111;
					6'b110111:W_DigitronCS_Out<=6'b101111;
					6'b101111:W_DigitronCS_Out<=6'b011111;
					6'b011111:W_DigitronCS_Out<=6'b111110;
					default:W_DigitronCS_Out<=6'b111110;
					endcase
				end
			else
				Count <= Count + 1'b1;
	end
	
	 assign Digitron_Out = W_Digitron_Out;
	 assign DigitronCS_Out = W_DigitronCS_Out;	
	 
	always @ (*)
	begin
		if(countdown==4'd10)
		begin
			Result1<=4'd1;
			Result2<=4'b0;
		end
		else
		begin
			Result1<=4'd0;
			Result2<=countdown;
		end
	end
	 
	always@ (*)
	begin
			case(SingleNum)					
						4'd0:  W_Digitron_Out = _0;
						4'd1:  W_Digitron_Out = _1;
						4'd2:  W_Digitron_Out = _2;
						4'd3:  W_Digitron_Out = _3;
						4'd4:  W_Digitron_Out = _4;
						4'd5:  W_Digitron_Out = _5;
						4'd6:  W_Digitron_Out = _6;
						4'd7:  W_Digitron_Out = _7;
						4'd8:  W_Digitron_Out = _8;
						4'd9:  W_Digitron_Out = _9;
						default: W_Digitron_Out = _0;	
				endcase
	end
	always@ (*)
	begin
			case(W_DigitronCS_Out)		
						6'b101111: SingleNum = Result2;	//Display Result and record
						6'b011111: SingleNum = Result1;	
						6'b110111: SingleNum = score[11:8];
						6'b111011: SingleNum = score[7:4];
						6'b111101: SingleNum = score[3:0];
						6'b111110: SingleNum = group;
						default: SingleNum = 4'd0;
					endcase
	end
	
endmodule 

计分模块:

module recorder(status,RSTn,key_latched,score,group,key_right,answer);

input status;
input key_right;
input RSTn;
input [2:0]key_latched;

output reg answer;
output [11:0]score;   						//record the scores
output [3:0]group;

reg [3:0]score_1;
reg [3:0]score_2;
reg [3:0]score_3;
reg [3:0]group_number;

always @ (*)
begin
	case(key_latched)
	3'b001:group_number<=4'd1;
	3'b010:group_number<=4'd2;
	3'b100:group_number<=4'd3;
	default:group_number<=4'd0;
	endcase
end

always @ (posedge key_right or negedge RSTn)
begin
	if(!RSTn)
	begin
		score_1<=0;
		score_2<=0;
		score_3<=0;
	end
	else
	case(key_latched)
	3'b001:score_1<=score_1+4'd1;
	3'b010:score_2<=score_2+4'd1;
	3'b100:score_3<=score_3+4'd1;
	default:begin 
	score_1<=score_1;
	score_2<=score_2;
	score_3<=score_3;
	end
	endcase
end

always @ (posedge key_right or negedge RSTn or negedge status)		//答题键
begin
	if(!RSTn|~status)													//在加入key_wrong键时逻辑无法实现
		answer<=0;
	else
		answer<=1;
end



assign score = {score_1,score_2,score_3};
assign group = group_number;

endmodule

按键模块:

module switch(input key_in,
				  input CLK,
				  output reg key_out);			//delay to avoid keys' bounce
				  
wire clk_use;
reg [7:0]counter;

assign clk_use = counter[7];

always @ (posedge CLK)
	counter <= counter + 1'b1;

always @ (posedge clk_use)
	key_out <= key_in;

endmodule 

锁存按键模块:

module latch_key(input rst,
					  input [2:0]key,
					  output reg[2:0]q=3'b0,
					  input start);  		//latch for key(oe change with fsm)
wire le;
	
always @ (~key[0] or ~key[1] or ~key[2])
begin
	if(rst)
	begin
		q<=3'b0;
	end
	else
	begin
		if(start)
		begin
		if(le)
			q<={~key[2],~key[1],~key[0]};
		else
			q<=q;
		end
		else q<=3'b0;
	end
end

assign le = (!q);

endmodule
	

计数器基础计时模块:

module counter_ten(CLK,start_impulse,CLR,countdown_num,flag);

input CLR;
input start_impulse;
input CLK;
output [3:0]countdown_num;
output reg flag=0;

wire clk_1hz;
reg [3:0]counter_10=4'd10;

clk50mto1 clk1hz_ist(CLK,clk_1hz);

always @ (posedge clk_1hz or posedge CLR)
begin
if(CLR)
begin
counter_10<=4'd10;
flag<=0;
end
else
begin
	if(start_impulse)
	begin
		if(counter_10==0)
			flag<=1;
		else
			counter_10 <= counter_10 - 1'b1;
	end

	else counter_10 <= counter_10;
end
end

assign countdown_num = counter_10;

endmodule 

蜂鸣器模块(有误):

module buzzer_m1(
	 input  CLK,
    input  on,
    output reg beep
    );
	 
	reg en=1;
	wire clk_1hz;
	reg [19:0] cnt; //20 bit get the maximum number of 1048575;
	reg [3:0]	clk_1hz_cnt;
	//计数模块,计数达到100 000次,计数器清零
	always @ (posedge CLK or negedge on)
	begin
		if(!on)
		begin
			cnt <= 20'b0;
		end
		else 
		begin
		if(!en)
			cnt <= 20'b0;
		else if(cnt < 20'd500000)
			cnt <= cnt + 1'b1;
		else
			cnt <= 20'b0;
		end
	end
 
 
	always @ (posedge CLK or negedge on)
	begin
		if(!on)
			beep <= 1'b0;
		else if(cnt < 20'd250000)
			beep <= 1'b1;
		else 
			beep <= 1'b0;
	
	end
	
clk50mto1 beep2s(CLK,clk_1hz);
	
always @ (posedge clk_1hz or negedge on)
begin
	if(!on)
		clk_1hz_cnt <= 4'd1;
	else if(clk_1hz_cnt > 0)
		clk_1hz_cnt <= clk_1hz_cnt -4'd1;
	else
	begin
		clk_1hz_cnt <= 4'd1;
		en<=0;
	end
end

endmodule

用FPGA实现多人抢答器_第1张图片

 

你可能感兴趣的:(fpga开发)