Verilog 实现流水灯

1、实验平台

软件:PC、Quartus Prime 18.1、Modelsim 10.5b
硬件:Altera FPGA开发板(EP4CE6E22F17C8)

2、实验目的

编写Verilog HDL代码驱动开发板上8颗LED实现流水灯效果

2.1、实验要求

1、每次点亮一颗LED,持续(亮灯)时间,1S
2、方向从右到左,最左边LED亮满1s之后,实现最右边的灯亮

3、实验流程

3.1、实验原理

根据开发板的原理图,可得到以下资料

在这里插入图片描述

根据硬件原理图所示,8颗发光二极管,所有的阳极都接通3.3V的正电压,也即————高电平,所以如果我们想要
发光二极管导通的话,需要在阴极接通低电平,就可以让LED亮起来。

3.2、框架设计

由于只是驱动8颗LED,即发光二极管,故可得到以下框架

在这里插入图片描述

3.3、功能模块划分

由于本设计比较简单,故没有必要划分多个模块	

在这里插入图片描述
信号定义

信号名端口类型信号说明
Clki输入时钟信号,50MHz
Rst_ni输入复位信号,低电平有效
Led[7:0]o输出LED信号,低电平有效

3.4、时序信号图

在这里插入图片描述

时钟信号:
	频率为50MHz,对应周期20ns,50%占空比的方波信号,多用于时序逻辑电路的控制信号;
复位信号:
	信号名后加上“_n”,表明该信号为低电平有效,当复位信号有效时,所有时序逻辑恒定在一个固定的状态;
计数器信号:
	要产生计时/定时效果,则需要生成计数器完成相应逻辑控制。由于开发板所搭载的晶振为50MHz,也即是说,
1秒钟晶振产生50M—>5000_0000次振动。而verilog所描述的时序逻辑都是基于时钟信号的控制————
上升沿或者下降沿,更新寄存器/触发器的值,我们让计数器在每一次时钟信号的上升沿处更新(自加1),
那么,计数器每计满5000_0000次,就是1s;然后在计满1秒的时候产生1个有效期为1个时钟周期的脉冲信号,
用以驱动LED信号进行变化;
led信号:
	系统处于复位状态时,LED全灭或者全亮,其后受计数器信号的驱动,做流水效果。

3.5、代码实现

相信基于以上的讲解,大家都能尝试着自己写出代码,这里给出一份Demo,以供参考:
/*================================================*\
		  Filename ﹕led_water.v
			Author ﹕Adolph
	  Description  ﹕8位流水灯
		 Called by ﹕No file
Revision History   ﹕ 2022-4-18 
		  			  Revision 1.0
  			  Email﹕ adolph1354238998@gamil.com
\*================================================*/
module led_water(
		//端口信号声明
	input wire 	clk		,//50MHz
	input wire	rst_n	,//reset ,low valid

	output [7:0]led_o	 //最后一个端口信号没有“,”
);
//参数定义
	parameter CNT_MAX = 26'd5000_0000;
//内部信号声明
	reg [25:0]	cnt_1s;//1s 计数器,计数最大值 5000_0000 - 1
	wire 		flag_1s;//计数器每计满1s,使能一个时钟周期

	reg [7:0]	led_reg;//输出信号的寄存信号
//逻辑实现
	//时序逻辑描述1s计数器
	always@(posedge clk or negedge rst_n)begin
		if(!rst_n)
			cnt_1s <= 26'd0;
		else if(cnt_1s >= CNT_MAX - 26'd1) //归零条件
			cnt_1s <= 26'd0;
		else
			cnt_1s <= cnt_1s + 26'd1;
	end
	
	assign flag_1s = cnt_1s >= CNT_MAX - 26'd1;

  //移位实现流水灯
	always@(posedge clk or negedge rst_n)begin
		if(!rst_n)
			led_reg <= 8'b0000_0000;//全亮
		else if(flag_1s)
			if(led_reg == 8'b0000_0000)
				led_reg <= 8'b1111_1110;
			else
				led_reg <= {led_reg[6:0],led_reg[7]};//拼接实现循环移位
		else
			led_reg <= led_reg;
	end

	assign led_o = led_reg;
	
endmodule 

3.6、测试文件

/*================================================*\
		  Filename ﹕ tb_led_water
			Author ﹕ Adolph
	  Description  ﹕ 流水灯仿真测试文件
		 Called by ﹕ No file
Revision History   ﹕ 2022-4-18 
		  			  Revision 1.0
  			  Email﹕ adolph1354238998@gmail.com
\*================================================*/
`timescale  1ns/100ps //定义仿真系统基本时间单位、时间精度
module tb_led_water();

//激励信号
	reg			tb_clk		;
	reg			tb_rst_n	;

//观测信号
	wire [7:0]	tb_led_o	;
	
//参数重定义
	defparam U_led_water.CNT_MAX = 100;
	

//模块例化
	led_water	U_led_water/*例化名称*/(
		/*input 			*/.clk	(tb_clk  ),//50MHz
		/*input				*/.rst_n(tb_rst_n),//low valid
	
		/*output reg [7:0] 	*/.led_o(tb_led_o)
	);

//时间生成
	initial tb_clk = 1'b0;
	always #10 tb_clk = ~tb_clk;

//系统初始化
	initial begin
		tb_rst_n = 1'b0;
		#38 ;
		tb_rst_n = 1'b1;
		
		#18000; //系统运行时间??? 2000ns * 9
		$stop; //系统函数。暂停仿真
	end

endmodule 

仿真图
关于Modelsim的使用,请自行百度
在这里插入图片描述
在这里插入图片描述

跟据仿真波形图,可以看到一切如我们预期那样,实现了LED的循环流水效果。

3.7、上板验证

基于前面的步骤的结束,我们开始上板验证
在quartus的Pin planner 中进行引脚绑定

在这里插入图片描述

然后进行全编译,待到全编译通过后,连接好开发板,电源线和下载都要连接好,然后打开电源

在这里插入图片描述

下载编程文件

在这里插入图片描述

如果是第一次使用开发板的童鞋,参看这里更新驱动,切记,前提条件是开发板正确和PC连接,并且已经通电!!!
驱动更新成功后,点击“Start”进行编程,右上角的Progress为下载进度,成功后会有“100% Successful”提示字样,然后在开发板上可以看到相应的效果——流水灯。
在这里插入图片描述

4、总结

到这里基本上就结束了,给大家提几点在学习过程中可能会出现的错误
	1、我们的文件名和Module后面的模块名要保持一致,不然在仿真的时候会找不到文件的
	2、文件编写过程中,除开注释部分,其他的全部使用英文输入法编辑,如果在代码部分出现了中文也会报错
	3、reg信号只能在always进程中被赋值,wire型信号只能被assign赋值
	...
然后大家可以在提供的基础代码上进行创新,比如:
	1、实现流水灯的速率改变,提速或降速
	2、流水的方式改变,实现从左至右,然后再从右至左,循环往复
  • 50
    点赞
  • 379
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值