【FPGA学习笔记02】按键控制LED灯

具体见正点原子《达芬奇Pro之FPGA开发指南v2.1》

1.硬件介绍:按键

按键开关是一种电子开关,属于电子元器件类。
这里主要用轻触式按键开关。该开关只有在被施加压力时内部电路才会闭合导通,也就是说,只有按住按键时才有动作响应,松开没有。
(1)原理图
在这里插入图片描述
①电阻:限流,防止按键按下时电源直接接地造成电路短路。
②按下按键后输出高电平。
在这里插入图片描述
结合原理图可知,KEY0对应T4,KEY1对应T3,KEY2对应R6,KEY3对应T6。
管脚约束代码如下:

#------------------LED-----------------------------
set_property -dict {PACKAGE_PIN V9 IOSTANDARD LVCMOS15} [get_ports {led[0]}]
set_property -dict {PACKAGE_PIN Y8 IOSTANDARD LVCMOS15} [get_ports {led[1]}]
set_property -dict {PACKAGE_PIN Y7 IOSTANDARD LVCMOS15} [get_ports {led[2]}]
set_property -dict {PACKAGE_PIN W7 IOSTANDARD LVCMOS15} [get_ports {led[3]}]
#------------------按键----------------------------
set_property -dict {PACKAGE_PIN T4 IOSTANDARD LVCMOS15} [get_ports {key[0]}]
set_property -dict {PACKAGE_PIN T3 IOSTANDARD LVCMOS15} [get_ports {key[1]}]
set_property -dict {PACKAGE_PIN R6 IOSTANDARD LVCMOS15} [get_ports {key[2]}]
set_property -dict {PACKAGE_PIN T6 IOSTANDARD LVCMOS15} [get_ports {key[3]}]

这里采用了整合的写法,用-dict实现,分开写举例如下:

set_property PACKAGE_PIN V9 [get_ports {led[0]}]
set_property IOSTANDARD LVCMOS15 [get_ports {led[0]}]

和整合写法相比,分开写要写的代码量较大,且重复了一些语句。

2.软件部分:主要代码

主要功能为:
按下KEY0 - LED从低到高流水
按下KEY1 - LED从高到低流水
按下KEY2 - LED间隔0.5s亮灭交替
按下KEY3 - LED常亮

module key_led(
   //input
   input			sys_clk,
   input			sys_rst_n,
   input	[3:0]	key,
   
   //output
   output reg[3:0]  led
);

//parameter
parameter CNT_MAX = 25'd2500_0000;
//parameter CNT_MAX = 25'd25;

//reg define
reg [24:0] cnt;
reg [1:0]  led_flag;

//***********************************
//**	main code
//***********************************

//计数器计时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

//LED状态切换标志位
// 0   1   2   3
// 00 01  10  11
always @(posedge sys_clk or negedge sys_rst_n) begin
	if(!sys_rst_n)
		led_flag <= 2'd0;
	else if(cnt == (CNT_MAX - 25'd1)) 
		led_flag <= led_flag + 2'd1;
	else
		led_flag <= led_flag;
end

//LED控制
always @(posedge sys_clk or negedge sys_rst_n) begin
	if(!sys_rst_n)
		led <= 4'b0000; //LED初始化全灭
	else begin
		case(key)
			4'b1111: led <= 4'b0000; //未按下:LED常灭
			4'b1110: begin //按下key0,从低到高流水灯
				if(led_flag == 2'd0)
					led <= 4'b0001;
				else if(led_flag == 2'd1)
					led <= 4'b0010;
				else if(led_flag == 2'd2)
					led <= 4'b0100;
				else
					led <= 4'b1000;
			end
			4'b1101: begin //按下key1,从高到低流水灯
				if(led_flag == 2'd0)
					led <= 4'b1000;
				else if(led_flag == 2'd1)
					led <= 4'b0100;
				else if(led_flag == 2'd2)
					led <= 4'b0010;
				else
					led <= 4'b0001;
			
			end
			4'b1011: begin //按下key2,4个LED一起交替闪烁
				if(led_flag[0] == 1'b0) 
					led <= 4'b1111;
				else
					led <= 4'b0000;
			end
			4'b0111: begin //按下key3,4个LED一起亮
				led <= 4'b1111;
			end
			default: ; 
		endcase
	end
end
endmodule

①设置了变量led_flag用来表示四个灯。
②用case判断是哪个按键按下。
③设置了常量CNT_MAX便于修改定时器定时时间。

3. 检测部分:仿真

仿真代码:

`timescale 1ns/1ns

module tb_key_led();

//parameter define
parameter CLK_PERIOD = 20;  //20ns
parameter CNT_MAX = 25'd25; //仅用于仿真,500ns(20*25 = 500)

//reg define
reg				sys_clk;
reg				sys_rst_n;
reg [3:0]		key;

//wire define
wire [3:0]		led;

//产生时钟
always #(CLK_PERIOD/2) sys_clk = ~sys_clk;

//信号初始化
initial begin
	sys_clk <= 1'b0;
	sys_rst_n <= 1'b0;
	key <= 4'b1111;
	
	#200
	sys_rst_n <= 1'b1;
	
	#2000
	key <= 4'b1110; //按下key0
	
	#2000
	key <= 4'b1101; //按下key1
	
	#2000
	key <= 4'b1011; //按下key2
	
	#2000
	key <= 4'b0111; //按下key3
	
	#2000
	key <= 4'b1111; //松开
end

//例化待测设计
key_led #(
	.CNT_MAX	(CNT_MAX)
)u_key_led(
	.sys_clk	(sys_clk),
	.sys_rst_n	(sys_rst_n),
	.key		(key),
	.led		(led)
);
endmodule

仿真结果:
在这里插入图片描述①设置数字格式可以右击变量,选择Radix,在列表里选择想要的数字格式即可(包括十六进制、十进制等)。

  • 7
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值