3路抢答器(键盘+数码管+LED灯+蜂鸣器)
差不多三天的时间都在弄这个抢答器,总算今天把它弄好了,这FPGA中还是得学会建模,学划分模块,对于这一块感觉自己还差那么点,不能很好地考虑好大局,然后细化到每一个模块,因为一个好的顶层模块,可以让子模块的程序更加简洁,否则子模块看起来很复杂,程序写起来也很费劲。好吧,下面来看程序。
//程序实现的功能:三路抢答器,当刚上电时,数码管开始倒计时40s;蜂鸣器响一下,四个LED灯闪烁一段时间; //期间如果有键盘按下,蜂鸣器响一下,四个LED灯闪烁一段时间,而数码管显示相应的按键值; //如果40S计时到后,没按键按下,蜂鸣器响一下,四个LED灯闪烁一段时间,数码管又从新开始计时; module qiang_da_qi //顶层模块; ( sysclk, rst_n, key, buzzer, led_out, smg_sel, smg_data ); input sysclk; //系统时钟50MHZ; input rst_n; //复位信号,低电平有效; input[2:0] key; //3个键盘 output buzzer; //蜂鸣器 output[3:0] led_out; //LED灯 output[1:0] smg_sel; //数码管片选; output[6:0] smg_data; //数码管段选; parameter div_clk_num1=32\'h17_D783F; //1s分频系数; parameter div_clk_num2=32\'hEE6_B27F; //10s分频系数; reg [2:0] key_reg; // 键盘检测; always @(posedge sysclk or negedge rst_n) begin if(!rst_n) key_reg<=3\'b111; else if(key!=3\'b111) key_reg<=key; else if(key_reg!=3\'b111) key_reg<=key_reg; else key_reg<=key_reg; end reg [3:0] key_num; always @ (*) begin case(key_reg) 3\'b110 : key_num=4\'h1; 3\'b101 : key_num=4\'h2; 3\'b011 : key_num=4\'h3; default: key_num=4\'h0; endcase end //--------------------------------------------------// reg lock; wire [3:0] sec_h; wire [3:0] sec_l; always @(posedge sysclk or negedge rst_n) begin if(!rst_n) lock<=1\'h0; else if((key_reg==3\'h7)&&(!sec_h)&&(!sec_l)) //当没有键盘按下且两个数码管显示都为0时; lock<=1\'h1; else lock<=lock; end reg [3:0] smg_l; always @(posedge sysclk or negedge rst_n) begin if(!rst_n) smg_l<=4\'h0; else if(key_reg!=3\'h7) smg_l<=key_num; else smg_l<=sec_l; end reg [3:0] smg_h; always @(posedge sysclk or negedge rst_n) begin if(!rst_n) smg_h<=4\'h0; else if(key_reg!=3\'h7) smg_h<=4\'h0; else smg_h<=sec_h; end //---------------------------------------------------------// 蜂鸣器和LED灯控制; reg [31:0] lig_buz_time; reg lig_buz_en; always @(posedge sysclk or negedge rst_n) begin if(!rst_n) lig_buz_time<=32\'h0; else if(lig_buz_time==32\'h17_D7840) lig_buz_time<=32\'h0; else if(lig_buz_en) lig_buz_time<=lig_buz_time+32\'h1; else lig_buz_time<=lig_buz_time; end always @(posedge sysclk or negedge rst_n) begin if(!rst_n) lig_buz_en<=1\'h1; else if(lig_buz_time==32\'h17_D7840) //lig_buz_en维持高电平的时间; lig_buz_en<=1\'h0; else if((!rst_n)||(lock)||((key_reg==3\'h7)&&(key!=3\'h7))) lig_buz_en<=1\'h1; else lig_buz_en<=lig_buz_en; end //-----------------------------------------------------//蜂鸣器模块; fmq fmq ( .sysclk(sysclk), .rst_n(rst_n), .buzzer_en(lig_buz_en), .buzzer(buzzer) ); //----------------------------------------------------// LED灯模块; led led ( .sysclk(sysclk), .rst_n(rst_n), .light_en(lig_buz_en), .led_out(led_out) ); //---------------------------------------------------//1s 计数模块; count counter_1s ( .sysclk(sysclk), .rst_n(rst_n), .cnt_max_num(4\'h9), .div_clk_num(div_clk_num1), .data_out(sec_l) ); count counter_10s //10s 计数模块; ( .sysclk(sysclk), .rst_n(rst_n), .cnt_max_num(4\'h3), .div_clk_num(div_clk_num2), .data_out(sec_h) ); smg smg ( .sysclk(sysclk), .rst_n(rst_n), .data_0(smg_l), .data_1(smg_h), .smg_sel(smg_sel), .smg_data(smg_data) ); endmodule
//计数模块; module count ( sysclk, rst_n, cnt_max_num, div_clk_num, data_out ); input sysclk; input rst_n; input[3:0] cnt_max_num; input[31:0] div_clk_num; output[3:0] data_out; wire sysclk; wire rst_n; wire[3:0] cnt_max_num; wire[31:0] div_clk_num; wire[3:0] data_out; //-------------------------------------------------------// reg [31:0] num; always @ (posedge sysclk or negedge rst_n) begin if(!rst_n) num<=32\'h0; else if(num==div_clk_num) num<=32\'h0; else num<=num+32\'h1; end //----------------------------------------------------------------// reg clk_div; reg clk_div_n; always @(posedge sysclk or negedge rst_n) begin if(!rst_n) clk_div<=1\'h0; else clk_div<=clk_div_n; end always @ (*) begin if(num==div_clk_num) clk_div_n<=~clk_div; else clk_div_n<=clk_div; end //----------------------------------------------------------------// reg[3:0] data_out_r; always @( posedge sysclk or negedge rst_n) begin if(!rst_n) data_out_r<=cnt_max_num; else if((data_out_r==4\'h0)&&(clk_div)&&(!clk_div_n)) data_out_r<=cnt_max_num ; else if((clk_div)&&(!clk_div_n)) data_out_r<=data_out_r-4\'h1; else data_out_r<= data_out_r; end assign data_out=data_out_r; endmodule
//蜂鸣器模块; module fmq ( sysclk, rst_n, buzzer_en, buzzer ); input sysclk; //50MHZ; input rst_n; input buzzer_en; output buzzer; //500HZ; wire sysclk; wire rst_n; wire buzzer_en; reg buzzer; reg [23:0] div_cnt; always @ (posedge sysclk or negedge rst_n) begin if(!rst_n) div_cnt<=24\'h0; else if(div_cnt==24\'hC350) div_cnt<=24\'h0; else div_cnt<=div_cnt+24\'h1; end always @ (posedge sysclk or negedge rst_n) begin if(!rst_n) buzzer<=1\'h0; else if((buzzer_en)&&(div_cnt==24\'hC350)) buzzer<=~buzzer; else buzzer<=buzzer; end endmodule
//LED灯模块; module led ( sysclk, rst_n, light_en, led_out ); input sysclk; input rst_n; input light_en; output[3:0] led_out; wire sysclk; wire rst_n; wire light_en; wire[3:0] led_out; //----------------------------------------------------// reg [23:0] led_cnt; always @ (posedge sysclk or negedge rst_n) begin if(!rst_n) led_cnt<=24\'h0; else if(led_cnt==24\'h33_12D0) led_cnt<=24\'h0; else led_cnt<=led_cnt+24\'h1; end reg [3:0] led_out_r; always @ (posedge sysclk or negedge rst_n) begin if(!rst_n) led_out_r<=4\'b1111; else if((light_en)&&(led_cnt==24\'h33_12D0)) led_out_r<=~led_out_r; else if(light_en) led_out_r<=led_out_r; else led_out_r<=4\'b1111; end assign led_out=led_out_r; endmodule
//数码管模块; module smg ( sysclk, rst_n, data_0, data_1, smg_sel, smg_data ); input sysclk; input rst_n; input[3:0] data_0; input[3:0] data_1; output[1:0] smg_sel; output[6:0] smg_data; wire sysclk; wire rst_n; wire[3:0] data_0; wire[3:0] data_1; reg[1:0] smg_sel; reg[6:0] smg_data; //-----------------------------------------------------------// reg[23:0] cnt; always @ (posedge sysclk or negedge rst_n) begin if(!rst_n) cnt<=24\'h0; else if(cnt==24\'h3_D090) cnt<= 24\'h0; else cnt<=cnt+24\'h1; end //------------------------------------------------------------// reg smg_sel_num; //数码管片选寄存器; always @(posedge sysclk or negedge rst_n) begin if(!rst_n) smg_sel_num<=1\'h0; else if(cnt==24\'h3_D090) smg_sel_num<=smg_sel_num+1\'h1; else smg_sel_num<=smg_sel_num; end always @(*) begin case(smg_sel_num) 1\'h0 : smg_sel=2\'b01; 1\'h1 : smg_sel=2\'b10; default: smg_sel=2\'b00; endcase end //-------------------------------------------------------------// reg[3:0] smg_data_num; //数码管段选寄存器; always @ (*) begin case(smg_sel_num) 1\'h0 : smg_data_num=data_0; 1\'h1 : smg_data_num=data_1; default: smg_data_num=4\'h0; endcase end always @ (*) begin case(smg_data_num) 4\'h0: smg_data[6:0]=7\'b100_0000; 4\'h1: smg_data[6:0]=7\'b111_1001; 4\'h2: smg_data[6:0]=7\'b010_0100; 4\'h3: smg_data[6:0]=7\'b011_0000; 4\'h4: smg_data[6:0]=7\'b001_1001; 4\'h5: smg_data[6:0]=7\'b001_0010; 4\'h6: smg_data[6:0]=7\'b000_0010; 4\'h7: smg_data[6:0]=7\'b111_1000; 4\'h8: smg_data[6:0]=7\'b000_0000; 4\'h9: smg_data[6:0]=7\'b001_0000; default:smg_data[6:0]=7\'b111_1111; endcase end endmodule