【原创】基于FPGA的数码管的动态显示--ILOVEFPGA--动态流水般飘过

一:背景介绍

很早之前就已经写过数码管的动态显示,此处暂且不谈静态显示。

第一个写的是:2个数码管,显示 固定的字符AF;

第二个写的是:2个数码管,显示 动态的字符00~FF,逐次递增加1;

第三个写的是:6个数码管,显示 动态的字符000000~FFFFFF,逐次递增加1;


最近写的是:   6个数码管,显示 动态的“ILOVEFPGA”,字符需要如流水表飘过,不要有明显抖动和停顿;

很是汗颜,我之前画的图是错的,导致 了我编写的程序也出现了问题。


二:思路解析

错误思路1:

01)片选第1个数码管

02)片选第2个数码管,同时片选第1个数码管;

03)片选第3个数码管,同时片选第2个数码管,片选第1个数码管;

.......

06)片选第6个数码管,同时片选第5个数码管,------,片选第1个数码管;

07)当数码管的数值在500ms时变化一次,片选值也是在500ms处变化一次;

这样就可以营造一个显示:数码管是第1位显示,然后第2位和第1位显示,......,然后第6位显示,第5位显示,......,第1位显示。

最后,所有的片选都持续的选中对应的数码管,如此就能达到流水般飘过,并且还不会明显抖动和停顿;想法是好的,但是现实是悲剧的;:显示的结果是:乱成一锅粥;

2017-04-16 补充:

1:可能是因为数值的变化率和片选变化率相同;

2:记住核心一点:每时每刻,只有一个数码管是被选中的;


错误思路2:

01)片选第1个数码管

02)片选第2个数码管,同时片选第1个数码管;

03)片选第3个数码管,同时片选第2个数码管,片选第1个数码管;

.......

06)片选第6个数码管,同时片选第5个数码管,------,片选第1个数码管;

07)当数码管的数值在600ms时变化一次,片选值在100ms处变化一次;

将段值和片值的时间进行搭配;如此就可以6个数码管都有一位数值显示

这样就可以营造一个显示:数码管是第6位显示,然后第5位,......,然后第1位显示。最后,所有的片选都轮流的选中对应的数码管,如此字符就会像 流水般飘过,并且还不会明显抖动和停顿;想法是好的,但是现实 并非是你想要的;

显示的结果是:有明显的停顿感;

2016-04-17 补充:

1:数值变化率差不多,有600ms还是可以的;

2:片选变化率 和 数值变化率相差的越小,显示的停顿感越强烈,看起来不连续,就好像是一个一个显示的那样;

3:记住核心一点:每时每刻,只有一个数码管是被选中的;


正确思路:

数码管的数值,默认为 0;

6个片选端,依次被选中,记住,每次只有1个数码管是被选中的,

片选6次为一轮循环,在该轮循环中,所有的数码管都被选中过

当循环m轮后,数码管的数值变化一次;如此为一个大循环;

大循环 循环往复的运行;

(当数码管的数值在720ms时变化一次,片选值在6ms处变化一次;(720 / 6=120))

所有的片选都轮流的选中对应的数码管,如此字符就会像 流水般飘过,并且还不会明显抖动和停顿;

显示的结果是:  效果明显,是我想要的结果,符合预设目标;


三:程序展示

module seg_6(
input wiresclk,
input wires_rst_n,

output reg[7:0] seg_mem,
output reg[5:0] sel_mem
);


//parameter
parameter CNT_10MS=19'd10_000;   //切换速率(刷新率)
parameter CNT_60MS=23'd8_300_000; //数据变化率

//变量定义
reg [18:0]slew_rate_cnt;
reg slew_rate_flag;
reg [22:0]change_cnt;
reg change_cnt_flag;
reg [4:0]static_cnt0;
reg [4:0]static_cnt1;
reg [4:0]static_cnt2;
reg [4:0]static_cnt3;
reg [4:0]static_cnt4;
reg [4:0]static_cnt5;
reg [4:0]disp_data;

//===============刷新率模块===============//
//slew_rate_cnt
//功能:计数;
always@(posedgesclk or negedges_rst_n)
if(!s_rst_n)
slew_rate_cnt<=19'd0;
else if(slew_rate_cnt==CNT_10MS)
slew_rate_cnt<=19'd0;
else
slew_rate_cnt<=slew_rate_cnt+1'b1;


//slew_rate_flag
always@(posedgesclk or negedges_rst_n)
if(!s_rst_n)
slew_rate_flag<=1'b0;
else if(slew_rate_cnt==CNT_10MS)
slew_rate_flag<=1'b1;
else
slew_rate_flag<=1'b0;

//sel_mem
//功能:切换数码管
always@(posedgesclk or negedges_rst_n)
if(!s_rst_n)
sel_mem<=6'b11_1110;
else if(slew_rate_flag)
sel_mem<={sel_mem[4:0],sel_mem[5]};
else
sel_mem<=sel_mem;

