搜索
bottom↓
回复: 9

请教关于FPGA矩阵键盘的问题

[复制链接]

出0入0汤圆

发表于 2010-10-18 21:17:15 | 显示全部楼层 |阅读模式
新手学FPGA  借鉴网上代码,编写了矩阵键盘控制小灯的代码,叫了特权的按键消抖以后 ,不好使了 (不加消抖好使),不知道什么原因,个人能力有限找不出来,在此向各位请教,请帮忙答疑解惑,谢谢了!!!

// 模块功能:用矩阵键盘控制小灯亮灭
module key16(input[4:1] row,                  //四行
                        input clk,reset,                 //时钟,复位
                        output reg[4:1] col,             //四列
                        output reg[8:1] led);            //八路灯
       
reg[4:1] key_n;
always@(posedge clk,negedge reset)
                begin
                        if(!reset) key_n<=4'hf;                //异步复位
                        else key_n<=row;                     //每次时钟上升沿到来时,记录一次key的值
                end       
               
reg[4:1] key_n_r;
always@(posedge clk,negedge reset)
         begin
                 if(!reset) key_n_r<=4'hf;                //异步复位
                 else key_n_r<=key_n;                   //时钟上升沿到来的时候,记录一次kye_n的值
         end
               
wire[4:1] key_an=key_n_r&(~key_n);         //当有键按下的瞬间即key由1变0瞬间,key_an变高


//--------计数寄存器---------------                                                 
reg[24:1] cnt;                           
always@(posedge clk,negedge reset)  
begin                                                            
if(!reset) cnt<=24'd0;
else if(key_an) cnt<=24'd0;
else cnt<=cnt+1'b1;               
end                       
                               
