找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2457|回复: 0
打印 上一主题 下一主题
收起左侧

基于FPGA的抢答器 包含源码、演示、文档

[复制链接]
跳转到指定楼层
楼主
设计要求:
据所学知识和试验板的资源,使用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)

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏2 分享淘帖 顶 踩
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表