北邮数电实验报告双色点阵.docx

上传人:b****4 文档编号:3497967 上传时间:2022-11-23 格式:DOCX 页数:27 大小:684.52KB
下载 相关 举报
北邮数电实验报告双色点阵.docx_第1页
第1页 / 共27页
北邮数电实验报告双色点阵.docx_第2页
第2页 / 共27页
北邮数电实验报告双色点阵.docx_第3页
第3页 / 共27页
北邮数电实验报告双色点阵.docx_第4页
第4页 / 共27页
北邮数电实验报告双色点阵.docx_第5页
第5页 / 共27页
点击查看更多>>
下载资源
资源描述

北邮数电实验报告双色点阵.docx

《北邮数电实验报告双色点阵.docx》由会员分享,可在线阅读,更多相关《北邮数电实验报告双色点阵.docx(27页珍藏版)》请在冰豆网上搜索。

北邮数电实验报告双色点阵.docx

北邮数电实验报告双色点阵

北京邮电大学

数电综合实验报告

 

实验名称:

双色点阵显示控制器

 

学院:

姓名:

班级:

学号:

班内序号:

一.设计课题的任务要求

用8×8点阵设计双色点阵显示控制器

基本要求:

1、固定红色显示一个汉字或图形,显示亮度4级可调,用一个btn按钮实现亮度调节,亮度变化视觉效果要尽量明显。

2、用从红到绿8级渐变色显示一个固定汉字或图形。

3、分别用单字循环显示、左右滚动显示、上下滚动显示三种显示方式单色显示四个汉字或图形,显示过程中,显示方式用一个btn按键进行切换。

4、显示的图形或汉字要尽量饱满美观。

提高要求:

滚动显示过程中实现四种显示颜色的自动变换,颜色变化视觉效果要尽量明显。

自拟其它功能。

二.系统设计

1.设计思路

考虑本程序设计要求模块明确单一但需要变化多种状态,因此采用单模块多状态多进程方式实现。

其中防抖进程用于检测输入,本程序使用BTN按键进行输入控制,而按键的键入可能由于抖动产生多个上升沿,对程序的控制产生影响。

防抖动采用了延时原理来对冒险或长时间按键电平进行处理。

分频使用了多个进程产生程序所需要的多个时钟频率。

包括:

clk1(扫描时钟大于480Hz但不过高)

clk2(占空比调节1clk1周期的整数倍,但不过高)

clk3(占空比调节2同clk2,但占空比不同)

clk4(占空比调节3同clk2,但占空比不同)

clk5(按键时钟约100Hz)

clk6(滚动变化计时约1Hz)

状态机变化进程用于管理状态变化,当遇到按键电平信号时根据规则改变对应状态。

显示进程包括主要显示进程和一些辅助进程,辅助进程完成了时钟对应计数器计数,主进程则根据状态变化显示不同显示模式下不同的图案。

2.总体框图

(1)

总体结构框图:

(2)逻辑划分框图

 

Mode

 

P

 

pPMode

 

PMode

 

Mode

 

P

P

 

P

 

(3)MDS图

P=1

Mode=1

Mode=1

Mode=1reset

Mode=1

P=1

 

3.各进程介绍

1分频进程们

分频进程含一个从50M(也可能是25M)分出的扫描频率clk1,这个频率要大于60*8=480Hz(因为人眼分辨频率为60Hz左右,要保证每排扫描时达到60Hz则需480Hz)。

然后以clk1为基准频率,将clk2、clk3、clk4以clk1的8倍数作占空比调整。

具体是,clk2、clk3、clk4均记为clk1的48分频,然后占空比调为32:

16,24:

24,16:

32

做8倍数的原因是为了保证至少每扫完一屏才有一次占空比调整,否则在主频率不足情况下可能有些排暗有些排亮(详见问题分析)

最后再将周期约为100ms的按键时钟clk5和周期为1s的滚动时钟clk6分出就可以了。

2状态机进程

没什么可说的,我写的是单进程状态机,防止了多进程状态机可能带来的冒险。

敏感量直接写的是防抖动输出的信号,本以为没必要加同步时序,但事实证明这是有问题的。

(详见代码分析)

3防抖动进程

防抖动我用的是老师给的代码。

