【Verilog】基于FPGA的闹钟系统设计(功能完整、附代码)

基于FPGA的闹钟系统设计


为了读者能从大的框架上理解整个设计的思路,博主将所有的子文件整合到一个.v文件中,便于读者理解和使用。

阿汪先生用的FPGA板子型号为:xc7a35tcsg324-1 ;

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2019/03/22 21:09:12
// Design Name: 
// Module Name: alarm_improve
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
/////////////////////////////////////////////////////////////////////////////////
module alarm_improve(clk,rst_n,key_h,key_l,wx,dx,fm,q0,q1,q2,q3);
//alarmq更改闹铃时间键
//tmq更改现实时间键
input  clk;
input  rst_n;//复位键
input  key_l;//列输入
output key_h;//行输出
output wx;//位选(片选)高电平有效
output dx;//段选,共阴极,高电平有效
output fm;//蜂鸣器
reg[6:0]shu3;//数码管数据
reg[6:0]shu2;
reg[6:0]shu1;
reg[6:0]shu0;

//存储人为设置时间,放映在数码管上
reg [3:0]tmrst0;
reg [3:0]tmrst1;
reg [3:0]tmrst2;
reg [3:0]tmrst3;


reg flag1;//标志按键按下后无按键按下五秒了
reg [3:0]count1;//用来计时,在停止输入时间5s后,还没有按下确定键,则恢复原来计数
//结束

 //设计闹铃功能处
 reg [3:0]cuna3;//存储闹铃时间
 reg [3:0]cuna2;
 reg [3:0]cuna1;
 reg [3:0]cuna0;
//结束

//阿汪先生的博客
//消抖加扫描键盘

reg [8:0]stata;//状态
wire [3:0]key_l;//列输入
reg [3:0]key_h;//行输出,改变其,以此来进行扫描列
reg [3:0]c_key_l;//存下列输出,可以知道哪列按下的
reg [3:0]c_key_h;//存下行输出,可以知道哪列按下的
reg [7:0]c_key_hl;//存行列值
reg flagkey;//标志有按键按下,为了后续当数码管左移使能信号
reg en_xd;//消抖计时的使能信号,进入消抖状态开始计时
reg [23:0]countxd;//20ms计时
reg count_20;//为1时代表达到了20ms
parameter kongbai=9'b0_0000_0001,
           xiaodou=9'b0_0000_0010,
           saomiao0=9'b0_0000_0100,
           saomiao1=9'b0_0000_1000,
           saomiao2=9'b0_0001_0000,
           saomiao3=9'b0_0010_0000,
           zhi=9'b0_0100_0000,//确定行列
           sfd=9'b0_1000_0000,//释放等待
           sfxd=9'b1_0000_0000,//释放消抖
           huanchong0=9'b11,//缓冲状态
           huanchong1=9'b111,
           huanchong2=9'b1111,
           huanchong3=9'b11111,
           huanchong4=9'b111111;

reg [9:0]count_sm0;//用于中途缓冲
reg [9:0]count_sm1;
reg [9:0]count_sm2;
reg [9:0]count_sm3;
reg [9:0]count_sf;//释放缓冲
reg a0;//用于测试第一行是否被检测到
reg a1;
reg a2;
reg a3;
output reg q0;
output reg q1;
output reg q2;
output reg q3;
always @* begin
q0<=a0;
q1<=a1;
q2<=a2;
q3<=a3;
end


