按键计数器#DE10-Lite

  1. DE10-Lite数码管:0点亮,1熄灭。

 

image

 

image

 

image

 

 

  1. 代码逻辑

按键计数需要处理1:按键消抖,2计数。

按键消抖:用2个按键KEY0和KEY1分别表示加计数和减计数的控制信号,检测按下的有效边沿,把按键输入key_in打两拍给key_buff2,然后用key_buff2去判断按键的状态,由按键的状态再打两拍来判断边沿。

 

按键边沿检测核心代码:

 

always @(posedge clk,negedge rst_n)
        begin
            if(!rst_n)
                begin
                    key_buff1 <= 0;
                    key_buff2 <= 0;
                end
            else
                begin
                    key_buff1 <= key_in;
                    key_buff2 <= key_buff1;
                end
        end
        
    always @(posedge clk,negedge rst_n)
        begin
            if(!rst_n)
                begin
                    state <= 0;
                    cnt <= 0;
                    key_out <= 1; //按键未按下
                end
            else
                begin
                    case(state)
                        0: begin
                                if(!key_buff2) // 按下
                                    begin
                                        if(cnt < T - 1)    // < 10ms
                                            begin
                                                cnt <= cnt+1;    //延时计数
                                                state <= 0; //状态保持没按下
                                                key_out <= 1;    
                                            end
                                        else    //按下持续达到10ms
                                            begin
                                                cnt <= 0;    
                                                state <= 1;    //进入按下状态
                                                key_out <= 0;
                                            end
                                    end
                                else    //没按下
                                    begin
                                        cnt <= 0;
                                        state <= 0;
                                        key_out <= 1;
                                    end
                            end
                        1: begin
                                if(key_buff2) // 松开
                                    begin
                                        if(cnt < T - 1)    //延时判断
                                            begin
                                                cnt <= cnt+1;
                                                state <= 1; //不够10ms延时,状态不变
                                                key_out <= 0;
                                            end
                                        else    // 延时足够,状态转换,按键拉高
                                            begin
                                                cnt <= 0;
                                                state <= 0;
                                                key_out <= 1;
                                            end
                                    end
                                else    //按键按住不松
                                    begin
                                        cnt <= 0;
                                        state <= 1;
                                        key_out <= 0;
                                    end
                            end
                        default: state <= 0;    
                    endcase    
                end
        end
        
    reg key_out_buff1,key_out_buff2;
    
    always @(posedge clk,negedge rst_n)
        begin
            if(!rst_n)
                begin
                    key_out_buff1 <= 1;
                    key_out_buff2 <= 1;
                end
            else
                begin
                    key_out_buff1 <= key_out;
                    key_out_buff2 <= key_out_buff1;
                end
        end
    
    assign pose_flag = key_out_buff1 & ~key_out_buff2;
    assign nege_flag = ~key_out_buff1 & key_out_buff2;

 

计数:有符号的计数器,符合位的处理,补码的逆运算,减1再取反。

有符号计数器核心代码:

 

always @(posedge clk,negedge rst_n)
        begin
            if(!rst_n)
                temp_a <= 0;
            else
                if(add_flag && temp_a < 5'sd15 && !sub_flag)
                    temp_a <= temp_a + 1;
                else
                    if(sub_flag && temp_a > -5'sd15 && !add_flag)
                        temp_a <= temp_a - 1;
                    else
                        temp_a <= temp_a;
        end
        
    assign symbol = temp_a[4] ? 1'b1 : 1'b0;
    
    wire [3:0] temp_b;
    
    assign temp_b = ~(temp_a[3:0] - 1);
    
    assign data = temp_a[4] ? temp_b : temp_a[3:0];
    

 

整体设计:连线,按键边沿检测—计数—bin转bcd—数码管驱动。

顶层核心代码:

 

key_filter k1(
        .clk(clk),
        .rst_n(rst_n),
        .key_in(key_add),
        .nege_flag(add_flag),
        .pose_flag()
    );
    
    key_filter k2(
        .clk(clk),
        .rst_n(rst_n),
        .key_in(key_sub),
        .nege_flag(sub_flag),
        .pose_flag()
    );
    //--------------------------
    wire [3:0] key_data;
    wire [3:0] symbol;
    
    key_num_signed k3(
        .clk(clk),
        .rst_n(rst_n),
        .add_flag(add_flag),
        .sub_flag(sub_flag),
        .data(key_data),
        .symbol(symbol)
        );
    //--------------------------
    wire [7:0] key_bcd;
    
    bin2bcdv3 #(.BIN_WIDTH(4),.BCD_WIDTH(8))
                b1(
                    .bin(key_data),
                    .bcd(key_bcd)
                    );
    //------------------------------------                
    
    seg s0(.din(key_bcd[3:0]),.dout(seg_out0));    
    seg s1(.din(key_bcd[7:4]),.dout(seg_out1));    
    seg s2(.din(4'd0),.dout(seg_out2));    
    seg s3(.din(4'd0),.dout(seg_out3));
    seg s4(.din(4'd0),.dout(seg_out4));    
    seg s5(.din(symbol),.dout(seg_out5));

 

posted on 2026-04-02 08:52  yf.x  阅读(2)  评论(0)    收藏  举报

导航