哈工程FPGA实验报告1616点阵.docx
- 文档编号:25845189
- 上传时间:2023-06-16
- 格式:DOCX
- 页数:23
- 大小:115.30KB
哈工程FPGA实验报告1616点阵.docx
《哈工程FPGA实验报告1616点阵.docx》由会员分享,可在线阅读,更多相关《哈工程FPGA实验报告1616点阵.docx(23页珍藏版)》请在冰豆网上搜索。
哈工程FPGA实验报告1616点阵
FPGA实验报告
姓名:
学号:
指导教师:
2013.6.10
实验六点阵扫描显示实验
一、实验原理
根据硬件电路可知,点阵的控制端口由行端口和列端口组成,分别为16个,相当于256个LED灯。
要是某一个灯亮,只需使对应位置上一端为高,一端为低。
该16*16的点阵的列端口由一个74154四位译码器控制。
由其资料可知,要使74154正常工作,其12脚、18脚与19脚必须接低。
20、21、22、23脚是数据输入端。
24脚为VCC,其他为数据输出端口。
16×16扫描LED点阵的工作原理同8位扫描数码管类似。
它有16个共阴极输出端口,每个共阴极对应有16个LED显示灯,所以其扫描译码地址需4位信号线(SEL0-SEL3),其汉字扫描码由16位段地址(0-15)输入。
通过时钟的每列扫描显示完整汉字。
点阵LED一般采用扫描式显示,实际运用分为三种方式:
(1)点扫描
(2)行扫描
(3)列扫描
若使用第一种方式,其扫描频率必须大于16×64=1024Hz,周期小于1ms即可。
若使用第二和第三种方式,则频率必须大于16×8=128Hz,周期小于7.8ms即可符合视觉暂留要求。
此外一次驱动一列或一行(8颗LED)时需外加驱动电路提高电流,否则LED亮度会不足。
汉字显示使用的是16×16的点阵,FPGA实验箱上有其接口电路,列选信号为SEL0,SEL1,SEL2,SEL3,经4线16线译码器输出16列,从左起为第一列,列选信号是由一个4位向量SEL[3..0]控制;行选信号为H0~H15,是由16个行信号组成的,每一行由一个单独的位来控制,高电平有效。
例如“0000”表示第0列,“0000000000000001”表示第一行的点亮。
由于列是由一个向量决定,而每一时刻的值只能有一个固定的值,因而只能使某一列的若干个点亮,因此就决定了只能用逐列扫描的方法。
例如要使第一列的2,4,6,8,行亮,则列为“0001”、行为“0000000010101010”就可以实现了
用动态分时扫描技术使LED点阵模块显示图像,需要进行两步工作。
第一步是获得数据并保存,即在存贮器中建立汉字数据库。
第二步是在扫描模块的控制下,配合行扫描的次序正确地输出这些数据。
获得图像数据的步骤是,先将要显示的每一幅图像画在一个如图3.3所示的被分成16×16共256个小方格的矩形框中,再在有笔划下落处的小方格里填上“1”,无笔划处填上“0”,这样就形成了与这个汉字所对应的二进制数据在该矩形框上的分布,再将此分布关系以32×16的数据结构组成64个字节的数据,并保存在只读存贮器ROM中。
以这种方式将若干个汉字的数据贮存在存贮器内,就完成了图像数据库的建立工作。
二、实验框图及原理图
实验原理图
实验框图
三、实验程序详解
1)行扫描
使行扫描端口依次拉低,同时较高频率进行列扫秒
moduleD_Z(clk,lie,hang,sel0,sel1,sel2);
inputclk;//时钟输入
output[4:
0]lie;//点阵引脚
output[15:
0]hang;
outputsel0;//扩张功能选择引脚
outputsel1;
outputsel2;
regclk_s;
regclk_ms;
reg[4:
0]lie;
reg[15:
0]hang;
reg[3:
0]XS_data;//显示状态
reg[3:
0]PY_data;//平移状态
reg[31:
0]XS_DIV;//显示计数
reg[31:
0]PY_DIV;//平移计数
wiresel0;
wiresel1;
wiresel2;
parameterCLK_XS='D25_000;
parameterCLK_PY='D1_000;
assignsel0=1'b0;//扩展功能选择点阵
assignsel1=1'b1;
assignsel2=1'b0;
always@(posedgeclk)//时钟分频产生毫秒时钟,用于点阵动态显示
begin
if(XS_DIV XS_DIV<=XS_DIV+1'b1; else begin XS_DIV<=0; clk_ms<=~clk_ms; end end always@(posedgeclk_ms)//毫秒时钟计数产生秒级时钟,用于平移 begin if(PY_DIV<=CLK_PY) PY_DIV<=PY_DIV+1; else begin PY_DIV<=0; clk_s<=~clk_s; end end always@(posedgeclk_ms)//显示一行点阵 begin case(XS_data) 0: begin lie=5'b00000; XS_data=1; end 1: begin lie=5'b00001; XS_data=2; end 2: begin lie=5'b00010; XS_data=3; end 3: begin lie=5'b00011; XS_data=4; end 4: begin lie=5'b00100; XS_data=5; end 5: begin lie=5'b00101; XS_data=6; end 6: begin lie=5'b00110; XS_data=7; end 7: begin lie=5'b00111; XS_data=8; end 8: begin lie=5'b01000; XS_data=9; end 9: begin lie=5'b01001; XS_data=10; end 10: begin lie=5'b01010; XS_data=11; end 11: begin lie=5'b01011; XS_data=12; end 12: begin lie=5'b01100; XS_data=13; end 13: begin lie=5'b01101; XS_data=14; end 14: begin lie=5'b01110; XS_data=15; end 15: begin lie=5'b01111; XS_data=0; end default begin lie=5'b01111; XS_data=0; end endcase end always@(posedgeclk_s)//行平移,间隔1秒显示每一行 begin case(PY_data) 0: begin hang=16'h0001; PY_data=1; end 1: begin hang=16'h0002; PY_data=2; end 2: begin hang=16'h0004; PY_data=3; end 3: begin hang=16'h0008; PY_data=4; end 4: begin hang=16'h0010; PY_data=5; end 5: begin hang=16'h0020; PY_data=6; end 6: begin hang=16'h0040; PY_data=7; end 7: begin hang=16'h0080; PY_data=8; end 8: begin hang=16'h0100; PY_data=9; end 9: begin hang=16'h0200; PY_data=10; end 10: begin hang=16'h0400; PY_data=11; end 11: begin hang=16'h0800; PY_data=12; end 12: begin hang=16'h1000; PY_data=13; end 13: begin hang=16'h2000; PY_data=14; end 14: begin hang=16'h4000; PY_data=15; end 15: begin hang=16'h8000; PY_data=0; end default begin hang=16'h0000; PY_data=0; end endcase end endmodule 2)列扫描 将行端口全部拉高,同时给译码器的数据输入端口加一,每次使对应显示的行端口保持低电平,与行扫描必须同时进行扫描的字符才能显示正确。 moduleD_Z(clk,lie,hang,sel0,sel1,sel2); inputclk;//时钟输入 output[4: 0]lie;//点阵引脚 output[15: 0]hang; outputsel0;//扩张功能选择引脚 outputsel1; outputsel2; regclk_s; reg[4: 0]lie; reg[3: 0]XS_data;//显示状态 reg[31: 0]XS_DIV;//显示计数 wire[15: 0]hang; wiresel0; wiresel1; wiresel2; parameterCLK_XS='D25_000_000; assignsel0=1'b0;//扩展功能选择点阵 assignsel1=1'b1; assignsel2=1'b0; assignhang=16'b1111_1111_1111_1111; always@(posedgeclk)//时钟分频,产生秒级时钟,用于平移 begin if(XS_DIV XS_DIV<=XS_DIV+1'b1; else begin XS_DIV<=0; clk_s<=~clk_s; end end always@(posedgeclk_s)//间隔一秒平移显示每列 begin case(XS_data) 0: begin lie=5'b00000; XS_data=1; end 1: begin lie=5'b00001; XS_data=2; end 2: begin lie=5'b00010; XS_data=3; end 3: begin lie=5'b00011; XS_data=4; end 4: begin lie=5'b00100; XS_data=5; end 5: begin lie=5'b00101; XS_data=6; end 6: begin lie=5'b00110; XS_data=7; end 7: begin lie=5'b00111; XS_data=8; end 8: begin lie=5'b01000; XS_data=9; end 9: begin lie=5'b01001; XS_data=10; end 10: begin lie=5'b01010; XS_data=11; end 11: begin lie=5'b01011; XS_data=12; end 12: begin lie=5'b01100; XS_data=13; end 13: begin lie=5'b01101; XS_data=14; end 14: begin lie=5'b01110; XS_data=15; end 15: begin lie=5'b01111; XS_data=0; end default begin lie=5'b01111; XS_data=0; end endcase end endmodule 3)显示姓名 moduledainzhen(clk,en,column,line,sel0,sel1,sel2,stop); inputclk; inputstop; output[3: 0]column; output[15: 0]line; reg[3: 0]column; reg[15: 0]line; reg[7: 0]i,j,k;//定义计算用于显示具体一个点的参数 outputen; outputsel0; outputsel1; outputsel2; assignen=0; assignsel0=0; assignsel1=1; assignsel2=0; reg[16: 0]counter; regclk_1; always@(posedgeclk) begin if(counter[15]) begin clk_1<=~clk_1; counter<=0; end else counter<=counter+1'b1; end //-------------------------- taskdisplay;//定义任务display reg[3: 0]column_out;//行显示中间变量,可以省略 reg[15: 0]line_out;//列显示中间变量,可以省略 begin case(i)//每一个i值进来以后,判断需要显示一个点的列坐标? 0: column_out=4'h0;// 1: column_out=4'h1;// 2: column_out=4'h2;// 3: column_out=4'h3;// 4: column_out=4'h4;// 5: column_out=4'h5;// 6: column_out=4'h6;// 7: column_out=4'h7;// 8: column_out=4'h8;// 9: column_out=4'h9;// 10: column_out=4'ha;// 11: column_out=4'hb;// 12: column_out=4'hc;// 13: column_out=4'hd;// 14: column_out=4'he;// 15: column_out=4'Hf;// endcase k=(i+j)%48;//k用取余计算来确定,使字符能够向左移动,每次移动一步 case(k)//每一个k值进来以后,判断需要显示一行上面的 //坐标上的数据 0: line_out=16'h2004;//刘 1: line_out=16'h1804;// 2: line_out=16'h0924;// 3: line_out=16'hFFA4;// 4: line_out=16'h0224;// 5: line_out=16'h4224;// 6: line_out=16'h2224;// 7: line_out=16'h1424;// 8: line_out=16'h1424;// 9: line_out=16'h0824;// 10: line_out=16'h0824;// 11: line_out=16'h1424;// 12: line_out=16'h2204;// 13: line_out=16'h4304;// 14: line_out=16'h8114;// 15: line_out=16'h0008;// 16: line_out=16'h1004;//妍 17: line_out=16'h17FE;// 18: line_out=16'h1088;// 19: line_out=16'h1088;// 20: line_out=16'hFC88;// 21: line_out=16'h2488;// 22: line_out=16'h2488;// 23: line_out=16'h27FE;// 24: line_out=16'h2488;// 25: line_out=16'h4488;// 26: line_out=16'h2888;// 27: line_out=16'h1088;// 28: line_out=16'h2888;// 29: line_out=16'h4488;// 30: line_out=16'h8108;// 31: line_out=16'h0288;// 32: line_out=16'h0008;//玉 33: line_out=16'h7FFC;// 34: line_out=16'h0100;// 35: line_out=16'h0100;// 36: line_out=16'h0100;// 37: line_out=16'h0100;// 38: line_out=16'h0110;// 39: line_out=16'h3FF8;// 40: line_out=16'h0100;// 41: line_out=16'h0100;// 42: line_out=16'h0140;// 43: line_out=16'h0130;// 44: line_out=16'h0110;// 45: line_out=16'h0104;// 46: line_out=16'hFFFE;// 47: line_out=16'h0000;// endcase column=column_out;//结束判断后给行输出赋值 line=line_out;//结束判断后给列输出赋值 end endtask //-------------------------- always@(posedgeclk_1) begin i=i+1;//每个clk信号来了以后自加1 if(i==16) begin i=0;//八行都显示完毕后归零 if(stop) begin j=j+1; end //同时纵向所有数据向左移动一位 end// if(j==48)j=0;//都完成移动后计数器j归零 display;//调用显示任务,clk连续不断,保持视觉暂留,形成滚动//的S字样 end endmodule 四、管脚分配 五、实验现象 1.行扫描 点阵上的点逐行依次点亮 2.列扫描 点阵上的点逐列依次点亮 3.姓名显示 点阵上滚动显示姓名“刘妍玉” 六、实验总结 实验结果显示字符可以正常显示并在点阵上滚动,通过将扫描的行与列的管脚分别反向分配可以实现字符的镜像显示 通过实验了解了点阵显示的基本原理,通过扫描的方式将存在存储器中的数据显示出来。 实验中发现,行扫描和列扫描需要同时分别进行,即要想使得某一位置亮起,就要保持列端口一直为高,行端口依次拉低即可,但是在实验过程中由于对语言的不熟悉,在实验开始阶段遇到了很大的困难,自己写程序很吃力,分频阶段之后行扫描与列扫描的并行处理,在老师同学帮助和查找网上资料,基本熟悉了大致的程序过程,但对于自己把握大段的程序仍然有困难,需要进一步的学习。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 工程 FPGA 实验 报告 1616 点阵