always@(posedge clk,negedge rst_n)begin
     if(!rst_n)begin
            stata<=kongbai;
            key_h<=4'b0000;
            c_key_h<=4'b0000;
            c_key_hl<=8'b0000_1111;
            en_xd<=1'b0;
            flagkey<=1'b0;
            count_sm0<=0;
            count_sm1<=0;
            count_sm2<=0;
            count_sm3<=0;
            a0<=0;
            a1<=0;
            a2<=0;
            a3<=0;
      end
      else begin
      case(stata)
       kongbai:begin
           key_h<=4'b0000;//空白状态下一直送0000,为了可以检测按键按下
           if(key_l!=4'b1111)begin//说明有按键按下
            c_key_l<=key_l;//存储列值
            stata<=xiaodou;
            en_xd<=1'b1;//进入消抖状态,计时开始,5ms
           end
           else begin
            stata<=kongbai;
            en_xd<=1'b0;
            end
         end
        xiaodou:begin
        if(count_20==1)begin
           stata<=huanchong0;
           key_h<=4'b1110;//由于是并行的,所以要提前給值再操作
           en_xd<=1'b0;
           end
        else if(key_l==4'b1111)begin
           stata<=kongbai;
           en_xd<=0;
           end
       else begin//既没有到5毫秒,也没有检测到抖动,维持原状态
          stata<=xiaodou;
         end
        end
        huanchong0:begin
           if(count_sm0<=100)begin
               count_sm0=count_sm0+1;
               key_h<=4'b1110;
            end
           else begin
               count_sm0<=0;
               stata<=saomiao0;
               key_h<=4'b1110;
           end
        end    
        saomiao0:begin
               if(key_l!=4'b1111)begin
                 c_key_h<=4'b1110;//代表在第一行 
                 stata<=huanchong1;
                 a0<=~a0;
               end
          else begin
            stata<=huanchong1;
            c_key_h<=c_key_h;             
          end
       end
        huanchong1:begin
          if(count_sm1<=100)begin
              count_sm1=count_sm1+1;
              key_h<=4'b1101;
           end
          else begin
              count_sm1<=0;
              stata<=saomiao1;
              key_h<=4'b1101;
          end
       end              
       saomiao1:begin      
           if(key_l!=4'b1111)begin
              c_key_h<=4'b1101;
              stata<=huanchong2;              
              a1<=~a1;                 
              end 
          else begin
           stata<=huanchong2;
           c_key_h<=c_key_h;                   
          end          
       end 
        huanchong2:begin
          if(count_sm2<=100)begin
              count_sm2=count_sm2+1;
              key_h<=4'b1011;
           end
          else begin
              count_sm2<=0;
              stata<=saomiao2;
              key_h<=4'b1011;
          end
       end        
       saomiao2:begin        
             if(key_l!=4'b1111)begin
                c_key_h<=4'b1011;
                stata<=huanchong3;            
                a2<=~a2;                 
                end
         else begin
          stata<=huanchong3;
          c_key_h<=c_key_h;                  
         end                                    
       end 
       
        huanchong3:begin
          if(count_sm3<=100)begin
              count_sm3=count_sm3+1;
              key_h<=4'b0111;
           end
          else begin
              count_sm3<=0;
              stata<=saomiao3;
              key_h<=4'b0111;
          end
       end              
       saomiao3:begin       
               if(key_l!=4'b1111)begin
                  c_key_h<=4'b0111;
                  stata<=zhi;       
                  a3<=~a3;                   
                  end
         else begin
            stata<=zhi;
            c_key_h<=c_key_h;                  
           end                              
         end    
        zhi:begin//确定行列值
            stata<=huanchong4;            
            c_key_hl<={c_key_h,c_key_l};
            flagkey<=1'b1;//表明有按键按下,为了后续数码管左移;让其保存一个时钟周期。
          end
        huanchong4:begin
           flagkey<=1'b0;//一个时钟到了
           if(count_sf<100) begin
              count_sf<=count_sf+1;
              key_h<=4'b0000;
            end
           else begin
              stata<=sfd;
              key_h<=4'b0000;
           end       
        end
        sfd:begin//等待释放
            if(key_l==4'b1111)begin
                stata<=sfxd;//进入释放消抖状态
                en_xd<=1'b1;//开始5ms计时
                end
            else begin
               stata<=sfd; //继续等待
             end   //阿汪先生的博客
         end    
        sfxd:begin
            if(count_20==1)begin
               stata<=kongbai;//释放结束,进入空白状态
               en_xd<=1'b0;//清零
               end
            else if(key_l!=4'b1111)begin
               stata<=sfd;
               en_xd<=0;
               end
            else begin
               stata<=sfxd;
             end
            end 
       default:begin
            stata<=kongbai;
         end           
     endcase   
   end  
end

//行列值译码
reg [3:0]key_board;
always@(*)begin
    case(c_key_hl)
         8'b1110_1110:
               key_board=4'h1;//扫描结果得出:第一行第一列,表示按下的为1;
         8'b1110_1101:
               key_board=4'h2;
         8'b1110_1011:
               key_board=4'h3;
         8'b1110_0111:
               key_board=4'ha;
         8'b1101_1110:
               key_board=4'h4;
         8'b1101_1101:
               key_board=4'h5;
         8'b1101_1011:
               key_board=4'h6;
         8'b1101_0111:
               key_board=4'hb;
         8'b1011_1110:
               key_board=4'h7;
         8'b1011_1101:
               key_board=4'h8;
         8'b1011_1011:
               key_board=4'h9;
         8'b1011_0111:
               key_board=4'hc;
         8'b0111_1110:
               key_board=4'he;//当tmq
         8'b0111_1101:
               key_board=4'h0;
         8'b0111_1011:
               key_board=4'hf;//当alarmq
         8'b0111_0111:
               key_board=4'hd;
        default:
               key_board=key_board;
    endcase 
end
//阿汪先生的博客
//消抖计时,5ms
parameter N_xd=24'd5_000_00;//fz.10
always@(posedge clk,negedge rst_n)begin
    if(!rst_n)begin
        countxd<=24'b0;
        count_20<=1'b0;
    end
    else if(en_xd)begin
         if(countxd

在这里,感谢一下老葛同志在编程过程中提供的帮助。

你可能感兴趣的:(FPGA)