差不多三天的时间都在弄这个抢答器,总算今天把它弄好了,这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; endalways @ (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; endendmodule
//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; endreg [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; endassign 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 endalways @ (*) 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