当前位置:   article > 正文

FPGA知识基础之--按键控制LED灯项目

FPGA知识基础之--按键控制LED灯项目


前言

笔者将基于正点原子的达芬奇开发板,结合夏宇闻老师的Verilog数字系统设计教程,来记录自己学习FPGA的学习思路,希望能给与读者一些帮助


一、按键简介

按键:通过按下或者释放来控制电路通断的电子元件

自锁按键:按下之后能保持,类似于开发板的电源按键

轻触摸式按键:按下就通,松开即断

按键原理图

按下是低电平,断开高电平

在这里插入图片描述

二、实验要求

在这里插入图片描述


三、程序设计

3.1思路整理

在这里插入图片描述

3.2 模型搭建

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

3.3 顶层模块

在这里插入图片描述

3.4 波形分析

在这里插入图片描述

四、代码整理

4.1RTL代码

module key_led(
input 					sys_clk,
input 					sys_rst_n,
input 	[3:0]			key,

output	reg [3:0] 		led

);

parameter CNT_MAX = 25'd25000000;//可在仿真时改为25'd25;,对应500ns

reg [24:0] cnt;
reg [1:0] 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

//LED状态切换标志位
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 
			cnt <= 25'd0;
		
end

//LED控制
always @(posedge sys_clk or negedge sys_rst_n) begin
	if(!sys_rst_n)
		led <= 4'd0;
	else
		begin
			case(key)
				4'b1111 : led <= 4'b0000;
				4'b1110 :begin
					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
					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
				
						if((led_flag == 2'd0)||(led_flag == 2'd2))
							led <= 4'b1111;
						else 
							led <= 4'b0000;
				
						end
				4'b0111 :  led <= 4'b1111;
				default : ;
			endcase
				
				
						
						
		
		end
end
endmodule

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86

4.2 仿真

需要注意的是,在modelsim仿真时,可以将0.5s改为20ns以缩短仿真时间,仅需将CNT_MAX改为25’d25即可
testbench代码

`timescale	1ns/1ns //仿真的单位/仿真的精度s
module tb_key_led();

parameter CLK_PERIOD = 20;

reg 		sys_clk;  //周期20ns
reg 		sys_rst_n; //并非所有的输入都是reg,根据代码编写情况
reg [3:0] 	key;


wire  [3:0]	led;

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'b1111;//松开key0
	#2000
	key <= 4'b1101;//按下key1
	#2000
	key <= 4'b1111;//松开key1
	#2000
	key <= 4'b1011;//按下key2
	#2000
	key <= 4'b1111;//松开key2
	#2000
	key <= 4'b0111;//按下key3
	#2000
	key <= 4'b1111;//松开key3
	
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
 
 

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55

笔者在进行仿真分析是发现了自己代码编写的一些小错误
例如,在编写rtl代码时,输入输出信号用的是分号,而不是逗号
在编写Testbench代码的时候,笔者发现自己在进行实例化时忘记改名了

同时,在仿真时,若是每次仿真都要改RTL代码,还是比较繁琐的,为此,笔者希望可以在Testbench上进行修改,以下是笔者根据资料学习的办法

parameter CNT_MAX = 25'd25;





 u_key_led #(
	.CNT_MAX  (CNT_MAX)
 );
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
只需在Testbench上增加上述一段代码即可将参数实例化,可达到在Testbench上更改参数的目的

关于modelsim的用法心得:指令篇
restart -f 即重新开始仿真
run -time 即仿真时间;

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号