显示器件驱动技术实验讲义10.docx
《显示器件驱动技术实验讲义10.docx》由会员分享,可在线阅读,更多相关《显示器件驱动技术实验讲义10.docx(59页珍藏版)》请在冰点文库上搜索。
显示器件驱动技术实验讲义10
显示器件驱动技术实验讲义
实验一FPGA程序设计与代码下载2
实验二组合逻辑设计(3-8译码器)19
实验三时序逻辑设计(四位计数器)21
实验四FPGA驱动LED22
实验五FPGA驱动数码管一(静态扫描)25
实验六FPGA驱动数码管二(动态扫描)(四学时)27
实验七FPGA驱动液晶160231
实验八FPGA和1602液晶实现数字频率计(四学时)36
实验九FPGA驱动16*16led点阵屏(两学时)38
实验十使用FPGA驱动16*16led点阵汉字滚动显示(四学时)42
实验十一正弦波发生器47
实验十二VGA显示器件驱动(四学时)50
实验一FPGA程序设计与代码下载
1.实验任务
1.1了解FPGA和FPGA开发板的功能。
1.2使用ALTERA公司的QuartusII进行开发和下载。
2.硬件原理图
开发板所使用的FPGA是ALTERA公司的Cyclone系列的EP1C12Q240型号
3.QuartusII调试过程
QuartusII是Altera的综合开发工具,它集成了Altera的FPGA/CPLD开发流程中所涉及的所有工具和第三方软件接口。
具体操作流程如下:
首先我们在桌面上运行QutartusII软件,程序启动后选择新工程向导工具如图
创建一个新的工程
实验二组合逻辑设计(3-8译码器)
1.实验任务
1.1学习硬件描述语言VerilogHDL的语法,实现组合逻辑。
1.2使用VerilogHDL语言设计3-8译码器并仿真。
2.参考书目
夏宇闻:
复杂数字电路与系统的VerilogHDL设计技术,北京:
航空航天大学出版社;
EDA先锋工作室 王诚 蔡海宁 吴继华 编著,AlteraFPGA/CPLD设计(基础篇)(第2版),人民邮电出版社;
3.设计思路
根据3-8译码器的真值表写出逻辑表达式
4.参考代码
采用case语句描述的3-8译码器,输出高电平有效。
modulemux(sel,res);//sel是译码输入,res是译码输出(高电平有效)
input[2:
0]sel;
output[7:
0]res;
reg[7:
0]res;
always@(selorres)
begin
case(sel)
3'b000:
res=8'b00000001;
3'b001:
res=8'b00000010;
3'b010:
res=8'b00000100;
3'b011:
res=8'b00001000;
3'b100:
res=8'b00010000;
3'b101:
res=8'b00100000;
3'b110:
res=8'b01000000;
default:
res=8'b10000000;
endcase
end
endmodule
5.扩展实验
5.1.实现两个四位数据相加。
5.2.实现两个四位数据相减。
实验三时序逻辑设计(四位计数器)
1.实验任务
1.1学习硬件描述语言VerilogHDL,实现时序逻辑。
1.2使用VerilogHDL语言设计一个同步清零的四位计数器。
2.参考书目
夏宇闻:
复杂数字电路与系统的VerilogHDL设计技术,北京:
航空航天大学出版社;
EDA先锋工作室 王诚 蔡海宁 吴继华 编著,AlteraFPGA/CPLD设计(基础篇)(第2版),人民邮电出版社;
3.参考代码
modulecounter(clk,clr,qout);
inputclk,clr;
output[3:
0]qout;
reg[3:
0]qout;
always@(posedgeclk)
if(clr)
qout<=0;
else
qout<=qout+1;
endmodule
4.注意事项
4.1.异步复位和同步复位的区别;
4.2.阻塞逻辑和飞阻塞逻辑的区别。
5.扩展实验,在示例程序的基础上修改设计代码,
5.1.实现异步清零的四位计数器。
5.2.实现可同步或者异步置位的计数器。
5.3.实现可控的正计数或者倒计数的计数器。
实验四FPGA驱动LED
1.实验任务
使用FPGA开发板,驱动板载LED,设计程序实现LED流水灯效果。
2.硬件原理图
图2.1.管脚定义
图2.2.共阴极的LED驱动方式
4.软件工具管脚定义
图4.1.QuartusII的管脚定义
5.参考代码
moduleled_run(mclk,led);
inputmclk;
output[7:
0]led;
reg[7:
0]led;
reg[22:
0]count;
reg[2:
0]state;
wireclk;
always@(posedgemclk)
count=count+1;
assignclk=count[22];//取计数器最高位做低频时钟
always@(posedgeclk)
begin
case(state)
3'b000:
beginled=8'b10000001;state=state+1;end
3'b001:
beginled=8'b01000010;state=state+1;end
3'b010:
beginled=8'b00100100;state=state+1;end
3'b011:
beginled=8'b00011000;state=state+1;end
3'b100:
beginled=8'b00011000;state=state+1;end
3'b101:
beginled=8'b00100100;state=state+1;end
3'b110:
beginled=8'b01000010;state=state+1;end
3'b111:
beginled=8'b10000001;state=state+1;end
endcase
end
endmodule
说明:
mclk是FPGA的输入时钟,采用50M有源晶振。
请思考:
count[22]是多少分频?
6.注意事项
使用FPGA开发板实现例程中的代码,并下载到开发板,观察LED灯的闪烁情况是否和设计代码一致。
7.扩展性实验
实现与参考代码不同的LED流水灯效果。
实验五FPGA驱动数码管一(静态扫描)
1.实验任务
使用fpga开发板驱动四位八段数码管显示四位一样的数据。
2.硬件原理图
2.1.共阳极四位数码管连接图
3、参考代码
moduleshu_ma_gaun(mainclk,//主时钟
seg_data,//段选
ledseg//位选
);
inputmainclk;
output[7:
0]seg_data;
output[3:
0]ledseg;
wire[3:
0]ledseg;
reg[7:
0]seg_data;
reg[24:
0]Cont;//计数器变量
reg[3:
0]keyword;
always@(posedgemainclk)//计数
Cont<=Cont+1;
always@(posedgeCont[24])//根据低频时钟
keyword<=keyword+1;//低频计数器
always@(keyword)
case(keyword)
4'h0:
seg_data<=8'hC0;//段选,显示0
4'h1:
seg_data<=8'hF9;//显示1
4'h2:
seg_data<=8'hA4;
4'h3:
seg_data<=8'hb0;
4'h4:
seg_data<=8'h99;
4'h5:
seg_data<=8'h92;
4'h6:
seg_data<=8'h82;
4'h7:
seg_data<=8'hF8;
4'h8:
seg_data<=8'h80;
4'h9:
seg_data<=8'h90;
4'ha:
seg_data<=8'h88;
4'hb:
seg_data<=8'h83;
4'hc:
seg_data<=8'hc6;
4'hd:
seg_data<=8'ha1;
4'he:
seg_data<=8'h86;
4'hf:
seg_data<=8'h8E;
endcase
assignledseg=4'b0000;//位选全开,4个数码管显示相同的数据
4、注意事项
观察四位八段数码管的显示的数字是否和设计代码一致。
5、扩展实验
实现四位八段数码管静态显示不同数字。
实验六FPGA驱动数码管二(动态扫描)(四学时)
1.实验任务
使用fpga开发板驱动四位八段数码管显示四位不同的数据。
2.硬件原理图
2.1.共阳极四位数码管连接图
3.参考代码
moduleshu_ma_guan(
mainclk,
seg_data,//段选
ledseg//位选
);
inputmainclk;
output[7:
0]seg_data;
output[3:
0]ledseg;//位选
reg[3:
0]ledseg;
reg[7:
0]seg_data;
reg[24:
0]Cont;
reg[1:
0]state;
always@(posedgemainclk)
Cont<=Cont+1;
always@(posedgeCont[15])
case(state)
2'h0:
beginseg_data<=8'b11000000;ledseg<=4'b0111;state<=state+1;end
2'h1:
beginseg_data<=8'b11111001;ledseg<=4'b1011;state<=state+1;end
2'h2:
beginseg_data<=8'b11111001;ledseg<=4'b1101;state<=state+1;end
2'h3:
beginseg_data<=8'b10000000;ledseg<=4'b1110;state<=state+1;end
endcase
endmodule
4.扩展应用参考代码
效果:
两个数码管显示0-99变化的数字。
思路:
做一个计数器变量0-99变化;取变量的个位和十位(通过整除取整和取余的方法);将个位和十位与要显示的段选码一一对应;开位选,送段选,循环。
注意:
FPGA并行执行!
四步无先后之分,这是与单片机的最大区别!
moduleshu_ma_guan(
mainclk,
seg_data,//段选
ledseg//位选
);
inputmainclk;
output[7:
0]seg_data;
output[3:
0]ledseg;//位选
reg[3:
0]ledseg;
reg[7:
0]seg_data;
reg[7:
0]gewei_code;
reg[7:
0]shiwei_code;
reg[3:
0]gewei_reg;
reg[3:
0]shiwei_reg;
reg[24:
0]Cont;
reg[4:
0]Cont1;
regstate;
always@(posedgemainclk)
Cont<=Cont+1;
always@(posedgeCont[15])
case(state)
1'b0:
beginseg_data=shiwei_code;ledseg<=4'b0111;state<=state+1;end
1'b1:
beginseg_data=gewei_code;ledseg<=4'b1011;state<=state+1;end
endcase
always@(posedgeCont[24])
begin
if(Cont1==30)
Cont1=0;
else
Cont1=Cont1+1;
end
always@(Cont1)
begin
gewei_reg=Cont1/10;
shiwei_reg=Cont1%10;
end
always@(gewei_reg)
case(gewei_reg)
4'h0:
gewei_code<=8'hC0;
4'h1:
gewei_code<=8'hF9;
4'h2:
gewei_code<=8'hA4;
4'h3:
gewei_code<=8'hb0;
4'h4:
gewei_code<=8'h99;
4'h5:
gewei_code<=8'h92;
4'h6:
gewei_code<=8'h82;
4'h7:
gewei_code<=8'hF8;
4'h8:
gewei_code<=8'h80;
4'h9:
gewei_code<=8'h90;
endcase
always@(shiwei_reg)
case(shiwei_reg)
4'h0:
shiwei_code<=8'hC0;
4'h1:
shiwei_code<=8'hF9;
4'h2:
shiwei_code<=8'hA4;
4'h3:
shiwei_code<=8'hb0;
4'h4:
shiwei_code<=8'h99;
4'h5:
shiwei_code<=8'h92;
4'h6:
shiwei_code<=8'h82;
4'h7:
shiwei_code<=8'hF8;
4'h8:
shiwei_code<=8'h80;
4'h9:
shiwei_code<=8'h90;
endcase
endmodule
5.扩展性实验
5.1.实现秒钟分钟的时钟计时效果,
5.2.实现秒和百分秒的秒表计时效果。
6.思考
怎样通过调整数码管位选的占空比来使得数码管亮度降低一些?
实验七FPGA驱动液晶1602
1.实验任务
1.1使用FPGA开发板,编写硬件语言程序,1602液晶显示当前日期和自己的学号。
1.2使用FPGA开发板,编写硬件语言程序,1602液晶显示1-9999计数。
2.硬件原理图
3.调试过程
4.参考代码
moduleLCD(fre_data,clk,rst_n,rs,rw,en,dat);
inputclk;
inputrst_n;
outputrs,rw,en;
output[7:
0]dat;
regrs,rw;
wireen;
input[31:
0]fre_data;//频率值
wire[9:
0]fre[3:
0];
wire[7:
0]fre_unit;//频率的单位
reg[7:
0]dat;
reg[4:
0]counter;
reg[1:
0]state;
reg[17:
0]count;
regclkr;
parameterinit=2'd0,write_data_1=2'd1,write_data_2=2'd2;
//parameterstop_state=3;
assignen=clkr;
//assignfre_data=32'd123_9;//显示固定值。
reg[9:
0]data_flag;
reg[1:
0]flag;
reg[7:
0]chara[3:
0];//----------分解频率值,MHz,KHz,Hz----------------?
assignfre[3]=fre_data/10000000;//MHz的位数?
assignfre[2]=(fre_data%10000000)/10000;//KHz的位数?
?
?
?
assignfre[1]=(fre_data%10000)/10;//Hz的位数?
assignfre[0]=fre_data%10;//0.1Hz的位数
assignfre_unit=(fre[3]>0)?
"M":
((fre[2]>0)?
"K":
"");//上面一句是判断频率级别,给定单位
//---------获取字符串,在液晶上显示-----------------
always@(posedgeclkornegedgerst_n)
if(!
rst_n)
begindata_flag<=4'b0;flag<=2'b0;end
else
begin
if(fre[3]>0)//MHz分解
beginflag=flag+2'd1;
if(flag==2'd1)data_flag=fre[3]/100;
if(flag==2'd2)data_flag=(fre[3]%100)/10;
if(flag==2'd3)data_flag=fre[3]%10;
if(flag==2'd0)data_flag=fre[2]/100;end
elseif(fre[2]>0)//KHz分解
beginflag=flag+2'd1;
if(flag==2'd1)data_flag=fre[2]/100;
if(flag==2'd2)data_flag=(fre[2]%100)/10;
if(flag==2'd3)data_flag=fre[2]%10;
if(flag==2'd0)data_flag=fre[1]/100;
end
else//Hz分解
beginflag=flag+2'd1;
if(flag==2'd1)data_flag=fre[1]/100;
if(flag==2'd2)data_flag=(fre[1]%100)/10;
if(flag==2'd3)data_flag=fre[1]%10;
if(flag==2'd0)data_flag=fre[0];
end
end
always@(posedgeclk)//获取字符
begincase(data_flag)
4'd0:
chara[flag]="0";
4'd1:
chara[flag]="1";
4'd2:
chara[flag]="2";
4'd3:
chara[flag]="3";
4'd4:
chara[flag]="4";
4'd5:
chara[flag]="5";
4'd6:
chara[flag]="6";
4'd7:
chara[flag]="7";
4'd8:
chara[flag]="8";
4'd9:
chara[flag]="9";
endcase
end
//--------------液晶读写时钟-----------------
always@(posedgeclkornegedgerst_n)
if(!
rst_n)
begincount=0;end//初始化
else
begincount=count+16'd1;
if(count==16'h7fff)beginclkr=~clkr;endend//------------液晶初始化及写数据-------------------
always@(posedgeclkrornegedgerst_n)
if(!
rst_n)//初始化
beginstate=init;counter=0;end
else
begin
case(state)
init:
//LCD1602初始化
beginrs=0;rw=0;counter=counter+4'd1;
case(counter)
1:
dat=8'h38;//显示模式设置
2:
dat=8'h08;//光标设计,08代表关闭光标?
3:
dat=8'h01;//显示清屏
4:
dat=8'h06;//显示光标移动设置
5:
dat=8'h0c;//显示开及光标设置?
6:
begindat=8'h81;//写光标地址
state=write_data_1;
counter=4'd0;end
default:
counter=4'd0;endcase
end
write_data_1:
//写数据
begin
rs=1;
case(counter)
0:
dat="f";
1:
dat="r";
2:
dat="e";
3:
dat=":
";
4:
dat="";
5:
dat=chara[1];
6:
dat=chara[2];
7:
dat=chara[3];
8:
dat=".";
9:
dat=chara[0];
10:
dat=fre_unit;
11:
dat="H";
12:
dat="z";
13:
dat="";
14:
beginrs=0;dat=8'hc0;end
default:
counter=0;
endcase
if(counter==14)
begincounter=0;state=write_data_2;
end
elsecounter=counter+4'd1;end
write_data_2:
//写数据
beginrs=1;
case(counter)
0:
dat="a";
1:
dat="m";
2:
dat="p";
3:
dat=":
";
4:
dat="";
5:
dat=chara[1];
6:
dat=chara[2];
7:
dat=chara[3];
8:
dat="m";
9:
dat="V";
10:
dat="";
11:
dat="";
12:
beginrs=0;dat=8'h80;end
default:
counter=0;
endcase
if(counter==12)
be