差不多三天的时间都在弄这个抢答器,总算今天把它弄好了,这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