引入按键控制流水灯
需求:实现一直按住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
按键消抖原理
运行结果
引入四个按键消抖控制流水灯
需求:实现四个按键按住松开控制流水灯的功能。
注意:请添加脉冲信号
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