1月8日
按键与灯的配合实验
功能描述:按键1,控制流水灯静止或者移动; 按键2,控制流水灯向左移动;按键3,控制流水灯向右移动;
原理:
1、利用上例的key程序 建立一个模块。
2、由于有3个key 我创建了3个这样的模块。
3、key产生的按下信号 作为输入 写led程序。
主模块:
module key_led(
sys_clk,
sys_rstn,
key,
led
);
input sys_clk;
input sys_rstn;
input [2:0]key;
output [7:0]led;
wire [2:0]key_en;
key key0(
.sys_clk(sys_clk),
.sys_rstn(sys_rstn),
.key(key[0]),
.key_en(key_en[0])
);
key key1(
.sys_clk(sys_clk),
.sys_rstn(sys_rstn),
.key(key[1]),
.key_en(key_en[1])
);
key key2(
.sys_clk(sys_clk),
.sys_rstn(sys_rstn),
.key(key[2]),
.key_en(key_en[2])
);
led led0(
.key_en(key_en),
.sys_clk(sys_clk),
.sys_rstn(sys_rstn),
.led(led)
);
endmodule
key模块:
module key(
sys_clk,
sys_rstn,
key,
key_en
);
input sys_clk;
input sys_rstn;
input key;
output key_en;
//下降沿检测
reg key_first;
reg key_second;
wire neg_key;
always @(posedge sys_clk or negedge sys_rstn)
begin
if(!sys_rstn)
begin
key_first <= 1'b1; //下降沿检测 初始值为高电平
key_second <= 1'b1;
end
else
begin
key_second <= key_first;
key_first <= key;
end
end
assign neg_key = key_second & (~key_first); //只有下降沿才是1 其他的就是0了
//20ms 计数 20ms/20ns = 1000_000 20位 0--1000_000
reg [19:0]cnt;
always @(posedge sys_clk or negedge sys_rstn)
begin
if(!sys_rstn)
cnt <= 20'd1000_000;
else if(cnt==20'd1000_000 && neg_key)
cnt <= 20'h0;
else if(cnt<20'd1000_000)
cnt <= cnt + 1'b1;
end
//20ms后再来检测按键是否按下
reg key_en_r; //1为按下 0为非按下
always @(posedge sys_clk or negedge sys_rstn)
begin
if(!sys_rstn)
key_en_r <= 1'b0;
else if(cnt==20'd999999 && !key) //20ms 和 还是低电平
key_en_r <= 1'b1;
else key_en_r <= 1'b0;
end
assign key_en = key_en_r;
endmodule
led模块:
module led(
key_en,
sys_clk,
sys_rstn,
led
);
input [2:0]key_en;
input sys_clk;
input sys_rstn;
output [7:0]led;
//500ms 计数
//500ms/20ns/2=12500_000 0--12499_999
reg clk_500ms;
reg [23:0]cnt;
always @(posedge sys_clk or negedge sys_rstn)
begin
if(!sys_rstn)
begin
clk_500ms <= 1'b0;
cnt <= 24'b0;
end
else if(cnt==12499_999)
begin
clk_500ms <= ~clk_500ms;
cnt <= 24'b0;
end
else cnt <= cnt + 1'b1;
end
//记录按键情况
reg move; //是否要灯移动
reg flag; // 0为左移动 1为右移动
always @(posedge sys_clk or negedge sys_rstn)
begin
if(!sys_rstn)
begin
flag <= 1'b0;
move <= 1'b0;
end
else if(key_en[0])
move <= ~move;
else if(key_en[1])
flag <= 1'd0;
else if(key_en[2])
flag <= 1'd1;
else
begin
flag <= flag;
move <= move;
end
end
reg [7:0]led_r;
always @(posedge clk_500ms or negedge sys_rstn)
begin
if(!sys_rstn)
begin
led_r <= 8'b0000_0001;
end
else if(!move) //优先级最高
led_r <= led_r; //灯的开关
else if(flag)
led_r <= {led_r[6:0],led_r[7]}; //右移
else
led_r <= {led_r[0],led_r[7:1]}; //左移
end
assign led = led_r;
endmodule
验证了能正常工作。
key_led.rar