1616LED点阵滚动显示.docx

上传人:b****5 文档编号:3861633 上传时间:2022-11-25 格式:DOCX 页数:35 大小:26.55KB
下载 相关 举报
1616LED点阵滚动显示.docx_第1页
第1页 / 共35页
1616LED点阵滚动显示.docx_第2页
第2页 / 共35页
1616LED点阵滚动显示.docx_第3页
第3页 / 共35页
1616LED点阵滚动显示.docx_第4页
第4页 / 共35页
1616LED点阵滚动显示.docx_第5页
第5页 / 共35页
点击查看更多>>
下载资源
资源描述

1616LED点阵滚动显示.docx

《1616LED点阵滚动显示.docx》由会员分享,可在线阅读,更多相关《1616LED点阵滚动显示.docx(35页珍藏版)》请在冰豆网上搜索。

1616LED点阵滚动显示.docx

1616LED点阵滚动显示

 

信息与通信工程学院

硬件描述语言课程设计

 

2018年4月

 

16*16LED点阵滚动显示

1设计要求

本设计主要实现16*16LED点阵的滚动显示。

可以滚动显示“硬件描述语言”这六个字。

同时通过两个按键进行方向控制,分别是模式切换键和方向切换键。

模式切换键可以进行上下方向和左右方向的模式切换。

方向切换键可以将向左滚动切换成向右滚动或者是向上切换成向下,向右切换成向左。

显示效果,无论汉字那个方向移动都是正面显示。

2方案设计

2.1系统设计框图

 

图2.1总体系统框图

本文整体设计如上图2.1所示,由按键控制模块,上线滚动显示模块和左右滚动显示模块这三部分组成。

按键控制模块实现对两个显示模块的控制,通过两个按键分别控制来实现汉字向左、向右、向上和向下四个方向的滚动显示。

当key_model按键为左右滚动显示模块工作,通过key_direction按键来控制向左、向右移动;反之上下滚动显示模块工作,通过key_direction按键来实现向上、向下移动。

下面针对这三个模块进行具体的说明。

2.2按键控制模块

这个模块主要实现按键的消抖功能。

机械按键触点在闭合、断开时,由于机械触点的弹性作用,一个按键开关在闭合时不会马上稳定地接通,在断开时也不会一下子断开。

因而在闭合及断开的瞬间均伴随有一连串的抖动,为了不产生这种现象而作的措施就是按键消抖。

机械按键的抖动时间一般为5~10ms。

按键抖动示意图如下所示:

 

图2.2按键抖动示意图

按键消抖的原理就是把按键按下过程和松开过程中的抖动现象过滤掉。

这里使用计数的方式来实现抖动过滤。

程序流程图如下所示:

 

图2.3按键程序流程图

部分关键程序:

always@(posedgeclk_1msornegedgereset_n)begin

if(!

reset_n)begin

k2<=1'b0;

key2<=1'b0;

state2<=2'b00;

key_conter2<=5'd0;

end

elsebegin

case(state2)

2'b00:

begin

state2<=2'b00;

