【FPGA第二天】按键消抖+流水灯



引入按键控制流水灯

需求:实现一直按住key2控制流水灯的功能。

实现原理请详见注释,

实现代码:

module key_ctrl (
    input clk,
    input rst_n,    
    input wire key,

    output wire [3:0] led_on
);
    parameter MAX = 25'd25_000_000;

    reg [25:0] cnt;  //计数寄存器
    reg[3:0] led_r;

//记录0.5s计数器设计
always @(posedge clk or negedge rst_n) begin //只会在上升沿或者下降沿的时候进入always模块
    if(!rst_n)begin //取反代表下降沿
        cnt <=26'd0;
    end
    else if (cnt == MAX - 1'd1)begin//记到最大数时清零
        cnt <=26'd0; 
    end
    else begin //FPGA只有双分支和多分枝结构没有单分支结构,代码不严谨将导致系统产生毛刺
    cnt <= cnt+1'd1;
    end
end                 //计数观察
//always块里不可以赋值wire
always @(posedge clk or negedge rst_n) begin
    
    if(!rst_n)begin
        led_r <=4'b0001;
    end

    else if(!key)begin
        if (cnt==MAX-1'd1)begin
            led_r <= {led_r[2:0],led_r[3]};
        end
        else begin
            led_r <=led_r;
    end
    end

    else begin
            led_r <=led_r;
    end

end
    assign led_on =led_r;

endmodule

引脚设置

set_location_assignment PIN_G15 -to led_on[0]
set_location_assignment PIN_F16 -to led_on[1]
set_location_assignment PIN_F15 -to led_on[2]
set_location_assignment PIN_D16 -to led_on[3]
set_location_assignment PIN_E1 -to clk
set_location_assignment PIN_E15 -to rst_n

运行效果

若是报错:
在这里插入图片描述
请修改为常规引脚,而不是编程引脚。

在这里插入图片描述

引入按键消抖控制流水灯

需求:实现按住松开key2控制流水灯功能。

注意:这里我直接复制了上面的工程文件再修改代码,但是造成了项目还是继续沿用引脚led_on而不是led的问题,所以我新建了一个项目,重新配置了引脚。我的意思是,引脚配置最好一次性完成,不要后期去修改它。

module key_ctrl (
    input wire clk,
    input wire rst_n,
    input wire key,

    output wire [3:0]led
);
localparam MAX = 25'd25_000_000;
parameter Delay = 25'd10_000_000;
reg [24:0] cnt;
reg [3:0] led_r;
reg start;
reg key_r0;             //记录key按键状态
reg key_r1;             //记录key_r0按键状态
reg flag;               //开启流水信号
reg [24:0] delay_cnt;
wire nedge;


always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        delay_cnt <= Delay;
    end
    else if (delay_cnt <= 1'd1) begin
            delay_cnt <= 25'd0;
    end
    else if (start) begin
        if (delay_cnt == 1'd1) begin
            delay_cnt <= 25'd0;
        end
        else begin
           delay_cnt <= delay_cnt - 1'd1; 
        end
    end
    else begin
        delay_cnt <= delay_cnt ;
    end
end


always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        key_r0 <= 1'b1;
        key_r1 <= 1'b1;
    end
    else begin
        key_r0 <= key;
        key_r1 <= key_r0;
    end
end

assign nedge = ~key_r0 && key_r1;


//start 信号约束
always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        start <= 1'b0;
    end
    else if(nedge) begin
        start <= 1'b1;
    end
    else if (delay_cnt == 1'b1) begin
        start <= 1'b0;
    end
    else begin
        start <= start;
    end
end

//flag信号约束
always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        flag <= 1'b0;
    end
    else if (delay_cnt == 1'b1) begin
        flag <= ~key_r0;
    end
    else begin
        flag <= flag;
    end
end

always @(posedge clk or negedge rst_n) begin
    if(!rst_n)begin
        cnt <= 26'd0;
    end
    else if (cnt == MAX - 1'd1) begin
        cnt <= 26'd0;
    end
    else begin
        cnt <= cnt + 1'd1;
    end
end

always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
       led_r <= 4'b0001;
    end
    else if (flag) begin
        if(cnt == MAX - 1'd1)begin
            led_r <= {led_r[2:0],led_r[3]};
        end
    end
    else begin
        led_r <= led_r;
    end
end


assign led = led_r;


endmodule

引脚设置:

set_location_assignment PIN_G15 -to led[0]
set_location_assignment PIN_F16 -to led[1]
set_location_assignment PIN_F15 -to led[2]
set_location_assignment PIN_D16 -to led[3]
set_location_assignment PIN_E1 -to clk
set_location_assignment PIN_E15 -to rst_n

按键消抖原理

按键消抖原理,引用林老师

按键消抖原理2

运行结果

在这里插入图片描述

引入四个按键消抖控制流水灯

需求:实现四个按键按住松开控制流水灯的功能。

注意:请添加脉冲信号
在这里插入图片描述

module key_ctrl(
    input wire [3:0]key    ,
    input wire rst_n  ,
    input wire clk    ,

    output wire [3:0]led
);
localparam DELAY = 20'd1_000_000  ;
localparam MAX   = 25'd25_000_000 ;
reg [24:0] cnt      ;
reg [3:0]  led_r    ;
reg [19:0] cnt_20ms ; 
reg        start    ;
reg    [3:0]    key_r0   ;
reg    [3:0]   key_r1   ;
wire       nedge    ;
reg        [3:0]flag     ;
always @(posedge clk or negedge rst_n) begin
    if(!rst_n)begin
        cnt_20ms <=20'd0;
    end
    else if(nedge)begin
        cnt_20ms <= DELAY;
    end
    else if(cnt_20ms==1'd1)begin
        cnt_20ms<=20'd0;
    end
    else if(start) begin
        if(cnt_20ms==1'd1)begin
          cnt_20ms <= 20'd0;
        end
        else begin
          cnt_20ms <= cnt_20ms -1;
        end
    end
    else begin
        cnt_20ms <=cnt_20ms;
    end
end


always @(posedge clk or negedge rst_n) begin
    if(!rst_n)begin
        key_r0[3:0] <= 4'b1111;
        key_r1[3:0] <= 4'b1111;
    end
    else begin 
        key_r0<= key;
        key_r1 <= key_r0;
    end
end

assign nedge  = (~key_r0[0] && key_r1[0])||(~key_r0[1] && key_r1[1])||(~key_r0[2] && key_r1[2])||(~key_r0[3] && key_r1[3]);
always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        start <= 1'b0;
    end
    else if (nedge) begin
        start <= 1'b1;
    end
    else if(cnt_20ms == 1'b1)begin
        start <= 1'b0;
    end
    else begin
        start <= start;
    end
end
//约束flag信号
always @(posedge clk or negedge rst_n) begin
    if(!rst_n)begin
        flag[3:0] <= 4'b0000;
    end
    else if(cnt_20ms == 1'b1)begin
        flag <= ~key_r0;
    end
    else begin
        flag<=4'b0000;
    end
end

always @(posedge clk or negedge rst_n) begin
    if(!rst_n)begin
        cnt=25'b0;
    end
    else if(cnt == MAX - 1'd1)begin
        cnt<=25'b0;
    end
    else begin
        cnt<=cnt+1'd1;
    end
end

always @(posedge clk or negedge rst_n) begin
    if(!rst_n)begin
        led_r <= 4'b0000;
    end
    else if(flag[0])begin
        led_r[0] <= ~led_r[0];
    end
    else if(flag[1])begin
        led_r[1] <= ~led_r[1];
    end
    else if(flag[2])begin
        led_r[2] <= ~led_r[2];
    end  
	 else if(flag[3])begin
        led_r[3] <= ~led_r[3];
    end
    else begin
        led_r <= led_r;
    end
end
assign led = led_r ;
endmodule

引脚设置:

set_location_assignment PIN_G15 -to led[0]
set_location_assignment PIN_F16 -to led[1]
set_location_assignment PIN_F15 -to led[2]
set_location_assignment PIN_D16 -to led[3]
set_location_assignment PIN_E1 -to clk
set_location_assignment PIN_E15 -to key[0]
set_location_assignment PIN_E16 -to key[1]
set_location_assignment PIN_M16 -to key[2]
set_location_assignment PIN_M15 -to key[3]

在这里插入图片描述


工程文件

https://www.aliyundrive.com/s/7vHxSaFjn7p

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值