//-------------行按键----------
reg[4:1] row_n;
always@(posedge clk,negedge reset)
begin
if(!reset)         row_n <= 4'b1111;
else if(cnt == 24'hfff_fff) row_n <= row;
end

reg[4:1] row_n_r;
always@(posedge clk, negedge reset)
begin
if(!reset) row_n_r<=4'b1111;
else row_n_r<=row_n;
end


wire[4:1] row_add = row_n_r&(~row_n);            //当20ms后确实有按键按下时,row_add变高



//-----------------------------------

reg[4:1] col_n;                   //存储键的键值状态
reg[3:1] state;                   //扫描状态
reg      key_flag;                      // 键的标志位

/*
//-------------列按键-------------
reg[4:1] col_n;
always@(posedge clk,negedge reset)
if(!reset)         col_n<=4'b1111;
else if(cnt==24'hfff_fff) col_n<=col;

reg[4:1] col_n_r;
always@(posedge clk, negedge reset)
if(!reset) col_n_r<=4'b1111;
else col_n_r<=col_n;

wire[4:1] col_add=col_n_r&(~col_n);            //当确实有按键按下时,col_add变高  
*/

//--------------------
always@(posedge clk,negedge reset)
begin
if(!reset) begin col<=4'b0000; state<=3'd0;end
else case(state)
         3'd0:
                                 begin  
                     col<=4'b0000;
                     key_flag<=1'b0;
                     if(row_add!=4'b0000)
         //    if(row!=4'b1111)
                     begin  state<=3'd1;col<=4'b1110;end
                     else begin state<=3'd0;  end
                     end
         3'd1:                   //扫描第一列
                                 begin  
                                 if(row_add!=4'b0000)
                         //        if(row!=4'b1111)
                           state<=3'd5;
                                 else  begin state<=3'd2;col<=4'b1101;end     
                                 end
         3'd2:                  //扫描第二列
                                 begin  
                                 if(row_add!=4'b0000)  
                 //                if(row!=4'b1111)
                           state<=3'd5;
                                 else  begin state<=3'd3;col<=4'b1011;end                 
                                 end
         3'd3:                   //扫描第三列
                                 begin  
                                 if(row_add!=4'b0000)
                 //                if(row!=4'b1111)
                                 state<=3'd5;
                                 else  begin state<=3'd4;col<=4'b0111;end               
                                 end
         3'd4:                   //扫描第四列
                                 begin  
                           if(row_add!=4'b0000)
                 //          if(row!=4'b1111)
                           state <= 3'd5;
                                 else  state <= 3'd0;   
                                 end
         3'd5:
                                 begin
                                   if(row_add!=4'b0000)
                 //                   if(row!=4'b1111)  
                                    begin
                                                 //                key_value <= {row_add,col};
                                                         col_n<=col;
                                                                 key_flag <= 1'b1;
                                                                 state <= 3'd5;
                                           end
                                   else state <= 3'd0;   
                           end
   default:   state <= 3'd0;
   endcase
  end


wire[8:1] key_value = {row_add,col_n};

always@(posedge clk,negedge reset)
if(!reset) led<=8'b1111_0000;
else if(key_flag)   
     case(key_value)
     8'b0001_1110:led<=8'b1111_1110;
     8'b0001_1101:led<=8'b1111_1101;
     8'b0001_1011:led<=8'b1111_1011;
     8'b0001_0111:led<=8'b1111_0111;
                     
     8'b0010_1110:led<=8'b1110_1111;
     8'b0010_1101:led<=8'b1101_1111;
     8'b0010_1011:led<=8'b1011_1111;
     8'b0010_0111:led<=8'b0111_1111;

     8'b0100_1110:led<=8'b1111_1100;
     8'b0100_1101:led<=8'b1111_0011;
     8'b0100_1011:led<=8'b1100_1111;
     8'b0100_0111:led<=8'b0011_1111;

     8'b1000_1110:led<=8'b1111_0000;
     8'b1000_1101:led<=8'b0000_1111;
     8'b1000_1011:led<=8'b0000_0000;
     8'b1000_0111:led<=8'b1111_1111;
/*
           8'b1110_1110:led<=8'b1111_1110;
     8'b1110_1101:led<=8'b1111_1101;
     8'b1110_1011:led<=8'b1111_1011;
     8'b1110_0111:led<=8'b1111_0111;
                     
     8'b1101_1110:led<=8'b1110_1111;
     8'b1101_1101:led<=8'b1101_1111;
     8'b1101_1011:led<=8'b1011_1111;
     8'b1101_0111:led<=8'b0111_1111;

     8'b1011_1110:led<=8'b1111_1100;
     8'b1011_1101:led<=8'b1111_0011;
     8'b1011_1011:led<=8'b1100_1111;
     8'b1011_0111:led<=8'b0011_1111;

     8'b0111_1110:led<=8'b1111_0000;
     8'b0111_1101:led<=8'b0000_1111;
     8'b0111_1011:led<=8'b0000_0000;
     8'b0111_0111:led<=8'b1111_1111;
      */
                 default:led<=led;
                 endcase
  else  led<=8'b00000000;
                                                   
endmodule

阿莫论坛20周年了!感谢大家的支持与爱护!!

知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)

出0入0汤圆

 楼主| 发表于 2010-10-19 20:57:33 | 显示全部楼层
自己用Modelsim 仿真找出问题了

出0入0汤圆

发表于 2010-10-19 21:59:40 | 显示全部楼层
恭喜

出0入0汤圆

 楼主| 发表于 2010-10-19 22:00:34 | 显示全部楼层
回复【2楼】yuphone  .COM 缺氧&#174;
-----------------------------------------------------------------------

呵呵

出0入0汤圆

发表于 2011-8-15 15:04:32 | 显示全部楼层
我按照楼主的思路改了一下,3*3的,但是实际运行还是不行,不知道楼主怎么修改的
// 模块功能:用矩阵键盘控制小灯亮灭
module key9(input[3:1] row,                  //四行
        input clk,reset,                 //时钟,复位
        output reg[3:1] col,             //四列
        output reg[4:1] led,
        output reg ss);            //八路灯

reg [16:1] cnt;
always @ (posedge clk)
    if (!reset) cnt <= 16'd0;
    else
       cnt <= cnt + 1'b1;


//-------------行按键----------
reg[3:1] row_n;
always@(posedge clk)
        if(!reset)  
            row_n <= 3'b111;
        else if(cnt == 16'hffff)
            row_n <= row;
       
reg[3:1] row_n_r;

always@(posedge clk)        
        if(!reset)
            row_n_r<=3'b111;
        else
            row_n_r<=row_n;



wire[3:1] row_add = row_n_r[3:1]&(~row_n[3:1]);            //当20ms后确实有按键按下时,row_add变高  

always @ (posedge clk)
if(!reset)
    ss<=1'b0;
else if(row_add==3'b100)
    ss<=~ss;

//-----------------------------------

reg[3:1] col_n;                   //存储键的键值状态
reg[3:1] state;                   //扫描状态




//--------------------
always@(posedge clk)
if(!reset)
        begin
             col<=3'b000;
            state<=3'd0;
        end
else
        case(state)
         3'd0:
          begin   
                  col<=3'b000;
                  if(row_add!=3'b000)  
                    begin  
                        state<=3'd1;
                        col<=3'b110;
                    end  
                  else
                        state<=3'd0;
          end
         3'd1:                   //扫描第一列   
          if(row_add==3'b001)   
                  state <= 3'd5;
          else  
                  begin
                          state<=3'd2;
                          col<=3'b101;
                  end      
         3'd2:                  //扫描第二列   
          if(row_add==3'b010)   
                  state <= 3'd5;
          else  
                  begin
                          state<=3'd3;
                      col<=3'b011;
                  end                  
         3'd3:                   //扫描第三列  
          if(row_add==3'b100)   
                  state <= 3'd5;
          else  
                  state<=3'd0;                  
         3'd5:
                 if(row_add!=3'b000)   
                          begin
                                  col_n<=col;
        //                          key_flag <= 1'b1;
                                  state <= 3'd5;
                          end
                 else
                          state <= 3'd0;   
           default:   state <= 3'd0;
        endcase


wire[6:1] key_value = {row_add,col_n};

always@(row_add,col_n,reset,key_value)
if(!reset)
         led<=4'b0_000;
else   
     case(key_value)
                 6'b001_110:led<=4'b1_110;   // key 0
                 6'b001_101:led<=4'b1_101;   // key 1
                 6'b001_011:led<=4'b1_011;   // key 2
                                                    
                 6'b010_110:led<=4'b0_111;   // key 3
                 6'b010_101:led<=4'b1_100;   // key 4
                 6'b010_011:led<=4'b1_001;   // key 5

                 6'b100_110:led<=4'b0_011;   // key 6
                 6'b100_101:led<=4'b0_110;   // key 7
                 6'b100_011:led<=4'b1_000;   // key 8

     default: led<=4'b0_000;
endcase
     
endmodule

出0入0汤圆

发表于 2013-5-7 09:45:50 | 显示全部楼层
molushali   你好   我现在在做6*5的键盘 包括组合按键部分   可以和你交流吗?
我的qq:150216708
不胜感谢

出0入0汤圆

发表于 2013-5-7 10:41:53 | 显示全部楼层
这个做的太麻烦了,还浪费逻辑宏单元,大可不必!用状态机最好了,还简单

出0入0汤圆

发表于 2013-5-9 09:31:35 | 显示全部楼层
minier 发表于 2013-5-7 10:41
这个做的太麻烦了,还浪费逻辑宏单元,大可不必!用状态机最好了,还简单 ...

8楼的  可以认识一下你吗?
我的矩阵按键的程序写好了;可是呢现在我的键盘还有个按键是独立出来的  完成组合按键(即联合按下的功能)
我写了个6*5矩阵按键+1*1矩阵按键  可是这两个模块组合起来,在数码管实验显示不同按键不同数字键值  有些问题了。
特请教下:::
我的
qq:150216708

出0入0汤圆

发表于 2013-9-24 19:04:05 | 显示全部楼层
学习一下
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-7-24 07:14

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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