//================显示模块================//
//change_cnt
always@(posedgesclk or negedges_rst_n)
if(!s_rst_n)
change_cnt<=23'd0;
else if(change_cnt==CNT_60MS)
change_cnt<=23'd0;
else
change_cnt<=change_cnt+1'b1;

//change_cnt_flag
always@(posedgesclk or negedges_rst_n)
if(!s_rst_n)
change_cnt_flag<=1'b0;
else if(change_cnt==CNT_60MS)
change_cnt_flag<=1'b1;
else
change_cnt_flag<=1'b0;

//static_cnt0
//功能:默认状态计数
always@(posedgesclk or negedges_rst_n)
if(!s_rst_n)
static_cnt0<=5'd11;
else if((static_cnt0==5'd16)&&(change_cnt_flag))
static_cnt0<=5'd0;
else if(change_cnt_flag)
static_cnt0<=static_cnt0+1'b1;
else
static_cnt0<=static_cnt0;


//static_cnt1
//功能:默认状态计数
always@(posedgesclk or negedges_rst_n)
if(!s_rst_n)
static_cnt1<=5'd12;
else if((static_cnt1==5'd16)&&(change_cnt_flag))
static_cnt1<=5'd0;
else if(change_cnt_flag)
static_cnt1<=static_cnt1+1'b1;
else
static_cnt1<=static_cnt1;

//static_cnt2
//功能:默认状态计数
always@(posedgesclk or negedges_rst_n)
if(!s_rst_n)
static_cnt2<=5'd13;
else if((static_cnt2==5'd16)&&(change_cnt_flag))
static_cnt2<=5'd0;
else if(change_cnt_flag)
static_cnt2<=static_cnt2+1'b1;
else
static_cnt2<=static_cnt2;

//static_cnt3
//功能:默认状态计数
always@(posedgesclk or negedges_rst_n)
if(!s_rst_n)
static_cnt3<=5'd14;
else if((static_cnt3==5'd16)&&(change_cnt_flag))
static_cnt3<=5'd0;
else if(change_cnt_flag)
static_cnt3<=static_cnt3+1'b1;
else
static_cnt3<=static_cnt3;


//static_cnt4
//功能:默认状态计数
always@(posedgesclk or negedges_rst_n)
if(!s_rst_n)
static_cnt4<=5'd15;
else if((static_cnt4==5'd16)&&(change_cnt_flag))
static_cnt4<=5'd0;
else if(change_cnt_flag)
static_cnt4<=static_cnt4+1'b1;
else
static_cnt4<=static_cnt4;

//static_cnt5
//功能:默认状态计数
always@(posedgesclk or negedges_rst_n)
if(!s_rst_n)
static_cnt5<=5'd16;
else if((static_cnt5==5'd16)&&(change_cnt_flag))
static_cnt5<=5'd0;
else if(change_cnt_flag)
static_cnt5<=static_cnt5+1'b1;
else
static_cnt5<=static_cnt5;

//disp_data
always@(posedgesclk or negedges_rst_n)
if(!s_rst_n)
disp_data<=5'd0;
else if(sel_mem[0]==1'b0)
disp_data<=static_cnt0;
else if(sel_mem[1]==1'b0)
disp_data<=static_cnt1;
else if(sel_mem[2]==1'b0)
disp_data<=static_cnt2;
else if(sel_mem[3]==1'b0)
disp_data<=static_cnt3;
else if(sel_mem[4]==1'b0)
disp_data<=static_cnt4;
else if(sel_mem[5]==1'b0)
disp_data<=static_cnt5;


//seg_mem
//功能:显示的数据
//我也是醉了,按照C语言的思维写了;
//case语句一般用在FSM中,其余时间很少用;多用用的;
always@(posedgesclk or negedges_rst_n)
if(!s_rst_n)
seg_mem<=8'hff;
else case(disp_data)
5'd0:seg_mem<=8'h7f;//空格
5'd1: seg_mem<=8'h7f;
5'd2: seg_mem<=8'h7f;
5'd3: seg_mem<=8'h7f;
5'd4: seg_mem<=8'h7f;
5'd5: seg_mem<=8'h7f;
5'd6: seg_mem<=8'hc0;//I
5'd7: seg_mem<=8'hf9;//_
5'd8: seg_mem<=8'ha4;//L
5'd9: seg_mem<=8'hb0;//O
5'd10:seg_mem<=8'h99;//V
5'd11:seg_mem<=8'h92;//E
5'd12:seg_mem<=8'h82;//_
5'd13:seg_mem<=8'hf8;//F
5'd14:seg_mem<=8'h80;//P
5'd15:seg_mem<=8'h90;//G
5'd16:seg_mem<=8'h08;//A
default:
seg_mem<=8'h7f;
endcase


endmodule

你可能感兴趣的:(FPGA基础篇)