一、硬件设计
领航者7Z020-V2按键硬件图如下。
二、实验任务
实验任务是使用开发板上的两个按键控制两个LED灯的亮灭。按不同的按键,LED灯呈现不同的效果。
两个按键控制两个LED灯。(LED灯高电平点亮)
按键状态 | LED显示效果 |
无按键按下 | 两个LED灯全灭 |
按下KEY0 | 两个灯交替闪烁 |
按下KEY1 | 两个灯同闪同灭 |
LED灯流水间隔0.5s。
三、程序设计
1.思维导图
2.波形图
3.代码编写
module key_led(
input sys_clk,
input sys_rst_n,
input [1:0] key,
output reg [1:0] led
);
parameter CNT_MAX <= 25'd25000000;
reg [24:0] cnt;
reg led_flag;
//计时0.5s
always @(posedge sys_clk or negedge sys_rst_n)begin
if(!sys_rst_n)
cnt <= 25'd0;
else if(cnt < (CNT_MAX - 25'd1))
cnt <= cnt + 25'd1;
else
cnt <= 25'd0;
end
//每隔0.5s变化一次led标志位
always @(posedge sys_clk or negedge sys_rst_n)begin
if(!sys_rst_n)
led_flag <= 1'b0;
else if(cnt == (CNT_MAX - 25'd1))
led_flag <= ~led_flag;
else
led_flag <= led_flag;
end
//led控制
always @(posedge sys_clk or negedge sys_rst_n)begin
if(!sys_rst_n)
led <= 2'b00;
else begin
case(key)
2'b11 : led <= 2'b00;
2'b10 :
if(led_flag == 1'b0)
led <= 2'b01;
else
led <= ~led; //注意:这样写会产生问题,当按键按下时led0在变化时一直保持一定亮度,此句需改为:led <= 2'b10;
2'b01 :
if(led_flag == 1'b0)
led <= 2'b00;
else
led <= ~led; //此句没有出现上一句类似问题,可能是由于按位取反操作对上一句led0一直有信号产生
default : ;
endcase
end
end
endmodule
4.实验仿真
编写tb_key_led文件
'timescale 1ns/1ns //仿真单位/仿真精度
module tb_key_led();
parameter CLK_PERIOD = 20;
reg sys_clk; //周期20ns
reg sys_rst_n;
reg [1:0] key ;
wire [1:0] led;
initial begin
sys_clk <= 1'b0;
sys_rst_n <= 1'b0;
key <= 2'b11; //按键没被按下
#200
sys_rst_n <= 1'b1;
#2000
key <= 2'b10; //按下KEY0
#2000
key <= 2'b11; //释放KEY0
#2000
key <= 2'b01; //按下KEY1
#2000
key <= 2'b11; //释放KEY1
end
always #(CLK_PERIOD/2) sys_clk = ~sys_clk;
key_led u_key_led(
.sys_clk (sys_clk) ,
.sys_rst_n (sys_rst_n),
.key (key ),
.led (led )
);
endmodule
在modulesim仿真,以500ns为周期(减少仿真时间),下图为部分放大后仿真结果。
注:led灯变化不是与led_flag反转沿对其的,因为需要采集到下个时钟上升沿才会led变化。
实验验证为预期输出。
四、下载验证
通过vivado创建工程,配置IO口和约束文件。
编译之后下载到开发板。
显示编译成功。
通过open target自动连接开发板再选择到指定文件(代码)下载
开发板实现控制效果。
key0:
key1: