赞
踩
实现8个LED灯依次点亮,每100ms点亮1个,直到8个LED灯被全部点亮,然后全部熄灭,再依次点亮。
LED灯简介
LED,又名发光二极管。 LED灯工作电流很小(有的仅零点几毫安即可发光) , 抗 冲击和抗震性能好,可靠性高,寿命长。由于这些优点, LED灯被广泛用在仪器仪表 中作指示灯、 液晶屏背光源等诸多领域。不同材料的发光二极管可以发出红、 橙、 黄、 绿、 青、蓝、 紫、白这八种颜色的光。 如下图所示:
发光二极管的原理图如上图4所示, LED1到LED8这8个发光二极管的阳 极都连到3.3V上, 阴极分别与FPGA相应的管脚相连。原理图中LED与地 之间的电阻起到限流作用。通过原理图我们可以看出,LED1与FPGA的管脚 L12相连。在PCB图或实物上我们都标注出了管脚号,所以在绑管脚的时候 可以不用看原理图,直接看板上的丝印就可以,如上图PCB图所示。我们只 点亮一个LED灯(LED1),那我们只用关心LED1的管脚号(L12)。当管脚L12 输出低电平时,LED灯便有电流流过,驱动LED灯发光,如果L12输出高电 平,LED灯没有电流流过,LED不发光。
信号名 | 方向 | FPGA管脚号 | 说明 |
---|---|---|---|
CLK50M | 输入 | B10 | 时钟信号,50MHZ |
KEY1 | 输入 | E4 | 独立按键,按下低电平,当作复位使用 |
LED1 | 输出 | L12 | 与LED灯相连,低电平LED灯亮 |
LED2 | 输出 | T13 | 与LED灯相连,低电平LED灯亮 |
LED3 | 输出 | R12 | 与LED灯相连,低电平LED灯亮 |
LED4 | 输出 | T12 | 与LED灯相连,低电平LED灯亮 |
LED5 | 输出 | P11 | 与LED灯相连,低电平LED灯亮 |
LED6 | 输出 | J11 | 与LED灯相连,低电平LED灯亮 |
LED7 | 输出 | K11 | 与LED灯相连,低电平LED灯亮 |
LED8 | 输出 | G11 | 与LED灯相连,低电平LED灯亮 |
总结:通过上述说明,可以将需求解读成,先点亮LED1(100ms),接着点亮LED2(100ms)…最后点亮LED8,然后全部熄灭。再重复上述操作。
为了让工程看起来整洁,同时方便工程移植。我们新建4个文件夹,分别是Project,Source,Sim,Doc。
Project — 工程文件夹,里面放的TD工程
Source — 源代码文件夹,里面放的工程源码(.v文件或.vhd文件)
Sim — 仿真文件夹,里面放的仿真相关的文件
Doc — 存放相关资料,比如数据手册,需求文档等
/// //QQ:3181961725 //TEL/WX:13540738439 //作者:Mr Wang //模块介绍:实现LED流水灯 /// module led_flow( input rst_n ,//复位信号,低电平有效 input clk ,//时钟信号,50MHZ output reg [7:0] led //LED灯控制信号 ); parameter time_100ms=5000000;//100mS //parameter time_100ms=2500; parameter IDLE =4'd0;//初始状态 parameter S0 =4'd1;//点亮第1个LED灯 parameter S1 =4'd2;//点亮第1.2两个LED灯 parameter S2 =4'd3;//点亮第1.2.3三个LED灯 parameter S3 =4'd4;//点亮第1.2.3.4四个LED灯 parameter S4 =4'd5;//点亮第1.2.3.4.5四个LED灯 parameter S5 =4'd6;//点亮第1.2.3.4.5.6四个LED灯 parameter S6 =4'd7;//点亮第1.2.3.4.5.6.7四个LED灯 parameter S7 =4'd8;//点亮第1.2.3.4.5.6.7.8四个LED灯 parameter S8 =4'd9;//LED灯全部熄灭 reg [3:0] curr_st; reg [24:0] led0_cnt,led1_cnt,led2_cnt,led3_cnt; reg [24:0] led4_cnt,led5_cnt,led6_cnt,led7_cnt; reg [24:0] all_off_cnt; //状态机跳转 always@(posedge clk or negedge rst_n)begin if(!rst_n) curr_st<=IDLE; else case(curr_st) IDLE:curr_st<=S0; S0:begin if(led0_cnt==time_100ms-1)//当led0_cnt等于time_500ms-1时,跳转到S1状态 curr_st<=S1; else; end S1:begin if(led1_cnt==time_100ms-1) curr_st<=S2; else; end S2:begin if(led2_cnt==time_100ms-1) curr_st<=S3; else; end S3:begin if(led3_cnt==time_100ms-1) curr_st<=S4; else; end S4:begin if(led4_cnt==time_100ms-1) curr_st<=S5; else; end S5:begin if(led5_cnt==time_100ms-1) curr_st<=S6; else; end S6:begin if(led6_cnt==time_100ms-1) curr_st<=S7; else; end S7:begin if(led7_cnt==time_100ms-1) curr_st<=S8; else; end S8:begin if(all_off_cnt==time_100ms-1) curr_st<=S0; else; end default:; endcase end //led0_cnt计数寄存器 always@(posedge clk or negedge rst_n)begin if(!rst_n) led0_cnt<=0; else if(curr_st==S0) led0_cnt<=led0_cnt+1; else led0_cnt<=0; end //led1_cnt计数寄存器 always@(posedge clk or negedge rst_n)begin if(!rst_n) led1_cnt<=0; else if(curr_st==S1) led1_cnt<=led1_cnt+1; else led1_cnt<=0; end //led2_cnt计数寄存器 always@(posedge clk or negedge rst_n)begin if(!rst_n) led2_cnt<=0; else if(curr_st==S2) led2_cnt<=led2_cnt+1; else led2_cnt<=0; end always@(posedge clk or negedge rst_n)begin if(!rst_n) led3_cnt<=0; else if(curr_st==S3) led3_cnt<=led3_cnt+1; else led3_cnt<=0; end always@(posedge clk or negedge rst_n)begin if(!rst_n) led4_cnt<=0; else if(curr_st==S4) led4_cnt<=led4_cnt+1; else led4_cnt<=0; end always@(posedge clk or negedge rst_n)begin if(!rst_n) led5_cnt<=0; else if(curr_st==S5) led5_cnt<=led5_cnt+1; else led5_cnt<=0; end always@(posedge clk or negedge rst_n)begin if(!rst_n) led6_cnt<=0; else if(curr_st==S6) led6_cnt<=led6_cnt+1; else led6_cnt<=0; end always@(posedge clk or negedge rst_n)begin if(!rst_n) led7_cnt<=0; else if(curr_st==S7) led7_cnt<=led7_cnt+1; else led7_cnt<=0; end always@(posedge clk or negedge rst_n)begin if(!rst_n) all_off_cnt<=0; else if(curr_st==S8) all_off_cnt<=all_off_cnt+1; else all_off_cnt<=0; end //LED灯接口赋值操作 always@(posedge clk or negedge rst_n)begin if(!rst_n) led<=8'hff; else case(curr_st) IDLE :led<=8'hff; S0 :led<=8'hfe; S1 :led<=8'hfc; S2 :led<=8'hf8; S3 :led<=8'hf0; S4 :led<=8'he0; S5 :led<=8'hc0; S6 :led<=8'h80; S7 :led<=8'h00; S8 :led<=8'hff; default:; endcase end endmodule
`timescale 1ns/1ns module led_flow_tb; reg rst_n; reg clk ; initial begin clk=0; rst_n=0;//产生复位激励信号 #1000 rst_n=1;//产生复位激励信号 end //产生时钟激励信号 always #10 clk<=~clk; //例化被仿真模块 led_flow Uled_flow( .rst_n (rst_n), .clk (clk), .led () ); endmodule
Modelsim仿真一般有两种方法
图形化界面仿真,即所有的操作都是在Modelsim软件界面上来完成,该方式的优点是,简单易学,适用于简单的项目,缺点是操作步骤繁琐。
批处理仿真,这种方式在仿真前需要编写相应的脚本文件,该方式的优点是,一键即可完成仿真,省时省力,缺点是前期需要编写脚本文件。前两讲采用的是图形化界面仿真的方式;为了更贴近工程实际,从这一讲开始,我们就采用批处理方式仿真。具体操作步骤可参考我们的视频教程
仿真出的波形如下图所示:
将第二步绘制的理论波形图与第六步Modelsim仿真出来的波形图进行对比,结果一致,说明我们的逻辑设计是正确的。如果发现比对结果不一致,就需要找到不一致的原因,最终要保证对比结果一致。通过对比,理论波形与仿真波形一致,说明功能符合设计要求。
下载成功后,便可以观察到开发板上的实验现象,如果实验现象与设计需求相符,那说明我们的设计是没有问题的,即可进行下一步固化配置文件。
FPGA有一个特性,就是掉电后配置信息会丢失,所以我们需要将配置信息存储在配置芯片(FLASH)中,待开发板上电后,FPGA便会读取配置芯片中的配置信息,这样开发板掉电再上电后同样可正常工作
固化成功后,开发板断电再重新上电,可以观察到开发板仍然可以执行刚刚的功能。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。