视频教程:第11.1讲 按键控制LED灯实验原理讲解_哔哩哔哩_bilibili
约束文件:digilent-xdc/Zybo-Master.xdc at master · Digilent/digilent-xdc (github.com)
原理图:Zybo Z7 - Digilent Reference B
实验任务
使用ZYBO上的PL端按键,分别控制两个PL端的LED,按下不同的按键时, 两个LED显示不同效果:
按键状态 | LED显示效果 |
---|---|
无按键按下 | 两个LED全亮 |
按下KEY0 | 两个LED交替闪烁 |
按下KEY1 | 两个LED同时闪烁 |
不同效果下两个LED灯led[0]和led[1]状态的变化:
无按键按下:led=11,11,11,11,…
按下key[0]: led=10,01,10,01,…
按下key[1]: led=11,00,11,00,…
程序设计
时钟频率50MHz =》时钟周期20ns
当key按下后每0.5s LED灯变化一次,计数器一个周期累加一次,所以计数器从0累加到25M=2500_0000后归零
key_led.v
module key_led(
input sys_clk,
input sys_rst_n,
input [1:0] key,
output reg [1:0] led
);
reg [24:0] cnt;
reg led_controller;
always @(posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n)
cnt <= 25'd0;
else if(cnt < 2500_0000)
cnt <= cnt + 1'b1;
else
cnt <= 25'd0;
end
always @(posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n)
led_controller <= 1'b0;
else if(cnt == 2500_0000)
led_controller <= ~led_controller;
end
always @(posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n)
led<=2'b11;
else case (key)
2'b10:
if(led_controller == 1'b0)
led <= 2'b10;
else
led<= 2'b01;
2'b01:
if(led_controller == 1'b0)
led <= 2'b11;
else
led<= 2'b00;
default: ;
endcase
end
endmodule
testbench: tb_key_led.v
首先定义要输入的信号,然后对其初始化,在initial模块里对时序进行控制
- 初始时钟为0,复位为0,按键全安
- 60ns,三个周期后,复位为高电平
- 40ns,两个周期后,按下按键0, key = 10, led灯交替闪烁
- 交替闪烁2000ns后,按键全按下,key=11
- 100ns后,按键1按下,key=01, led灯同时闪烁
- 同时闪烁2000ns后,按键全按下
例化key_led模块
时钟周期为20ns,所以每10ns取反
`timescale 1ns/1ps
module tb_key_led ();
reg sys_clk;
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;
#60
sys_rst_n = 1'b1;
#40
key = 2'b10;
#2000
key = 2'b11;
#100
key = 2'b01;
#2000
key = 2'b11;
end
key_led u_key_led(
.sys_clk(sys_clk),
.sys_rst_n(sys_rst_n),
.key(key),
.led(led)
);
always #10 sys_clk <= ~sys_clk;
endmodule
ModelSim仿真
改变工作目录:File->Change Directory,添加verilog文件 -> Compile ->Compile All
开始仿真:Simulate->start simulate,添加设计文件 tb_key_led.v,取消使能优化enable optimization
添加需要查看波形图的信号:
由于每0.5s也就是cnt计数到25M后led变化一次时间太长,改为25后保存,重新编译仿真
设置运行时间100ms,点击运行
放缩到合适的尺度[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-:
三周期系统复位,再两周期后 按下按键0:key=10:
两个led灯交替闪烁:10,01,10,01
2100ns后,key变为11
2200ns后,按键1被按下,key=01:两个led灯同时闪烁:11,00,11,00
vivado下载验证
添加
- 设计文件:key_led.v
- 约束:key_led.xdc
- 总的约束文件:digilent-xdc/Zybo-Master.xdc at master · Digilent/digilent-xdc (github.com)
修改:
- 将cnt计数改为25M
- zybo没有复位按键,将按键3 btn[2] 变为复位按钮
- 按钮是按下变成高电平有效,不安下是低电平,所以sys_rst_n前面的 ! 要去掉
module key_led(
input sys_clk,
input sys_rst_n,
input [1:0] key,
output reg [1:0] led
);
reg [24:0] cnt;
reg led_controller;
always @(posedge sys_clk or negedge sys_rst_n) begin
if(sys_rst_n)
cnt <= 25'd0;
else if(cnt < 2500_0000)
cnt <= cnt + 1'b1;
else
cnt <= 25'd0;
end
always @(posedge sys_clk or negedge sys_rst_n) begin
if(sys_rst_n)
led_controller <= 1'b0;
else if(cnt == 2500_0000)
led_controller <= ~led_controller;
end
always @(posedge sys_clk or negedge sys_rst_n) begin
if(sys_rst_n)
led<=2'b11;
else case (key)
2'b10:
if(led_controller == 1'b0)
led <= 2'b10;
else
led<= 2'b01;
2'b01:
if(led_controller == 1'b0)
led <= 2'b11;
else
led<= 2'b00;
default: ;
endcase
end
endmodule
取消需要接口的注释,并更改端口名称与程序对应:
## This file is a general .xdc for the ZYBO Rev B board
## To use it in a project:
## - uncomment the lines corresponding to used pins
## - rename the used signals according to the project
##Clock signal
set_property -dict { PACKAGE_PIN L16 IOSTANDARD LVCMOS33 } [get_ports { sys_clk }]; #IO_L11P_T1_SRCC_35 Sch=sysclk
#create_clock -add -name sys_clk_pin -period 8.00 -waveform {0 4} [get_ports { clk }];
##Switches
#set_property -dict { PACKAGE_PIN G15 IOSTANDARD LVCMOS33 } [get_ports { sw[0] }]; #IO_L19N_T3_VREF_35 Sch=SW0
#set_property -dict { PACKAGE_PIN P15 IOSTANDARD LVCMOS33 } [get_ports { sw[1] }]; #IO_L24P_T3_34 Sch=SW1
#set_property -dict { PACKAGE_PIN W13 IOSTANDARD LVCMOS33 } [get_ports { sw[2] }]; #IO_L4N_T0_34 Sch=SW2
#set_property -dict { PACKAGE_PIN T16 IOSTANDARD LVCMOS33 } [get_ports { sw[3] }]; #IO_L9P_T1_DQS_34 Sch=SW3
##Buttons
set_property -dict { PACKAGE_PIN R18 IOSTANDARD LVCMOS33 } [get_ports { key[0] }]; #IO_L20N_T3_34 Sch=BTN0
set_property -dict { PACKAGE_PIN P16 IOSTANDARD LVCMOS33 } [get_ports { key[1] }]; #IO_L24N_T3_34 Sch=BTN1
set_property -dict { PACKAGE_PIN V16 IOSTANDARD LVCMOS33 } [get_ports { sys_rst_n }]; #IO_L18P_T2_34 Sch=BTN2
#set_property -dict { PACKAGE_PIN Y16 IOSTANDARD LVCMOS33 } [get_ports { btn[3] }]; #IO_L7P_T1_34 Sch=BTN3
##LEDs
set_property -dict { PACKAGE_PIN M14 IOSTANDARD LVCMOS33 } [get_ports { led[0] }]; #IO_L23P_T3_35 Sch=LED0
set_property -dict { PACKAGE_PIN M15 IOSTANDARD LVCMOS33 } [get_ports { led[1] }]; #IO_L23N_T3_35 Sch=LED1
#set_property -dict { PACKAGE_PIN G14 IOSTANDARD LVCMOS33 } [get_ports { led[2] }]; #IO_0_35=Sch=LED2
#set_property -dict { PACKAGE_PIN D18 IOSTANDARD LVCMOS33 } [get_ports { led[3] }]; #IO_L3N_T0_DQS_AD1N_35 Sch=LED3
生成bitstream
连接开发板->Open Hardware Manager->Open Target->Program Device:
在开发板上测试