【FPGA项目】第1个项目,来点个灯吧~

前言

你会FPGA吗?我会点灯!

一、概述

        作为一名点灯高手,今天就来实际操练一下。

如何点亮?

        开发板上带有8个LED灯,我们只需要控制它对应的管脚电平输入即可。

 1:灭;0:亮。

 如何实现流水灯?

        通过 FPGA 内部的定时器,循环点亮每个 LED,达到流水灯的效果。如下图 所示,8 个 LED 指示灯,我们依次给它们赋值,每次只有一个 LED 点亮, 每次点亮某个 LED 的时间一定(固定延时)。8个 LED 依次被点亮一次,如此循环便能达到流水灯的效果。

【FPGA项目】第1个项目,来点个灯吧~_第1张图片

二、代码

module flow_led(
			input 			i_sys_clk,	//外部输入50MHz时钟信号
			input 			i_rst_n,	//外部输入复位信号,低电平有效
			output	[7:0] 	o_led		//8个LED指示灯接口,1--灭;0--亮
		);		

`define SIM	//仿真时使用		
		
`ifdef SIM	
	parameter MAX_CNT = 24'd10;
`else 
	parameter MAX_CNT = 24'd9_999_999;
`endif
	
//-------------------------------------
reg[23:0] cnt;		//24位计数器
reg[7:0]  led;															

	//cnt计数器进行循环计数,一个计数周期的时间为 10000000*20ns = 200ms
always @ (posedge i_sys_clk or negedge i_rst_n)									
	if(!i_rst_n) cnt <= 24'd0;											
	else if(cnt < MAX_CNT) cnt <= cnt+1'b1;	
	else cnt <= 24'd0;

//-------------------------------------

	//计数器cnt计数到最大值时,切换点亮的指示灯
always @ (posedge i_sys_clk or negedge i_rst_n) 
	if(!i_rst_n) led <= 8'b1111_1110;	//默认只点亮一个指示灯D2
	else if(cnt == MAX_CNT) led <= {led[6:0],led[7]};	//200ms为一个计数周期,执行一次循环移位操作

assign  o_led = led;		
	

endmodule

2.1代码说明

`define SIM

`ifdef SIM

parameter MAX_CNT = 24'd10;

`else

parameter MAX_CNT = 24'd9_999_999;

`endif

        表示如果代码中定义了 SIM,则执行 MAX_CNT = 24'd10 的赋值;否者执行 MAX_CNT = 24'd9_999_999 的赋值。那么我们使用这个定义,仿真和板级两种情况下 MAX_CNT 的取值不同,仿真时希望快速看到结果,那么计数值小一些,我们看到功能实现即可;而板 级情况下,流水灯的速度不能太快(太快就看不到流水灯的效果了),必须至少有几百毫秒 的延时才能够看清流水灯的效果。因此,在做仿真时,需要有“`define SIM”这个语句,而在实际板级编译时,则必须注释该语句。

三、仿真

`timescale 1ns / 1ps

`timescale 1ns/1ps
module flow_led_tb();
	
reg sys_clk_i;	
reg ext_rst_n;	
wire[7:0] led;	
	
flow_led		u_flow_led(
			.i_sys_clk(sys_clk_i),	
			.i_rst_n(ext_rst_n),	
			.o_led(led)		
		);			
	
initial begin
	sys_clk_i = 0;
	ext_rst_n = 0;	//复位中
	#1000;
	@(posedge sys_clk_i); #2;
	ext_rst_n = 1;	//复位结束,正常工作
	#5000;
	$finish;
end	
	
always #10 sys_clk_i = ~sys_clk_i;	//50MHz时钟产生
	
endmodule

        为了便于查看,我们先选中 led[7:0]这个信号,然后在 Value 这一列中右键单击,如下图所示,弹出菜单中点击 Radix --> Binary,表示以 2 进制方式显示。

【FPGA项目】第1个项目,来点个灯吧~_第2张图片

        led 信号以 2 进制显示,我们可以更直观的看到 8 位数据中有 1 位是 0,且不断的向左移动,到最高位后又回到最低位。

【FPGA项目】第1个项目,来点个灯吧~_第3张图片

四、上板子

生成bit/mcs文件的流程就不啰嗦了,这里简单看下约束文件

set_property IOSTANDARD LVTTL [get_ports sys_clk_i]

set_property PACKAGE_PIN N11 [get_ports sys_clk_i]



set_property IOSTANDARD LVTTL [get_ports ext_rst_n]

set_property PACKAGE_PIN T2 [get_ports ext_rst_n]



set_property IOSTANDARD LVTTL [get_ports {led[0]}]

set_property PACKAGE_PIN M1 [get_ports {led[0]}]

set_property IOSTANDARD LVTTL [get_ports {led[1]}]

set_property PACKAGE_PIN N1 [get_ports {led[1]}]

set_property IOSTANDARD LVTTL [get_ports {led[2]}]

set_property PACKAGE_PIN P1 [get_ports {led[2]}]

set_property IOSTANDARD LVTTL [get_ports {led[3]}]

set_property PACKAGE_PIN R2 [get_ports {led[3]}]

set_property IOSTANDARD LVTTL [get_ports {led[4]}]

set_property PACKAGE_PIN T3 [get_ports {led[4]}]

set_property IOSTANDARD LVTTL [get_ports {led[5]}]

set_property PACKAGE_PIN R5 [get_ports {led[5]}]

set_property IOSTANDARD LVTTL [get_ports {led[6]}]

set_property PACKAGE_PIN R6 [get_ports {led[6]}]

set_property IOSTANDARD LVTTL [get_ports {led[7]}]

set_property PACKAGE_PIN T7 [get_ports {led[7]}]





set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 4 [current_design]

set_property BITSTREAM.CONFIG.SPI_FALL_EDGE YES [current_design]

上板效果:

略。

后期图像采集和以太网通信等等项目再上板子。

后记

        其他常见的什么加法器、按键消抖、FIFP IP创建等等凑字数的东西,这个系列就不写了,专栏文章如同《FPGA接口篇》一样,实用为主。

        下个项目,开始虚拟项目教学,一般作为公司的入职培训

        咱们下期见~

你可能感兴趣的:(FPGA项目篇,fpga开发)