基于FPGA的LED跑马灯实现

led呼吸灯

mistake:
1.modelsim仿真的时候,计数器的最大值不能设计太大(跑十几分钟都跑不出来),可以将计数器的最大值调小(或者调整时钟周期),得到波形图,只要波形图在逻辑上是自己想要的波形,上板子的时候再将最大值换回来是一样的。
2.在always快里面赋值的数据都定义成 reg类型,wire一般是 assign in_i=in;
3.两个if连在一起编译会报错

note:
1.一个always快里面尽量只对一个数据赋值,对4个led灯赋值用4段来写
2.能够分离出来的模块一定分离出来,这样逻辑很清楚,不管是自己写还是后面的调试改错都会有好处
3.学会调适程序,用波形图来分析,分析出到底是哪一个信号出了问题导致波形不对,然后再返回源码查看自己的逻辑,这是最重要的

point:
设计思想:
1.单个led灯:led灯闪烁的过程用三段状态机描述,画出状态转移图,时间的控制用计数器完成,计数器的计数与状态机的状态转移联系起来(如:if(state==S1) count<=count+1’b1;)(同时计数器有两种设计方式,直接设计一个带输出使能信号的计数器,或者直接在第二段状态机中判断计数有没有达到最后计数值减一),这样逻辑很清楚。
2.多个led灯循环:用一个计数器控制(4个灯,位宽设置为2就可以,00是led1工作,01是led2工作,10是led3工作,11 是led4工作,只有当当前模式为第二次熄灭且这个计数1s的计数器的计数满了的时候,这个计数器才能开始计数)
3.按键设计:刚开始是IDLE模式,只有检测到key1的下降沿才会改变改变(按键key1是按下为低电平 从开发板的原理图看),对key2按键的检测用的是电平检测(代码是If(!key2) 按下是为低电平,所以要取反)

分割线-------------------------------------------------------------------------------------------------------

具体实验
1.基本要求描述:FPGA开发板上电复位后,按键key1按下,四颗led实现循环实现(亮0.1s—灭0.5s—亮0.1s—灭1s),按键key2按下时呼吸灯停止工作,如果这时key1灯再次按下,呼吸灯又从第一个led开始循环闪烁工作。
2.rsc
module heart(clk,Rst_n,key1,key2,led1,led2,led3,led4);
input clk;
input Rst_n;
input key1;
input key2;

output reg led1;
output reg led2;
output reg led3;
output reg led4;

reg [5:0]current_state;
reg [5:0]next_state;

reg out;

reg [27:0]count1;
reg [27:0]count2;
reg [27:0]count3;

parameter SUM1=5000_000 ;
parameter SUM2=25000_00 ;
parameter SUM3=50_000_000;

parameter IDLE=6’b000001,
LIGHT1=6’b000010,
DOWN1=6’b000100,
LIGHT2=6’b001000,
DOWN2=6’b010000,
CHECK=6’b100000;
//计数器与状态机相关联
//0.1s
always@(posedge clk or negedge Rst_n)
if(!Rst_n)
count1<=28’b0;
else if(current_stateLIGHT1 || current_stateLIGHT2 )
count1<=count1+1’b1;
else
count1<=28’b0;
//0.5
always@(posedge clk or negedge Rst_n)
if(!Rst_n)
count2<=28’b0;
else if(current_stateDOWN1 )
count2<=count2+1’b1;
else
count2<=28’b0;
//1
always@(posedge clk or negedge Rst_n)
if(!Rst_n)
count3<=28’b0;
else if(current_state
DOWN2)
count3<=count3+1’b1;
else
count3<=28’b0;

wire key1pos;
reg key1_n;
always@(posedge clk or negedge Rst_n)
if(!Rst_n)
key1_n<=1’b0;
else
key1_n<=key1;

assign key1pos=~key1&(key1_n);

always@(posedge clk or negedge Rst_n)
if(!Rst_n)
current_state<=IDLE;
else
current_state<=next_state;

always@(*)
if(!Rst_n)begin
next_state=IDLE;
end
else
case(current_state)
IDLE: if(key1pos)
next_state=LIGHT1;
else
next_state=IDLE;
LIGHT1: if(count1SUM1-1’b1)
next_state= DOWN1;
else
next_state=LIGHT1;
DOWN1: if(count2
SUM2-1’b1)
next_state=LIGHT2;
else
next_state=DOWN1;
LIGHT2: if(count1SUM1-1’b1)
next_state=DOWN2;
else
next_state=LIGHT2;
DOWN2: if(count3
SUM3-1’b1)
next_state=CHECK;
else
next_state=DOWN2;
CHECK: if(~key2)//电平检测
next_state=IDLE;
else
next_state=LIGHT1;

default: ;
endcase

always@(posedge clk or negedge Rst_n)
if(!Rst_n)
out<=1’b0;
else
case(next_state)
IDLE: out<=1’b0;
LIGHT1: out<=1’b1;
DOWN1: out<=1’b0;
LIGHT2: out<=1’b1;
DOWN2: out<=1’b0;
default : out<=1’b0;
endcase

reg [1:0]cnt;
always@(posedge clk or negedge Rst_n)
if(!Rst_n)
cnt<=2’b0;//改成curretn_state
else if(current_stateDOWN2 && count3SUM3-1’b1)begin
if(cnt == 2’d3)
cnt<=2’b0;
else
cnt<=cnt+1’b1;
end

always@(posedge clk or negedge Rst_n)
if(!Rst_n)
led1<=1’b0;
else if(cnt==2’b00)
led1<=out;
else
led1<=1’b0;

always@(posedge clk or negedge Rst_n)
if(!Rst_n)
led2<=1’b0;
else if(cnt==2’b01)
led2<=out;
else
led2<=1’b0;

always@(posedge clk or negedge Rst_n)
if(!Rst_n)
led3<=1’b0;
else if(cnt==2’b10)
led3<=out;
else
led3<=1’b0;

always@(posedge clk or negedge Rst_n)
if(!Rst_n)
led4<=1’b0;
else if(cnt==2’b11)
led4<=out;
else
led4<=1’b0;

endmodule
3. 仿真波形图(为了能跑出图形 ,改了计数器最大值)
图中能看到led1 led2 led3 led4 4个灯的亮灭波形转转逻辑图是对的
在这里插入图片描述
4.板子上的效果
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/jiyishizhe/article/details/97565341
今日推荐