先阐述一下原理:

按键输入电平做敏感量,将输入赋值给resetmp1。

resetmp1被赋值后,将这段值有时延的赋值给resetmp2,并利用这段时间去判断是否按键仍为1。

则面对下面两种情况下防抖程序可以做出调整

A.突然翘起的冒险:

此种情况下若r1得到赋值,则r2在下一个时钟沿得到赋值,但由于此时r1电平为低,不能判断成功

B.长时间按下:

此种情况下r1得到赋值,在赋值给r2的间歇判断正确,而后r2得到赋值后不再有效,因此输出仅有一个按键时钟高电平

 

Clk

In_signal

Resetmp1

Resetmp2

Out_signal

但在使用该进程的过程中遇到了问题,具体见问题分析。

(4)显示进程

首先说一下点阵显示的原理:

如下图所示,列高电平有效,行低电平有效,当对应高电平和低电平时中间的灯就亮了。

而不同颜色则是由不同亮度的红色灯和绿色灯光混合而成。

由于都是整排显示,为了达到整屏显示效果,需要每排进行扫描,当扫描频率较高时人眼无法分辨则可达到整屏显示。

数码管原理类似,这里不再赘述。

接着说一下亮度调节:

前面已经说过时钟分频的问题,在显示每排前对占空比时钟进行判断,则有些情况会亮,有些情况会灭,这样就能很好的形成明暗效果。

最后说一下滚动:

滚动我是用最笨的方法实现的,即一屏一屏的画出每屏图案。

当时我是觉得可能循环之类的不太好实现,不过有同学使用了循环减少了代码量,我觉得以后很值得借鉴。

三.仿真波形及分析

1、防抖动波形的测试

这两张张图中,mode为输入,并设置了很多毛刺作为干扰电平,可以从图中看出多个干扰电平出现时仅输出一个周期的高电平。

那为什么仅有毛刺时也会有输出呢?

因为毛刺刚好位于clk5的下降沿,这样的话也会造成程序误判一次输出(这也是这个防抖动程序的不足之处)。

而连续多次下降沿毛刺造成的结果却是r1连续两个周期(其实是一个半)的高电平,同步电路就是这样一个特点。

当仅有冒险且冒险未在clk5边沿时,则不会触发电平。

如下图所示

关于同步电路问题的下一步讨论(包含同步时钟选用的问题)放在问题分析部分。

2、显示波形测试

从图中可以看出当Mode改变后red_out开始有波形出现,这说明模式已经从m0转变为m1_p1

改变p后,则有:

Clk2为0时则red输出为0,这时就有了亮度的变化。

其它亮度变化以此类推,这里不再赘述。

以上波形显示了最重要的状态变化过程,状态变化后按该状态显示内容显示,只要状态机能正常工作,仿真的任务就基本完成。

 

四、源代码解析

(由于源程序后半部分属于机械重复,因此省略)

(这里按50M时钟输入写)

LibraryIEEE;

USEIEEE.STD_LOGIC_1164.All;

ENTITYscIS

PORT(

clk,mode,p,reset:

INSTD_LOGIC;--reset用于复位到m0

red_out,green_out:

OUTstd_logic_vector(7downto0):

="00000000";

row_out:

OUTstd_logic_vector(7downto0):

="11111111";

num_out:

OUTstd_logic_vector(7downto0):

="00000000";--用于数码管输出

num_choose:

Outstd_logic_vector(5downto0):

="111110");--用于选择数码管

ENDsc;

architectureaofscis

TYPEstate_typeIS(m0,m1_p1,m1_p2,m1_p3,m1_p4,m2,m3_p1,m3_p2,m3_p3);

signalmode_mp1,mode_mp2,mode_out:

STD_logic;--防抖动临时信号(下同)

signalp_mp1,p_mp2,p_out:

STD_logic;

signalclk1,clk2,clk3,clk4,clk5,clk6:

STD_logic;

signaltmp1:

IntegerRange0To1000000:

=0;

signaltmp2:

IntegerRange0To200000:

=0;

signaltmp3:

IntegerRange0To50000000:

=0;

signaltmp4:

IntegerRange0To30:

=0;

signaltmp5:

IntegerRange0To30:

=0;

