EDA课程设计 数字电压表 代码及 报告
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
第一部分项目名称、内容与要求
项目名称:数字电压表设计
1.1 设计内容
利用FPGA与模数转换器ADC0809设计一个数字电压表,能够测量0~5V之间的直流电压,用四个数码管显示被测电压,要求精确到小数点后三位数字。
了解数字电压表的工作原理,掌握可编程逻辑器件与模数转换器之间的接口电路设计及调试方法。
下载并测试电路功能,分析芯片资源的占用情况。
1.2 具体要求
1)、能正确测量0-5∨模拟电压,误差<1%,数字电压值分别由四个数码管显示。
(2)、FPGA芯片产生ADC0809控制信号和七段显示器断码和位码等。
(3)、ADC0809芯片实现8位模数转换,输入0-5∨,输出00H-FFH。
(4)、ADC0809输出00H-FFH送FPGA芯片处理为十进制数百十个等位,并产生动态显示位码和断码。
(5)、FPGA芯片产生ADC0809芯片需要写、读和片选信号等,注意时序。
(6)、了解掌握A/D(模数)转换器芯片ADC0809的转换原理、管脚定义以及实际用法。
第二部分:系统整体架构(Architecture Description)
2.1 设计思路
数字电压表(Digital V oltmeter)简称DVM,是一种用数字显示的电压测量仪表。
由于数字电压表具有读数准确方便、精度高、误差小、灵明度高和分辨率高、测量速度快等特点而备受青睐。
其基本理是采用数字化测量技术,对直流电压进行模数转换,转换成不连续、离散的数字形式并加以显示。
由此可知数字电压表的设计应包括三个主要部分:作为电压采样端口的模数转换单元、数据处理单元及电压值显示单元。
设计要求利用ADC0809模数转换器,FPGA 作为数据处理的核心器件,用LED和数码管进行电压值的显示。
系统结构框图如下图所示。
2.2 系统原理(包含:框图等阐述)与设计说明等内容
1、模数转换器工作原理
A/D转换器芯片ADC0809简介8路模拟信号的分时采集,片内有8路模拟选通开关,以及相应的通道抵制锁存用译码电路,其转换时间为100μs左
右。
输入电压范围0~5V,该芯片内部有输出数据锁存器。
ADC0809芯片外引脚如下所示。
其中V IN(+)、V IN(-)为ADC0809的模拟信号输入端,用以接受单极性、双极性或差模输入信号;D0~D7为A/D转换器数字信号输出端,CLKIN为外电路提供的时钟脉冲输入端,频率限制在100KHz~1460KHz ;CLKR为内部时钟发生器外接电阻端,与CLKIN端配合可有芯片自身产生时钟脉冲,频率为1/1.1RC。
ADC0809的工作时序,当片选信号CS与写输入信号WR同时为低电平时,A/D转换器启动,在WR上升沿后100us完成模数转换,转换结果存入芯片内部的输出数据锁存器,如图7-3(a)所示。
转换结束输出信号INTR自动变为低电平,表示本次转换已结束。
如CS、读输入信号RD同时为低电平,则数据锁存器三态门打开,数字信号送出至输出端D0~D7,RD高电平到来后数据锁存器三态门回到高阻状态。
2.数据处理及显示单元
FPGA芯片负责ADC0809A/D转换过程的启动以及转换数据的读取。
同时,把读取的8位二进制数据转换成便于输出的3位LED 段码送给LED数码管显示。
因此FPGA部分的程序设计应包括ADC0809转换接口控制模块、数据转换模块、译码模块,FPGA电路设计原理。
本设计采用5V,由于模数转换器件ADC0809的数字输出为8位,则电压的最小分辨率为0.02V,也就是说若转换后的数据为00H,则对应的电压值为0V,转换后的数据为01H,则对应电压值为0.02V,以此类推,若将转换数据以一定的规则从小到大存放,则可得到转换数据与实际电压值,以及数据存放地址间的对应关系见表7-1.若将电压数值的每一位用4位BCD码表示(不包括小数点),则
可得如表7-1所示的高四位BCD码和低四位BCD码。
ADC0809转换数据与实际电压值对应关系
表7-1
分析表7-1的数据,可知数据转换模块的设计可以有两种方法:查表法和计算法,下面对计算法进行介绍。
计算法的设计思路如下:由表7-1可知,如果将转换后的高、低四位字节数据看做是一个8位二进制数的话,电压值与转换后的数据之间有一个2倍的关系(不考虑小数点),假设转换后的数据为“11011110”,“11011110”对应的十进制数为222,222*2=444,与“11011110”对应的4.44V电压值相等,而十进制数的显示可以通过对10取模和取余的方法依次获得个位、十位、百位,分别显示即可,显示时需要在最高位后加一个小数点显示。
如果采用计算法实现数据处理,FPGA设计中需要采用乘法、除法电路才能实现数据处理。
数据处理电路流程图如图
2.3 创新点与原创性内容
总体来说本次实训的代码还是从图书馆和网上查找的,可并没那么顺利的将实训做得达到要求,本次实训本组在查阅的资料里大胆组合创新(采用AD控制元件,BCD 8位转12位,三选一数据选择器,位选信号产生器,三进制计数器,七段译码器,小数点产生器)模块,除了AD控制元件模块外后面的模块本组就利用了一个代码将其终合,这样减少了连线,更为简洁。
最后在实践的面前结果就在面前。
第三部分系统设计 (含HDL或原理图输入设计)
3.1 HDL 代码
BCD 8位转12位,三选一数据选择器,位选信号产生器,三进制计数器,七段译码器,小数点产生器)终合模块代码
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; entity ADCCL is
port(clk:in std_logic;
a:in std_logic_vector(7 downto 0);
rd,wr,cs: out std_logic; da:out
std_logic_vector(7 downto 0);
w:out std_logic_vector(2 downto 0)
);
end ADCCL;
architecture behave of ADCCL is
signal daa: std_logic_vector(7 downto 0);
signal p: std_logic;
signal wei: std_logic_vector(2 downto 0);
signal q: integer range 0 to 9; signal wqian: integer range 0 to 5;
signal wbai: integer range 0 to 9;
signal wshi: integer range 0 to 9;
signal wge: integer range 0 to 9; begin
process(clk,a)
variable qq: integer range 0 to 6000000;
variable qian:integer range 0 to 5;
variable bai: integer range 0 to 9;
variable shi: integer range 0 to 9;
variable ge: integer range 0 to 9;
variable baii: integer range 0 to 1000000;
variable shll: integer range 0 to 100000;
variable gee: integer range 0 to 10000;
begin
qq:=conv_integer(a)*19610;
if qq>=0 and qq<=999999 then qian:=0;
elsif qq>=1000000 and qq<=1999999 then qian:=1;
elsif qq>=2000000 and qq<=2999999 then qian:=2;
elsif qq>=3000000 and qq<=3999999 then qian:=3;
elsif qq>=4000000 and qq<=4999999 then qian:=4;
elsif qq>=5000000 and qq<=5999999 then qian:=5;
else qian:=0;
end if;
baii:=(qq-qian*1000000);
if baii>=0 and baii<=99999 then bai:=0;
elsif baii>=100000 and baii<=199999 then bai:=1;
elsif baii>=200000 and baii<=299999 then bai:=2;
elsif baii>=300000 and baii<=399999 then bai:=3;
elsif baii>=400000 and baii<=499999 then bai:=4;
elsif baii>=500000 and
baii<=599999 then bai:=5;
elsif baii>=600000 and baii<=699999 then bai:=6;
elsif baii>=700000 and baii<=799999 then bai:=7;
elsif baii>=800000 and baii<=899999 then bai:=8;
elsif baii>=900000 and baii<=999999 then bai:=9;
else bai:=0;
end if;
shll:=((qq-qian*1000000)-bai*10 0000);
if shll>=0 and shll<=9999 then shi:=0;
elsif shll>=10000 and shll<=19999 then shi:=1;
elsif shll>=20000 and shll<=29999 then shi:=2;
elsif shll>=30000 and shll<=39999 then shi:=3;
elsif shll>=40000 and shll<=49999 then shi:=4;
elsif shll>=50000 and shll<=59999 then shi:=5;
elsif shll>=60000 and shll<=69999 then shi:=6;
elsif shll>=70000 and shll<=79999 then shi:=7;
elsif shll>=80000 and shll<=89999 then shi:=8;
elsif shll>=90000 and shll<=99999 then shi:=9;
else shi:=0;
end if;
gee:=(((qq-qian*1000000)-bai*10 0000)-(shi*10000));
if gee>=0 and gee<=999 then ge:=0;
elsif gee>=1000 and gee<=1999 then ge:=1;
elsif gee>=2000 and gee<=2999 then ge:=2;
elsif gee>=3000 and gee<=3999 then ge:=3;
elsif gee>=4000 and gee<=4999 then ge:=4;
elsif gee>=5000 and gee<=5999 then ge:=5;
elsif gee>=6000 and gee<=6999 then ge:=6;
elsif gee>=7000 and gee<=7999 then ge:=7;
elsif gee>=8000 and gee<=8999 then ge:=8;
elsif gee>=9000 and gee<=9999 then ge:=9;
else ge:=0;
end if;
wqian<=qian;wbai<=bai;wshi<=shi
;wge<=ge;
end process;
process(clk)
variable
cnt:std_logic_vector(2 downto 0);
begin
if clk'event and clk='1' then
if cnt<3 then cnt:=cnt+1;
else cnt:="000";p<=not p;
end if;
wei<=cnt;
case cnt is
when"000"=>q<=wqian; when"001"=>q<=wbai;
when"010"=>q<=wshi;
when"011"=>q<=wge;
when others=>null;
end case;
end if;
wr<=p; rd<='1'; cs<='0';
end process;
process(q)
begin
case q is
when 0=>daa<="11111100"; when 1=>daa<="01100000"; when 2=>daa<="11011010"; when 3=>daa<="11110010"; when 4=>daa<="01100110"; when 5=>daa<="10110110"; when 6=>daa<="10111110"; when 7=>daa<="11100000"; when 8=>daa<="11111110"; when 9=>daa<="11110110"; when others=>null;
end case;
end process;
process(wei,daa)
begin
if wei="000" then
w<=wei; da<=daa or"00000001";
else
w<=wei; da<=daa;
end if;
end process;
end behave;
AD控制元件代码
IBRARY ieee; --A/D0809
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all;
entity ad is
port(ST,eoc:in std_logic; --控制端口
d:in std_logic_vector(7 downto 0); oe,sta,ale,adda:out std_logic; q:out std_logic_vector(7 downto 0));
end ad;
architecture a of ad is
type states
is(st0,st1,st2,st3,st4,st5,st6); --7个状态
signal
c_state,n_state:states :=st0; signal regl:std_logic_vector(7 downto 0);
signal lock:std_logic;
begin adda<='1';
com:process(c_state,eoc)
begin
case c_state is
when
st0=>ale<='0';sta<='0';oe<='0'; lock<='0';
n_state<=st1;
when
st1=>ale<='1';sta<='0';oe<='0'; lock<='0';
n_state<=st2;
when
st2=>ale<='0';sta<='1';oe<='0'; lock<='0';
n_state<=st3;
when
st3=>ale<='0';sta<='0';oe<='0'; lock<='0';
if(eoc='1') then n_state<=st4; else n_state<=st3; ――eoc为‘1’转换结束进入下一状态
end if; ――否则继续转换
when
st4=>ale<='0';sta<='0';oe<='1';lock<='0';
n_state<=st5; when
st5=>ale<='0';sta<='0';oe<='0';lock<='1'; n_state<=st6; when
st6=>ale<='0';sta<='0';oe<='0';lock<='1';
n_state<=st0;
when others=>n_state<=st0; end case;
end process com;
reg:process(st)
begin
if(st'event and st='1') then c_state<=n_state; end if;
end process reg;
lo:process(lock) --锁存 begin
if(lock'event and lock='1') then regl<=d; end if;
end process lo; q<=regl; end a;
3.2 系统整体电路图(或RTL 级电路图)
第四部分:系统仿真(Simulation
Waveform)
系统仿真图如图:仿真前输入设置图:
功能仿真图:
时序仿真图:
第五部分:FPGA实现(FPGA Implementation)1、硬件验证
在前两次代码无误但下载到芯片硬件验证,始终不能满足要求时,经过查阅资料和老师指导。
和本组成员的不放弃的努力下。
改正过RTL原理图后,怀着试一试的态度和必胜的心态又一次下载到硬件验证。
2、操作过程
下载成功后,我们可以通过AD装换芯片ADC0809(详见附录)的功能,通过:A/B/C三段的不同84321BCD码状态来得到此芯片八个频道具体是哪一频道。
(注:000选CH0;001选CH1…)然后将相应的频道接到直流电压(0——5V)。
当然输出显示为数码管显示和3个LED灯(3个LED灯主要是显示的是CS,RD,WD)。
3、结果等说明
在实验箱上的左上角的直流电压旋钮旋到最小处时数码管显示为:0:.000,当旋到最大处时数码管显示为:5:.000,中间的值位0V——5V之间。
第六部分:总结(Closing)
这次数字电压表系统的设计达到了预期的效果,这次设计的内容主要体现在程序算法上。
电压值。
此程序下载后占用芯片内存小易实现。
,DVM的高速发展,使它已成为实现
量的采集资料的过程。
在这个过程里我们走过需对弯路和冤枉路。
这些都是我们宝贵的
字系统设
参考书目(Reference):
EDA技术与实验———陈立万陈强赵威威李洪兵姜玉泉电子设计自动化(EDA)课程设计与项目实例——李莉路而红
附录(Appendix):
A/D转换器芯片ADC0809简介 8
路模拟信号的分时采集,片内有8路
模拟选通开关,以及相应的通道抵制
锁存用译码电路,其转换时间为100
μs左右。
1. ADC0809的内部结构
ADC0809的内部逻辑结构图如图9-7所示。
图9.7 《ADC0809内部逻辑结构》图中多路开关可选通8个模拟通道,允许8路模拟量分时输入,共用一个A/D转换器进行转换,这是一种经济的多路数据采集方法。
地址锁存与译码电路完成对A、B、C 3个地址位进行锁存和译码,其译码输出用于通道选择,其转换结果通过三态输出锁存器存放、输出,因此可以直接与系统数据总线相连,表9-1为通道选择表。
2.信号引脚
ADC0809芯片为28引脚为双列直插式封装,其引脚排列见图9.8。
对ADC0809主要信号引脚的功能说明如下:
IN7~IN0——模拟量输入通道
ALE——地址锁存允许信号。
对应AL E上跳沿,A、B、C地址状态送入地址锁存器中。
START——转换启动信号。
START上升沿时,复位ADC0809;START下降沿时启动芯片,开始进行A/D转换;在A/D转换期间,START应保持低电平。
本信号有时简写为ST.
A、B、C——地址线。
通道端口选择线,A为低地址,C为高地址,引脚图中为ADDA,ADDB和ADDC。
其地址状态与通道对应关系见表9-1。
CLK——时钟信号。
ADC0809的内部没有时钟电路,所需时钟信号由外界提供,因此有时钟信号引脚。
通常使用频率为500KHz的时钟信号
EOC——转换结束信号。
EOC=0,正在进行转换;EOC=1,转换结束。
使用中该状态信号即可作为查询的状态标志,又可作为中断请求信号使用。
D7~D0——数据输出线。
为三态缓冲输出形式,可以和单片机的数据线直接相连。
D0为最低位,D7为最高
OE——输出允许信号。
用于控制三态输出锁存器向单片机输出转换得到的数据。
OE=0,输出数据线呈高阻;OE=1,输出转换得到的数据。
Vcc—— +5V电源。
Vref——参考电源参考电压用来与输入的模拟信号进行比较,作为逐次逼近的基准。
其典型值为+5V(Vref(+) =+5V, Vref(-)=-5V).
9.2.2 MCS-51单片机与ADC0809的接口
ADC0809与MCS-51单片机的连接如图9.10所示。
电路连接主要涉及两个问题。
一是8路模拟信号通道的选择,二是A/D转换完成后转换数据的传送。
3.ADC0809的接口
电路连接主要涉及两个问题。
一是8路模拟信号通道的选择,二是A/D转换完成后转换数据的传送。
如图9.11所示模拟通道选择信号A、B、C分别接最低三位地址A0、A1、A2即(P0.0、P0.1、P0.2),而地址锁存允许信号ALE由P2.0控制,则8路模拟通道的地址为0FEF8H~0FEFFH.此外,通道地址选择以作写选通信号,这一部分电路连接如图9.12所示。
图9.11 ADC0809的部分信号连接
图9.12 信号的时间配合。