if(key_conter2<5'd10)begin

if(!

key_model)begin

key_conter2<=key_conter2+5'd1;

end

elsekey_conter2<=5'd0;

end

elsebegin

state2<=2'b01;

key_conter2<=5'd0;

k2<=1'b1;

end

end

2'b01:

begin

k2<=1'b0;

if(key_conter2<5'd10)begin

if(key_model)begin

key_conter2<=key_conter2+5'd1;

end

elsekey_conter2<=5'd0;

end

elsebegin

state2<=2'b00;

key_conter2<=5'd0;

end

end

default:

state2<=2'b00;

endcase

if(k2)key2<=~key2;

end

end

assignkey_model_c=key2;

2.3滚动显示模块

上下滚动显示模块和左右滚动显示模块的原理基本相同,唯一不同的是上下滚动显示模块是按照逐个led点亮来显示汉字,而左右滚动模块是按照逐列led点亮来显示汉字。

滚动显示,主要有三部分构成。

第一部分,能够静态稳定的显示一个汉字的。

第二部分,产生汉字滚动效果的数据模块。

第三部分,储存“硬件描述语言”的存储模块。

 

图2.48*8led点阵结构图

由于led的单向导电性,上下滚动显示模块,必须选中一行led逐个送数据,来静态显示。

也就是说当16列led的数据送完之后,行选择信号才能选择下一行,即行选择信号的时间间隔是列选择信号时间的16倍。

而左右滚动显示模块可以选中一列led后整体送数据,来实现静态显示。

汉字的滚动效果是不断的给静态显示模块,送一幅一幅逐渐占满16*16led点阵的数据。

换句话说就是让本身显示完整汉字的数据的一部分用无效数据代替,来让完整的汉字只显示一部分。

程序中cnt4和memory_r是滚动效果的16个状态计数器,当计数器从0计到15的过程中,汉字会逐渐完整显示满整个led点阵。

当cnt4和memory_r计满一次后,memory1和memory10刷新一次,换成下一个汉字的数据,重新逐个状态显示。

memory0中存储的数据是送给led点阵显示的数据。

上下滚动显示由于点阵的列接在74hc154上,需要通过一个16/4的编码模块将memory0中的数据转换成4位二进制数据送给74hc154。

而左右滚动显示模块,相比之下比较简单,直接将memory0的数据送给行端就可以直接显示。

滚动显示的原理示意图如下所示:

 

图2.5滚动显示示意图

数据存储采用verilong中的存储器类型来存储数据。

存储器类型变量由reg类型变量构成。

程序如下所示:

reg[15:

0]memory1[15:

0];

reg[0:

255]memory2[5:

0];

initialbegin

$readmemh("F:

/vhdl_shiyan/vhdl_design/ziku.patt",memory1);

$readmemh("F:

/vhdl_shiyan/vhdl_design/ziku1.patt",memory2);

end

$readmemh为系统任务,用来读取patt文件中的数据到存储器变量中。

patt文件中用空格来分隔两个数据。

3仿真结果及硬件测试

3.1器件选择

硬件平台采用Altera公司的EP2C8Q208C8芯片。

总共包含4608个LES,片上RAM共计119808bits,13个18*18乘法器、两个高性能PLL以及多达142个用户自定义IO口。

3.2管脚分配

管脚分配采用qsf文件进行分配,当大量使用的管脚,能够更加高效的分配管脚。

qsf文件是在工程编译后产生的与工程名字一样的文件。

将写好的管脚分配命令粘贴在qsf文件的末尾处,进行保存。

管脚分配命令如下:

set_location_assignmentPIN_23-toclk50mhz

set_location_assignmentPIN_144-tosel0

set_location_assignmentPIN_145-tosel1

set_location_assignmentPIN_146-tosel2

set_location_assignmentPIN_142-tosel3

set_location_assignmentPIN_127-toline[0]

set_location_assignmentPIN_134-toline[1]

set_location_assignmentPIN_137-toline[2]

set_location_assignmentPIN_139-toline[3]

set_location_assignmentPIN_46-torow[15]

set_location_assignmentPIN_44-torow[14]

set_location_assignmentPIN_41-torow[13]

set_location_assignmentPIN_39-torow[12]

set_location_assignmentPIN_35-torow[11]

set_location_assignmentPIN_33-torow[10]

set_location_assignmentPIN_30-torow[9]

set_location_assignmentPIN_15-torow[8]

set_location_assignmentPIN_13-torow[7]

set_location_assignmentPIN_11-torow[6]

set_location_assignmentPIN_3-torow[0]

set_location_assignmentPIN_4-torow[1]

set_location_assignmentPIN_5-torow[2]

set_location_assignmentPIN_6-torow[3]

set_location_assignmentPIN_8-torow[4]

set_location_assignmentPIN_10-torow[5]

set_location_assignmentPIN_40-tokey[1]

set_location_assignmentPIN_147-tokey[0]

set_location_assignmentPIN_56-toreset_n

管脚分配图:

 

图3.1管脚分配图

 

3.3功能仿真

滚动显示模块仿真使用Altera-modelsim进行功能仿真。

仿真过程具体如下:

1、打开Assigment下的setting进行simulation设置。

 

图3.2

2、点击Testbenches进入NewTestBenchSetting中填好测试文件名称,并添加该文件。

 

 

图3.3

 

图3.4

仿真文件只需要修改模块的例化部分就能分别对两个显示模块进行仿真。

3、打开RTLsimulation进行功能仿真。

仿真图形如下图所示:

 

图3.5上下滚动显示仿真

 

 

图3.6左右滚动显示仿真

 

从仿真图像中可以看出,memory1和memory10这两个存储器数据更新刚好差一幅图的扫描时间。

这与预期的目标功能完全相同,只有相差一幅图的扫描时间才能实现led点阵汉字的连续滚动效果。

3.4硬件实物展示图

 

图3.7实物效果图

4结论和心得体会

通过本次的课程设计,让我对verilong硬件描述语言有了更深一层的认识。

学会使用verilong中的存取器类型变量,存储器类型变量跟c语言中的数组有一点类似,但又不完全相同。

刚开始使用这种变量的时候,总是出现各种错误。

其中最容易出错的是存储器类型变量的初始化问题。

后来经过查阅资料,使用patt文件来对存储器类型变量初始化。

本次设计中也让我见识到了硬件描述语言跟一般的编程语言有本质上的差异。

硬件描述语言的逻辑以最终综合出来的电路为基础,而一般的编程语言是和编程语言的本身语法有关。

因此在编写完verilong程序后一定要看综合后的RTL级视图来查看,逻辑是否正确。

本次设计中的上下滚动模块,总会出现一条靠左的亮线。

这是因为74hc154的16个状态全用到了,没有空余的状态来让led灯灭,把灭的状态赋值为0引起的。

这个问题目前还没有想到解决办法,后续还需要再研究一下。

 

5参考文献

[1]刘宝琴“数字电路与系统”北京清华大学出版社,1993.

[2]夏宇闻“复杂数字电路与系统的VerilogHDL设计技术”北京航空航天大学

出版社,1998.

[3]李国洪,沈明山,崔瑞雪.EDA技术与实验[M].北京:

机械工业出版社,2009.

[4]SteveK.AdvancedFPGAdesign:

Architecture,Im-plementation,andOptimization[M].JOHNWILEY&SONS,Inc,2007.

[5]潘松,黄继业.EDA技术与VHDL[M].北京:

清华大学出版社,2005.

[6]范昌波,申文达.基于FPGA在LED点阵中的应用研究[J].仪表技术,2010.

6附录

程序:

dianzhen.v

moduledianzhen(clk50mhz,row,sel0,sel1,sel2,sel3,line,reset_n,key);

inputclk50mhz;//实验箱提供50MHz时钟信号

inputreset_n;//复位信号

input[1:

0]key;

outputsel0,sel1,sel2,sel3;//设置引脚选通点阵

output[15:

0]row;//列

output[3:

0]line;//行

wirekey_direction_c;

wirekey_model_c;

wireclk50mhz_1,clk50mhz_2;

wire[15:

0]row_1;

wire[15:

0]row_2;

wire[3:

0]line_1;

wire[3:

0]line_2;

wirereset_n_1;

wirereset_n_2;

wirekey_direction_c_1;

wirekey_direction_c_2;

assignsel0=1'b0;

assignsel1=1'b1;

assignsel2=1'b0;

assignsel3=1'b0;

assignclk50mhz_1=(key_model_c)?

(clk50mhz):

1'bz;

assignclk50mhz_2=(!

key_model_c)?

(clk50mhz):

1'bz;

assignrow=(key_model_c)?

(row_1):

(row_2);

assignline=(key_model_c)?

(line_1):

(line_2);

assignreset_n_1=(key_model_c)?

(reset_n):

(1'bz);

assignreset_n_2=(!

key_model_c)?

(reset_n):

(1'bz);

assignkey_direction_c_1=(key_model_c)?

(key_direction_c):

(1'bz);

assignkey_direction_c_2=(!

key_model_c)?

(key_direction_c):

(1'bz);

hangsaomiaou1(.clk50mhz(clk50mhz_1),

.row(row_1),

.line(line_1),

.reset_n(reset_n_1),

.key_direction_c(key_direction_c_1)

);

liesaomiaou2(.clk50mhz(clk50mhz_2),

.row(row_2),

.line(line_2),

.reset_n(reset_n_2),

.key_direction_c(key_direction_c_2)

);

key_controlu3(

.clk50mhz(clk50mhz),

.reset_n(reset_n),

.key_direction(key[0]),

.key_model(key[1]),

.key_direction_c(key_direction_c),

.key_model_c(key_model_c)

);//按键消抖程序

endmodule

liesaomiao.v

moduleliesaomiao(clk50mhz,row,line,reset_n,key_direction_c);

inputreset_n;

inputkey_direction_c;

inputclk50mhz;//实验箱输入50MHz时钟信号

output[15:

0]row;//行

outputreg[3:

0]line;//列

reg[15:

0]row_r;

reg[20:

0]cnt2;

reg[3:

0]cnt1;

regfig;

reg[2:

0]cnt4;

reg[11:

0]memory_cnt;

reg[3:

0]memory_r;

reg[3:

0]line_cnt;

regclk_100khz;

reg[15:

0]memory0[15:

0];

reg[15:

0]memory1[15:

0];

reg[15:

0]memory10[15:

0];

reg[0:

255]memory2[5:

0];

parameterhz50k=25'd500;

initialbegin

$readmemh("F:

/vhdl_shiyan/vhdl_design/ziku2.patt",memory1);

$readmemh("F:

/vhdl_shiyan/vhdl_design/ziku3.patt",memory2);

end

assignrow[15]=row_r[0];

assignrow[14]=row_r[1];

assignrow[13]=row_r[2];

assignrow[12]=row_r[3];

assignrow[11]=row_r[4];

assignrow[10]=row_r[5];

assignrow[9]=row_r[6];

assignrow[8]=row_r[7];

assignrow[7]=row_r[8];

assignrow[6]=row_r[9];

assignrow[5]=row_r[10];

assignrow[4]=row_r[11];

assignrow[3]=row_r[12];

assignrow[2]=row_r[13];

assignrow[1]=row_r[14];

assignrow[0]=row_r[15];

always@(posedgeclk50mhzornegedgereset_n)begin//产生100khz的时钟

if(!

reset_n)begin

cnt2<=21'd0;

clk_100khz<=1'b0;

end

elsebegin

if(cnt2>=hz50k)

begin

cnt2<=21'd0;

clk_100khz<=1'b1;

end

elsebegin

cnt2<=cnt2+21'd1;

clk_100khz<=1'b0;

end

end

end

always@(posedgeclk_100khzornegedgereset_n)begin

if(!

reset_n)begin

cnt1<=4'd0;

line_cnt<=4'd1;

memory_cnt<=12'd0;

memory_r<=4'd0;

end

elsebegin

cnt1<=cnt1+4'd1;

if(cnt1==4'd15)

line_cnt<=line_cnt+4'd1;

memory_cnt<=memory_cnt+12'd1;

if(memory_cnt==12'hfff)

memory_r<=memory_r+4'd1;

end

end

always@(posedgeclk_100khzornegedgereset_n)begin//产生滚动效果的模块

if(!

reset_n)begin

cnt3<=8'd0;

cnt5<=5'd0;

fig<=1'd0;

cnt4<=0;

end

elsebegin

if(clkrow==4'd15)begin

cnt3<=cnt3+8'd1;

if(cnt3==8'd255)cnt5<=cnt5+4'd1;

//cnt4<=cnt4+1;

end

case(cnt5)

5'd0:

begin

memory0[0]<=memory10[0];memory0[1]<=memory10[1];

memory0[2]<=memory10[2];memory0[3]<=memory10[3];

memory0[4]<=memory10[4];memory0[5]<=memory10[5];

memory0[6]<=memory10[6];memory0[7]<=memory10[7];

memory0[8]<=memory10[8];memory0[9]<=memory10[9];

memory0[10]<=memory10[10];memory0[11]<=memory10[11];

memory0[12]<=memory10[12];memory0[13]<=memory10[13];

memory0[14]<=memory10[14];memory0[15]<=memory10[15];

fig<=1'b1;

end

5'd1:

begin

memory0[0]<=memory10[1];memory0[1]<=memory10[2];

memory0[2]<=memory10[3];memory0[3]<=memory10[4];

memory0[4]<=memory10[5];memory0[5]<=memory10[6];

memory0[6]<=memory10[7];memory0[7]<=memory10[8];

memory0[8]<=memory10[9];memory0[9]<=memory10[10];

memory0[10]<=memory10[11];memory0[11]<=memory10[12];

memory0[12]<=memory10[13];memory0[13]<=memory10[14];

memory0[14]<=memory10[15];memory0[15]<=memory1[0];

end

5'd2:

begin

memory0[0]<=memory10[2];memory0[1]<=memory10[3];

memory0[2]<=memory10[4];memory0

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

当前位置:首页 > 小学教育 > 数学

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

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