设计要求: 根据所学知识和试验板的资源,使用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, 下载次数: 44)
|