原创 【博客大赛】【原创】状态机输入与输出相关带来的时序问题[前篇]

2012-5-23 19:21 1317 16 18 分类: FPGA/CPLD

昨天帮同学修改一个不知道从哪里Ctrl+C、Ctrl+V来的矩阵键盘检测代码,没有分频、没有消抖,直接拿来用就别指望了,呵呵…在这里拿出来主要是想说明一个隐藏的时序问题。废话不多说,直接上代码,注意看。

/*************************************************/

       //row为输入

       //col 为输出

       //按键按下为低电平

      此处省略xxx字……………….

       …………………………………

      parameter NO_KEY_PRESSED=6'b000_001;//没有键按下

       parameter SCAN_COL0     =6'b000_010;//扫描第 0 列

       parameter SCAN_COL1     =6'b000_100;//扫描第 1 列

       parameter SCAN_COL2     =6'b001_000;//扫描第 2 列

       parameter SCAN_COL3     =6'b010_000;//扫描第 3 列

       parameter KEY_PRESSED   =6'b100_000;//有键按下

 

       reg [5:0]current_state,next_state;  //现态和次态

      /*********************************/

       //状态转移

       always @(posedge key_clk or negedge rst_n)

              if(!rst_n)

                     current_state<=NO_KEY_PRESSED;

              else

                     current_state<=next_state;

        /*************************************************/

       //状态逻辑           

       always @ (current_state)     //根据条件转移状态

              case (current_state)

                     NO_KEY_PRESSED:                           

                            if(row!=4'hf)         //有键按下

                                   next_state=SCAN_COL0;    

                            else                //没有键按下

                                   next_state=NO_KEY_PRESSED;       

                     SCAN_COL0:           //扫描第 0 列

                            if(row!=4'hf)

                                   next_state=KEY_PRESSED;

                            else

                                   next_state=SCAN_COL1;            

                     SCAN_COL1:          //扫描第 1 列

                            if(row!=4'hf)

                                   next_state=KEY_PRESSED;

                            else

                                   next_state=SCAN_COL2; 

                     SCAN_COL2:         //扫描第 2 列

                            if(row!=4'hf)

                                   next_state=KEY_PRESSED;

                            else

                                   next_state=SCAN_COL3;

                     SCAN_COL3:        //扫描第 3 列

                            if(row!=4'hf)

                                   next_state=KEY_PRESSED;

                            else

                                   next_state=NO_KEY_PRESSED;      

                     KEY_PRESSED:      //有按键按下

                            if(row!=4'hf)

                                   next_state=KEY_PRESSED;

                            else

                                   next_state=NO_KEY_PRESSED;         

              endcase

 

            /*************************************************/  

              reg key_pressed_flag; //按键按下标志

              reg [3:0]col_val;      //列值

              reg [3:0]row_val;     //行值

              /*************************************************/

              //根据次态,给相应的寄存器赋值

             /*************************************************/

              always @(posedge key_clk or negedge rst_n)

                     if(!rst_n) begin      //复位

                            col<=4'h0;

                            key_pressed_flag<=0;

                            end

                     else begin

                            case (next_state)

                                   NO_KEY_PRESSED:

                                          begin

                                          col<=4'h0;

                                          key_pressed_flag<=0;

                                          end

                                   SCAN_COL0:       //扫描第 0 列

                                          col<=4'b1110;

                                   SCAN_COL1:       //扫描第 1 列

                                          col<=4'b1101;

                                   SCAN_COL2:       //扫描第 2 列

                                          col<=4'b1011;

                                   SCAN_COL3:      //扫描第 3 列

                                          col<=4'b0111;

                                   KEY_PRESSED:     //有按键按下

                                          begin

                                          col_val<=col;   // 锁存列值

                                          row_val<=row;  // 锁存行值

                                          key_pressed_flag<=1;          // 置键盘按下标志

                                   end

                            endcase

       此处省略xxx字……………………

       ……………………………………….

       /*************************************************/

介位看官,有何感想,是不是觉得So easy ?状态划分很清晰,逻辑上也很顺畅,顺着代码看一切都是那么美好!

PARTNER CONTENT

文章评论2条评论)

登录后参与讨论

用户401816 2012-5-26 11:52

菜鸟第二次发帖,呵呵

用户419124 2012-5-25 22:42

LZ不错,加油
相关推荐阅读
用户401816 2012-08-24 11:16
HDL代码维护:都会有的第一次
  尊重原作者的劳动。   以欣赏的眼光去阅读代码,吸取其精妙之处。   清醒地认识到代码存在的问题,并仔细斟酌。   代码分析步骤:   阅读设计文档,仔细、...
用户401816 2012-05-23 19:28
【博客大赛】【原创】状态机输入与输出相关带来的时序问题[后篇]
如果用单片机来写这个程序,我们会这么写,先输出col,再检测row行值。同样上面的Verilog代码目的也是要实现这个时序,但恰恰是检测 row在输出col之前。所以对这个代码进行修改的话就是让它...
用户401816 2012-05-23 19:25
【博客大赛】【原创】状态机输入与输出相关带来的时序问题[中篇]
可一到运行起来就蛋疼了,呵呵…. 下面分析一下,仅供参考,若有不对,敬请指正!   看上面时序图在 1、第0~2个时钟周期内 row(输入)为4’b1111代表无键按下,...
用户401816 2012-04-18 22:56
双向口采用纯组合逻辑产生的组合回环
这是一个RAM的代码: me :使能信号 io: 控制输入输出 io=1接收,io=0输出 marL:地址寄存使能信号 /*----------------------------...
EE直播间
更多
我要评论
2
16
关闭 站长推荐上一条 /3 下一条