电压测量西工大fpga课设数电实验.docx
《电压测量西工大fpga课设数电实验.docx》由会员分享,可在线阅读,更多相关《电压测量西工大fpga课设数电实验.docx(51页珍藏版)》请在冰豆网上搜索。
电压测量西工大fpga课设数电实验
西北工业大学
课程设计报告
题目:
电压测量
学院:
班级:
学生(学号):
学生(姓名):
学生(学号):
学生(姓名):
日期:
年月日
摘要
用FPGA开发板和Verilog-HDL语言实现了学号循环显示以及电压测量这两个功能。
其中学号循环显示在开发板的数码管上实现,数码管上呈现出两人学号后四位循环。
电压测量通过开发板上LED小灯闪烁,电压在1v~2v时LED1闪烁;电压在2v~3v时LED2闪烁;电压在3v~4v时LED3闪烁;电压在4v~5v时LED4闪烁。
与此同时,VGA屏幕显示准确电压测量值,误差<0.1V。
关键词:
FPGAVerilog学号循环显示
电压测量VGA接口
八、附录(含代码)•••••••••••••••••••••••• 14
题目:
电压测量
一、课程设计目的
1)巩固和加深所学电子技术课程的基本知识,提高综合运用所学知识的能力;
2)培养学生根据课题需要选用参考书,查阅手册、图表和文献资料的能力,提高学生独立解决工程实际问题的能力;
3)通过设计方案的分析比较、设计计算、元件选择及电路安装调试等环节.初步掌握单实用电路的工程设计方法;
4)提高学生的动手能力。
掌握FPGA开发板以及Verilog的正确使用方法,学会对简单实用电路的实验调试和对整机指标的测试方法;
5)了解与课题有关的电路以及元器件的工程技术规范,能按课程设计任务书的要求编写设计说明书,能正确反映设计和实验成果。
二、设计任务与要求
一)任务:
1.显示学号
2.测量电压范围0-5V,误差<0.1V
二)要求:
1.采用数码管显示
循环显示2个人的学号后四位
2.电压在1-2V:
LED1按1Hz闪烁
电压在2-3V:
LED2按1Hz闪烁
电压在3-4V:
LED3按1Hz闪烁
电压在4-5V:
LED4按1Hz闪烁
通过VGA显示测量结果
三、方案设计与论证
一)学号循环显示设计方案
该工程分为三个模块,分别是数码管译码模块、分频模块、学号循环显示模块。
其中数码管译码模块的功能是将输入的整形变量译码成8
位2进制数,8位二进制数分别对应七段数码管灯,不同的整形变量通过译码会点亮不同位置的灯(其中高电平1表示熄灭,低电平0表示点亮),从而显示不同的数字。
分频模块是将50Mhz震荡频率通过计数法降低到频率为1hz的震荡信号。
学号循环显示模块是通过检测震荡信号的上跳沿(分频后的)来控制输出两个不同的信号,周期为1S。
并输出给数码管(通过数码管译码模块)。
学号循环显示模块为主模块,它调用了分频模块与数码管译码模块。
二)电压测量显示设计方案
该工程分为四个模块,分别是采集模块、数据转换模块、LED闪烁模块、VGA显示模块。
1.采集模块:
通过PCF8591芯片将模拟电压信号转换成8位二进制数字信号。
I2C通信中只涉及两条信号线,即时钟线SCL和数据线SDA。
时钟线的下降沿锁存数据。
当时钟线SCL高电平时,如果把数据线SDA从高电平拉到低电平,则表示通信开始;如果把数据线SDA从低电平拉到高电平,则表示通信结束。
该模块接口定义如下:
信号名称
方向
描述
clk
Input
时钟信号,50MHz
rst_n
Input
复位信号,低电平有效
ren
Input
按键,低电平有效,进行读写操作
scl
output
PCF8591的时钟端口
sda
Inout
PCF8591的数字端口
data_out
output
数据输出
2.数据转换模块:
将PCF8591芯片对电压采集的8位二进制数字信号转化为两个4位二进制数字信号。
3.LED闪烁模块:
这个模块有三个输入信号,分别是clk(50MHz时钟信号),clr(复位信号)和Va[3:
0](表示高位的4位二进制数字信号)。
有四个输出信号,分别为led0,led1,led2,led3(LED灯显示)。
实现的功能是,当电压位于不同的区间时,所对应的led灯闪烁。
当Va为1~2V,led0闪烁;当Va为2~3V,led1闪烁;当Va为3~4V,led2闪烁;当Va为4~5V,led3闪烁。
4.VGA显示模块:
其功能是通过程序逻辑设计实现对VGA屏幕的逐行逐列扫描,并定义了VGA上的有效显示区间并在有效区间上显示测量结果。
FPGA是整个系统的核心,而VGA显示颜色则为本次课程设计的重点。
通过Verilog可控制输出红、绿、蓝三基色信号和HS、VS 行场扫描同步信号。
当FPGA 接受输出的控制信号后,内部的数据选择器模块根据控制信号选择相应的字符生成模块,输出字符信号,与行场扫描时序信号一起通过VGA 接口电路送入显示器,VGA显示器上便可看到对应的测试结果。
主时钟由外部提供,提供50 MHz频率的时钟源。
控制中,只需要考虑行同步信号(Hs)、场同步信号(Vs)以及红绿蓝(RGB)这5个信号。
如果能从FPGA发出这5个信号到VGA接口,就可以实现对VGA的控制。
通过对硬件进行编程,输出标准的 VGA 信号(红、绿、蓝三色信号和行、场同步信号),通过 VGA 接口输出至显示器,可具有显示驱动程序的能力,驱动显示器显示图像信号。
板上的 VGA 接口只需使用其中的 5 个引脚,其中行、帧同步信号直接由 FGPA 输出;在硬件编程过程中,定义了三个颜色输出信号,通过定义二进制数来控制三个输出端输出与否,最后经由电阻网络 D/A 变换后输出值显示器。
四、单元电路设计与参数计算
1、数码管显示学号:
2、VGA显示
用了五个进程实现VGA接口协议内容:
1)使用分频器产生25MHz的脉冲信号
2)行计数
3)行同步
4)场计数
5)场同步
五、遇到问题的解决方法
1、在Verilog语言编译和实际应用中,这个问题着实困扰了我们很长时间,之前学习过C,VB等语言,主要通过VC6.0进行编译。
众所周知,在VC6.0中集合的语言都为主流语言,突然接触一门新的,对我们来说比较陌生甚至偏门的语言让人很不适应,尤为特殊的是Verilog主要为了实现硬件功能,和上述其他语言还是有很大的不同。
但是在花了一天时间看Verilog语法后,发现还是与通用语言有许多共通之处的,只不过是表示方法不同而已,比如说输出在C中是printf,在Verilog中却是output。
在实际应用中,我们只需要写好正确并编译无误的程序并分配合适的管脚,实现功能还是相对简单的。
总的来说,在初步入门之后,我们才发现Verilog的易读性和通用性有多强。
2、遇到数码管显示时,显示学号的数字反向。
因为编写代码时数码管译码高低位写反。
3、VGA显示中,关于显示方面的知识之前完全没有接触过,也不知道显示原理什么的,书上讲的也比较少。
但是在网上查资料与同学交流后,发现VGA显示的原理其实就是信号扫描,因此在定义了计数器后,我们将显示屏分成640*480的点阵,弄清楚VGA三原色即红绿蓝组成其他颜色的原理后,用2进制数进行控制,从而实现了显示三种颜色的任务要求。
4、电压采集时,一开始对IIC协议并不是很了解,经过了查找资料和同学的交流,逐渐理解,数据采集的本质是将模拟信号转化成二进制数字信号最终通过编译显示出来的过程。
六、结论与心得
虽然在数电实验课曾经对FPGA板子和Virelog语言有一些初步的了解,可是当题目给出时仍然手足无措,只有短短的一个多星期,我们做出了成果,此次课设收获颇丰。
在数电实验课中,我们很少使用程序语言来进行开发,多半采用绘制电路图的简单方法,然而在多数复杂的项目中,我们必须使用程序语言进行硬件开发。
此次课设中我们初步了解了硬件开发的过程以及硬件语言的使用,感受到了程序语言的简洁方便,也体会到Virelog语言比C语言在硬件开发方面更简便易懂,深深感受到了程序的功能强大。
虽然刚开始设计开发时我们总是不断碰壁,无法看懂程序代码,无法缕清设计模块,甚至连PCF8591板如何连接如何采集也是一无所知,但是随着后来的查阅资料,咨询同学以及多次试验后我们渐渐感受到了课程设计的有趣之处,呆在实验室中用心钻研忘记吃饭互相探讨携手并进的时光仍令人怀念。
当最后VGA屏幕上显示出我们的动态电压值时,那种激动的心情,是其他事情无法比拟的。
课程设计注重知识与现实的结合,在此次课设中我们锻炼了动手能力,接触了课本以外的实体事物,了解到了数电的魅力。
七、参考文献
《数字电路实验指导讲义(第二版)》,樊伟敏、祁才君编
《深入浅出玩转FPGA视频学习教程》
附录(所编代码)
一、学号循环显示
modulestu_num(clk,clr,led0,led1,led2,led3);
inputclk;//50MHz
inputclr;
output[7:
0]led0;
output[7:
0]led1;
output[7:
0]led2;
output[7:
0]led3;
reg[7:
0]led0;
reg[7:
0]led1;
reg[7:
0]led2;
reg[7:
0]led3;
reg[25:
0]cnt;
reg[1:
0]num1;
reg[1:
0]num2;
always@(posedgeclkornegedgeclr)
begin
if(!
clr)
begin
num1<=2'd0;
cnt=25'd0;
end
elseif(cnt==25'h1ffffff)//2^25deviceT=0.617
begin
num2<=num1;
cnt=25'd0;
if(num1<2'd2)
num1<=num1+1'b1;
else
num1<=2'd0;
end
else
cnt=cnt+1'b1;
end
parameter
a0=8'b11111001,//数字1
a1=8'b10100100,//数字2
a2=8'b10110000,//数字3
a3=8'b10000000,//数字8
a4=8'b10010000;//数字9
always@(num2)
begin
case(num2)
2'd0:
begin
led3<=a0;
led2<=a3;
led1<=a4;
led0<=a1;
end
2'd1:
begin
led3<=a0;
led2<=a3;
led1<=a4;
led0<=a2;
end
endcase
end
endmodule
二、电压采集
moduleAD(clk,rst_n,ren,scl,sda,data_out);
inputclk,rst_n,ren;
inoutsda;
outputscl;
output[7:
0]data_out;
reg[7:
0]data_out;
regscl,sda;//I2CSerialBUS
parameterfre=8'd50;//T=1us
reg[7:
0]cnt;
regclk_in;
//-------------------------------------
reg[2:
0]start_check;//dismissjitterofswitch,getsynchronizingsignalstart_en
wirestart_en;
always@(posedgeclkornegedgerst_n)
if(!
rst_n)start_check<=3'd0;
else
begin
start_check[0]<=ren;
start_check[1]<=start_check[0];
start_check[2]<=start_check[1];
end
//en=1
assignstart_en=start_check[2]&start_check[1]&start_check[0];
//-----------------------------------------
always@(posedgeclk)//frequencydivider,T(clk_in)=1us,usedinI2CBUS
if(start_en)
begin
cnt<=cnt+1'b1;
if(cnt==fre>>1)begin
clk_in=~clk_in;
end
elseif(cnt==fre)
begin
clk_in=~clk_in;
cnt<=8'd0;
end
end
/*--------------------------------------------------
I2CBUStorealizeADCofPCF8591with4states
ack=2'b00start()+write(AddrWr)//0x90
ack=2'b01write(ControlByte)//0x02
ack=2'b10start()+write(AddrRd)//0x91
ack=2'b10Read(data)//dataistheADCoutput
--------------------------------------------------*/
reg[1:
0]ack;
reg[7:
0]data,delay;
regtemp;
always@(posedgeclk_inornegedgerst_n)//1us
if(!
rst_n)begin
delay<=8'd0;
ack<=2'b00;
end
else
begin
delay<=delay+1'b1;
if(ack==2'b00)
case(delay)
8'd1:
sda<=1;
8'd2:
scl<=1;//scl<=1;
8'd6:
sda<=0;
8'd9:
scl<=0;
8'd11:
sda<=1;//addwrh90/1
8'd15:
scl<=1;
8'd19:
scl<=0;
8'd21:
sda<=0;//0
8'd25:
scl<=1;
8'd29:
scl<=0;
8'd31:
sda<=0;//0
8'd35:
scl<=1;
8'd39:
scl<=0;
8'd41:
sda<=1;//1
8'd45:
scl<=1;
8'd49:
scl<=0;
8'd51:
sda<=0;//0
8'd55:
scl<=1;
8'd59:
scl<=0;
8'd61:
sda<=0;//0
8'd65:
scl<=1;
8'd69:
scl<=0;
8'd71:
sda<=0;//0
8'd75:
scl<=1;
8'd79:
scl<=0;
8'd81:
sda<=0;//0
8'd85:
scl<=1;
8'd89:
scl<=0;//end
8'd91:
sda<=1'bz;
8'd95:
scl<=1;
8'd98:
temp<=sda;
default:
if((delay>100))//&&(delay<255)&&(temp==0)
beginack<=2'b01;delay<=8'd0;scl<=0;end
endcase
elseif(ack==2'b01)
case(delay)
8'd2:
sda<=0;//h02controlbyte
8'd6:
scl<=1;
8'd10:
scl<=0;
8'd12:
sda<=0;//0
8'd16:
scl<=1;
8'd20:
scl<=0;
8'd22:
sda<=0;//0
8'd26:
scl<=1;
8'd30:
scl<=0;
8'd32:
sda<=0;//0
8'd36:
scl<=1;
8'd40:
scl<=0;
8'd42:
sda<=0;//0
8'd46:
scl<=1;
8'd50:
scl<=0;
8'd52:
sda<=0;//0
8'd56:
scl<=1;
8'd60:
scl<=0;
8'd62:
sda<=1;//1
8'd66:
scl<=1;
8'd70:
scl<=0;
8'd72:
sda<=1;//0
8'd76:
scl<=1;
8'd80:
scl<=0;//end
8'd82:
sda<=1'bz;
8'd86:
scl<=1;
8'd89:
temp<=sda;
default:
if((delay>90))//&&(delay<255)&&(temp==0)
beginack<=2'b10;delay<=8'd0;scl<=0;end
endcase
elseif(ack==2'b10)
case(delay)
8'd1:
sda<=1;
8'd2:
scl<=1;//scl<=1;
8'd6:
sda<=0;
8'd9:
scl<=0;
8'd11:
sda<=1;//addwrh91/1
8'd15:
scl<=1;
8'd19:
scl<=0;
8'd21:
sda<=0;//0
8'd25:
scl<=1;
8'd29:
scl<=0;
8'd31:
sda<=0;//0
8'd35:
scl<=1;
8'd39:
scl<=0;
8'd41:
sda<=1;//1
8'd45:
scl<=1;
8'd49:
scl<=0;
8'd51:
sda<=0;//0
8'd55:
scl<=1;
8'd59:
scl<=0;
8'd61:
sda<=0;//0
8'd65:
scl<=1;
8'd69:
scl<=0;
8'd71:
sda<=0;//0
8'd75:
scl<=1;
8'd79:
scl<=0;
8'd81:
sda<=1;//1
8'd85:
scl<=1;
8'd89:
scl<=0;//end
8'd91:
sda<=1'bz;
8'd95:
scl<=1;
8'd98:
temp<=sda;
default:
if((delay>100))//&&(delay<255)&&(temp==0)
beginack<=2'b11;delay<=8'd0;//sda<=1'bz;
scl<=1'b0;end
endcase
elseif(ack==2'b11)//readADC
case(delay)
8'd1:
sda<=1'bz;
8'd3:
scl<=1;
8'd5:
data[7]<=sda;
8'd8:
scl<=0;
8'd13:
scl<=1;
8'd15:
data[6]<=sda;
8'd18:
scl<=0;
8'd23:
scl<=1;
8'd25:
data[5]<=sda;
8'd28:
scl<=0;
8'd33:
scl<=1;
8'd35:
data[4]<=sda;
8'd38:
scl<=0;
8'd43:
scl<=1;
8'd45:
data[3]<=sda;
8'd48:
scl<=0;
8'd53:
scl<=1;
8'd55:
data[2]<=sda;
8'd58:
scl<=0;
8'd63:
scl<=1;
8'd65:
data[1]<=sda;
8'd68:
scl<=0;
8'd73:
scl<=1;
8'd75:
data[0]<=sda;
8'd78:
scl<=0;
8'd80:
sda<=0;//ack
8'd83:
scl<=1;
8'd88:
scl<=0;//querenwanbi
default:
if(delay>90)begin
delay<=8'd0;sda<=1'bz;//data_out<=data;ack<=2'b01;//xunhuan
ack<=2'b11;data_out<=data;
end
endcase
end
endmodule
三、数据转换
LIBRARYIEEE;
USEIEEE.STD_LOGIC_1164.ALL;
USEIEEE.STD_LOGIC_UNSIGNED.ALL;
USEIEEE.STD_LOGIC_ARITH.ALL;
ENTITYtransIS
PORT(datain:
INSTD_LOGIC_VECTOR(7DOWNTO0);
q1,q2,q3,q4:
OUTSTD_LOGIC_VECTOR(3DOWNTO0));
ENDtrans;
ARCHITECTUREbehaveOFtransIS
SIGNALdata0,data1:
STD_LOGIC_VECTOR(15DOWNTO0);
SIGNALsum1,sum2,sum3,sum4:
STD_LOGIC_VECTOR(4DOWNTO
0);
SIGNALc1,c2,c3:
STD_LOGIC_VECTOR(4DOWNTO0);
BEG