signalcount:

IntegerRange0To8:

=0;

signalcount_2:

IntegerRange0To4:

=0;

signalcount_3:

IntegerRange0To32:

=0;

signalclk_tmp:

STD_logic;

signalstate:

state_type;

signalred,green:

std_logic_vector(7downto0):

="00000000";

signalrow:

std_logic_vector(7downto0):

="11111110";

Begin

p1_1:

Process(clk)

Begin

if(clk'eventANDclk='1')then

iftmp1=50000then

tmp1<=0;

else

tmp1<=tmp1+1;

endif;

iftmp1<25000then

clk1<='1';

else

clk1<='0';

endif;

endif;

endprocessp1_1;

p1_2:

Process(clk)

Begin

if(clk'eventANDclk='1')then

iftmp2=500000then

tmp2<=0;

else

tmp2<=tmp2+1;

endif;

iftmp2<250000then

clk5<='1';

else

clk5<='0';

endif;

endif;

endprocessp1_2;

p1_3:

Process(clk)

Begin

if(clk'eventANDclk='1')then

iftmp3=50000000then

tmp3<=0;

else

tmp3<=tmp3+1;

endif;

iftmp3<25000000then

clk6<='1';

else

clk6<='0';

endif;

endif;

endprocessp1_3;

p1_4:

Process(clk1)

Begin

if(clk1'eventANDclk1='1')then

iftmp4=31then

tmp4<=0;

else

tmp4<=tmp4+1;

endif;

iftmp4<24then

clk2<='1';

else

clk2<='0';

endif;

iftmp4<8then

clk4<='1';

else

clk4<='0';

endif;

endif;

endprocessp1_4;

p1_5:

Process(clk1)

Begin

if(clk1'eventANDclk1='1')then

iftmp5=15then

tmp5<=0;

else

tmp5<=tmp5+1;

endif;

iftmp5<8then

clk3<='1';

else

clk3<='0';

endif;

endif;

endprocessp1_5;

小结:

上面几个分频进程分出了程序所需的6个频率

p2:

Process(clk5)

Begin

if(clk5'eventANDclk5='0')then

mode_mp2<=mode_mp1;--延迟一个周期赋值

mode_mp1<=mode;

p_mp2<=p_mp1;

p_mp1<=p;

endif;

endProcessp2;

p2_out:

Process(clk1)--这里单独拿出一个进程用于赋值

Begin

if(clk1'eventandclk1='1')then

mode_out<=clk5andmode_mp1and(notmode_mp2);

p_out<=clk5andp_mp1and(notp_mp2);

endif;

endProcessp2_out;

小结:

上述两个进程完成了防抖动功能,和老师给的代码不同的地方在于单独拿出了一个进程用于与操作,原因在于这里的输出值依旧是signal变量,必须在进程内赋值才能在仿真时显示出来。

(否则会被优化掉!

第二个问题就是为什么赋值进程敏感量使用了clk1?

其实这里使用什么时钟作为同步时钟并不重要,重要的在于这个时钟周期必须小于clk5周期的一半。

为什么呢?

因为防抖动的输出仅为clk5的高电平,必须要在这一时刻得到同步时钟沿。

那为什么不就用clk5呢?

因为使用clk5则得到的有效电平长度为clk5整个周期,相当于不具备了防止冒险的作用,影响防抖动进程。

p3:

Process(p_out,mode_out,reset)

Begin

if(clk5'eventandclk5='0')then

CasestateIs

whenm0=>if(mode_out='1')thenstate<=m1_p1;

endif;

whenm1_p1=>if(p_out='1')thenstate<=m1_p2;

elsif(mode_out='1')thenstate<=m2;

elsifreset='1'thenstate<=m0;

elsestate<=m1_p1;

endif;

whenm1_p2=>if(p_out='1')thenstate<=m1_p3;

elsif(mode_out='1')thenstate<=m2;

elsifreset='1'thenstate<=m0;

elsestate<=m1_p2;

endif;

whenm1_p3=>if(p_out='1')thenstate<=m1_p4;

elsif(mode_out='1')thenstate<=m2;

elsifreset='1'thenstate<=m0;

elsestate<=m1_p3;

endif;

whenm1_p4=>if(p_out='1')thenstate<=m1_p1;

elsif(mode_out='1')thenstate<=m2;

elsifreset='1'thenstate<=m0;

elsestate<=m1_p4;

endif;

whenm2=>if(mode_out='1')thenstate<=m3_p1;

elsifreset='1'thenstate<=m0;

elsestate<=m2;

endif;

whenm3_p1=>if(p_out='1')thenstate<=m3_p2;

elsif(mode_out='1')thenstate<=m1_p1;

elsifreset='1'thenstate<=m0;

elsestate<=m3_p1;

endif;

whenm3_p2=>if(p_out='1')thenstate<=m3_p3;

elsif(mode_out='1')thenstate<=m1_p1;

elsifreset='1'thenstate<=m0;

elsestate<=m3_p2;

endif;

whenm3_p3=>if(p_out='1')thenstate<=m3_p1;

elsif(mode_out='1')thenstate<=m1_p1;

elsifreset='1'thenstate<=m0;

elsestate<=m3_p3;

endif;

EndCase;

endif;

EndProcessp3;

小结:

这一部分是状态机,值得一提的是状态机的同步时钟。

开始本以为没必要加的,结果不行,原因在于这是一个需要反复判断的进程,没有同步时钟系统是无法执行这些的。

时钟的选择上依旧采用了clk5。

值得一提的是选择时钟沿时一定选择下降沿。

因为在防抖动过程中当clk5高电平结束时则完成了防抖动信号的赋值,然而完成赋值是有一定延时的,这一延时过程中触发状态机,然后开始判断

p4_counter1:

Process(clk1)

Begin

if(clk1'eventandclk1='1')then

if(count=7)thencount<=0;

elsecount<=count+1;

endif;

endif;

endProcessp4_counter1;

p4_counter2:

Process(clk6)

Begin

if(clk6'eventandclk6='1')then

if(count_2=3)thencount_2<=0;

elsecount_2<=count_2+1;

endif;

if(count_3=31)thencount_3<=0;

elsecount_3<=count_3+1;

endif;

endif;

endProcessp4_counter2;

小结:

这里利用时钟计数来完成扫描,滚动等变化

p4:

Process(count,count_2,count_3)

Begin

CasestateIs

whenm0=>row<="11111111";red<="00000000";green<="00000000";num_out<="00000000";

whenm1_p1=>

--if(clk1='1')then

CasecountIs

when0=>row<="11111101";red<="01111110";green<="00000000";

when1=>row<="11111011";red<="00001000";green<="00000000";

when2=>row<="11110111";red<="00001000";green<="00000000";

when3=>row<="11101111";red<="00101110";green<="00000000";

when4=>row<="11011111";red<="00101000";green<="00000000";

when5=>row<="10111111";red<="11111111";green<="00000000";

when6=>row<="01111111";red<="00000000";green<="00000000";

when7=>row<="11111110";red<="00000000";green<="00000000";

whenothers=>row<="11111110";

EndCase;

num_out<="00000110";

--Endif;

whenm1_p2=>

if(clk2='1')then

CasecountIs

when0=>row<="11111101";red<="01111110";green<="00000000";

when1=>row<="11111011";red<="00001000";green<="00000000";

when2=>row<="11110111";red<="00001000";green<="00000000";

when3=>row<="11101111";red<="00101110";green<="00000000";

when4=>row<="11011111";red<="00101000";green<="00000000";

when5=>row<="10111111";red<="11111111";green<="00000000";

when6=>row<="01111111";red<="00000000";green<="00000000";

when7=>row<="11111110";red<="00000000";green<="00000000";

whenothers=>row<="11111110";

EndCase;

elsered<="00000000";

Endif;

num_out<="01011011";

whenm1_p3=>

if(clk3='1')then

CasecountIs

when0=>row<="11111101";red<="01111110";green<="00000000";

when1=>row<="11111011";red<="00001000";green<="00000000";

when2=>row<="11110111";red<="00001000";green<="00000000";

when3=>row<="11101111";red<="00101110";green<="00000000";

when4=>row<="11011111";red<="00101000";green<="00000000";

when5=>row<="10111111";red<="11111111";green<="00000000";

when6=>row<="

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 表格模板 > 合同协议

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1