EDA原理及应用 何宾 2008.11
第十三章 数字电压表设计-本章概要 第 13章 本章给出了PLD器件在数字和模拟系统的典型应用-数 字电压表的设计。数字电压表实际上是一个模拟和数字混 合系统,该设计通过A/D转换器将模拟信号转换成离散的 数字量,通过可编程逻辑器件PLD进行处理,最后通过7 段数码管显示测量值。 该章首先介绍了数字电压表的功能要求和整体结构;随后具体介绍了数字电压表的模块设计,其中包括数字电压表的控制信号、ADC转换原理和控制模块的具体结构。本章最后详细描述了设计的具体实现过程,具体包括ADC控制模块的原理及实现、显示控制模块原理及实现、顶层模块的设计。
数字电压表设计-数字电压表的功能要求 第十三章 ● 数字电压表是一个模拟和数字混合系统,该数字电压表完成模拟直流信号的测试,并将结果在数码管上显示。数字电压表主要有以下几个功能: 1、模拟信号通过ADC0809转换为离散的数字量,设计模块和ADC0809通过并口连接,并且向ADC0809发出控制信号; 2、数字电压表设计模块,将外部的时钟信号分频后得到合适的采样时钟送给ADC0809; 3、每当ADC0809完成一次模/数转换过程后,设计模块对采样数据进行处理,并通过3个7段数码管显示测量的直流电压值。
第十三章 数字电压表设计-数字电压表的整体结构 ●
数字电压表设计-数字电压表的整体结构 第十三章 ● 从图中可以看出,实验平台上,在PLD和ADC0809之间加入了ADC控制模块,由于该模块的加入使PLD产生ADC控制模块可以识别的信号,然后送到ADC0809。图中的PLD的设计部分和ADC控制模块、7段数码管、外部时钟信号、按键进行连接。
数字电压表设计-数字电压表控制信号 第十三章 ● 该数字电压表的控制逻辑由PLD完成,该模块的输入和输出接口由下面信号组成: 1、输入信号 外部时钟信号(clk_in) 外部复位信号(reset) ADC转换后的数字信号(din) ADC转换完的中断信号(INTR)
数字电压表设计-数字电压表控制信号 第十三章 ● 2、输出信号 ADC片选信号(ncs) ADC读信号(nrd) ADC写信号(nwr) ADC通道选择信号(nadd) ADC时钟信号(nclock) LED选择信号(led_select) LED数码显示控制信号(seg)
数字电压表设计-ADC转换原理 第十三章 ● ADC0809是CMOS的8位A/D转换器,片内有8路模拟开关,可控制8个模拟量中的一个进入转换器中。ADC0809的分辨率为8位,转换时间约100us,含锁存控制的8路多路开关,输出有三态缓冲器控制,单5V电源供电。
数字电压表设计-ADC转换原理 第十三章 ●
数字电压表设计-控制模块结构 第十三章 ●
数字电压表设计-控制模块结构 第十三章 ● 1、ADC控制模块 ADC控制模块产生ADC控制模块需要的控制信号,同时读取ADC转换后的中断信号和数据信号。 该设计采用了教学实验系统,该系统的ADC控制模块接收ncs,nrd,nwr和nintr信号。图13.4给出了该模块的控制信号时序关系。
数字电压表设计-控制模块结构 第十三章 ● 2、显示控制模块 显示控制模块产生LED显示所需要的LED选择信号和LED数码控制信号。 3、采样时钟生成模块 采样时钟生成模块对外部输入的1MHz信号进行分频后,为ADC0809产生合适的采样时钟信号。 4、扫描时钟生成模块 扫描时钟生成模块对外部输入的1MHz信号进行分频后,为LED正确显示测量值产生合适的扫描时钟信号。
数字电压表设计-主要控制信号说明 第十三章 ● 1、START是转换启动信号,高电平有效; 2、ALE是3位通道选择地址(ADDC、ADDB、ADDA)信号的锁存信号。当模拟量送至某一输入端(如IN1或IN2等),由3位地址信号选择,而地址信号由ALE锁存;
数字电压表设计-主要控制信号说明 第十三章 ● 3、EOC是转换情况状态信号,当启动转换约100us后,EOC产生一个负脉冲,以示转换结束;在EOC的上升沿后,若使输出使能信号OE为高电平,则控制打开三态缓冲器,把转换好的8位数据结果输出至数据总线。至此ADC0809的一次转换结束了。
数字电压表设计-控制时序说明 第十三章 ●
数字电压表设计-实验箱控制信号 第十三章 ● 在实验仪器中CS与WR相与后接在了ALE和START端,CS与RD相与后接在了OE端,通过对时序和电路的综合考虑,建议使用如下的AD控制时序。
数字电压表设计-FSM的设计 第十三章 可以将整个控制分成4个步骤状态:S0、S1、S2、S3,各状态的动作方式如下: ● 可以将整个控制分成4个步骤状态:S0、S1、S2、S3,各状态的动作方式如下: 1、状态S0:CS=1、WR=1、RD=0(由控制器发出信号要求ADC0809开始进行模/数信号的转换)。 2、状态S1:CS=0、WR=0、RD=0 (ADC0809进行转换动作,转换完毕后INT将低电位升至高电位)。 3、状态S2: CS=1、WR=0、RD=1(由控制器发出信号以读取ADC0809的转换数据)。 4、状态S3: CS=0、WR=0、RD=0(由控制器读取数据总线上的数字转换数据)。
数字电压表设计-FSM的状态图描述 第十三章 ● S1 S2 S3 S4
数字电压表设计-FSM的设计 第十三章 由上述的四个状态可以归纳出整个控制器的动作功能有: ● 由上述的四个状态可以归纳出整个控制器的动作功能有: 1、负责在每个步骤送出所需的CS、WR、RD控制信号。 2、在状态S1时,监控INT信号是否由低变高,如此以便了解转换动作结束与否。 3、在状态S3,读取转换的数字量。
数字电压表设计-编码转换电路 第十三章 计算转换后的数字电压信号与BCD码的对应关系: ● 计算转换后的数字电压信号与BCD码的对应关系: 对8位的ADC0809而言,它的输出准位共有2**8=256种,即它 的分辨率是1/256。 VIN= 输入到 ADC0808的电压 Vfs= 满量程电压 VZ= 0电压 DX= 输出的数字量 DMAX= 最大数字量 DMIN= 最小数字量
数字电压表设计-编码转换电路 第十三章 ● 假设输入信号为0~5V电压范围,参考电压(Vref/2)为2.56V时,则它最小输出电压是5V/256=0.01953V,这代表ADC0809所能转换的最小电压值,我们在该实验中取最小电压准位为0.02V。当ADC0809收到的信号是01110110(76H),则其对应的电压值为: 76H×0.02V = 2.36V
数字电压表设计-编码转换电路 第十三章 ● 要实现电压值与BCD码的对应关系用多种方法(如查表法、比较法等)。查表法需要写大量的数据,比较麻烦,在示例程序中使用了比较法。
数字电压表设计-具体算法 第十三章 例如:10100101表示165*2=330=101001010 ● 例如:10100101表示165*2=330=101001010 165/255*5=3.26,用三个七段数码管显示,分离3 2 6 =0011 ,0010,0110 将1010高四位,0101低四位分离. 0101表示0000,0000,1010, BCD码1 1010表示0010,1100,0000, BCD码2 下面就是BCD码1+BCD码2
数字电压表设计-具体算法 第十三章 ● 0000,0000,1010 + 0010,1100,0000, 0010,1100,1010 0000,0011,0000 比如:9+1=10, 6+7=13, BCD码的加法实际上就是10进制的加法 判断: 由于BCD码显示0-9,所以加法运算要符合BCD码的运算 当>9时,BCD+6,并且+1进位 否则<9,BCD<=BCD+1
数字电压表设计-VHDL描述 第十三章 library IEEE; use IEEE.STD_LOGIC_1164.ALL; ● library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; library work; use work.disp_driver.all; entity disp_controller is port( rst : in std_logic; scan_clk : in std_logic; din : in std_logic_vector(7 downto 0); sel : out std_logic_vector(1 downto 0); seg : out std_logic_vector(6 downto 0); dp : out std_logic); end disp_controller;
数字电压表设计-VHDL描述 第十三章 architecture Behavioral of disp_controller is ● architecture Behavioral of disp_controller is signal vol_value : std_logic_vector(7 downto 0); signal bcd_value : std_logic_vector(11 downto 0); signal bcd_h,bcd_l : std_logic_vector(11 downto 0); signal scan_out : std_logic_vector(1 downto 0); begin
数字电压表设计-VHDL描述 第十三章 ● process(rst,scan_clk) begin if(rst='0')then vol_value<="00000000"; bcd_value<="000000000000"; elsif(rising_edge(scan_clk))then vol_value<=din; bcd_h<=bin_bcd(vol_value(7 downto 4),'1'); bcd_l<=bin_bcd(vol_value(3 downto 0),'0'); bcd_value<=bcd_h+bcd_l; if(bcd_value(3 downto 0)>"1001")then bcd_value<=bcd_value+"000000000110"; end if; if(bcd_value(7 downto 4)>"1001")then bcd_value<=bcd_value+"000001100000"; end process;
数字电压表设计-VHDL描述 第十三章 ● process(scan_clk) begin if(rising_edge(scan_clk))then if(scan_out="10")then scan_out<="00"; else scan_out<=scan_out+'1'; end if; end process;
数字电压表设计-VHDL描述 第十三章 ● process(scan_out) begin case scan_out is when "00" => seg<=display(bcd_value(3 downto 0));sel<="00";dp<='0'; when "01" => seg<=display(bcd_value(7 downto 4)); sel<="01";dp<='0'; when "10" => seg<=display(bcd_value(11 downto 8));sel<="10";dp<='1'; when others => seg<=display("1111");sel<="11";dp<='1'; end case; end process; end Behavioral;
数字电压表设计-程序包的设计 第十三章 ● 在该设计中,在处理数码管显示部分会多次使用到BCD码到7段码,为了提高对程序代码的复用和减少程序代码长度,在设计中将BCD码到7段码的转换过程通过函数调用实现。下面给出在程序包中的函数声明过程。
数字电压表设计-程序包的设计 第十三章 ● library IEEE; use IEEE.STD_LOGIC_1164.all; package disp_driver is function display(a : in std_logic_vector(3 downto 0) ) return std_logic_vector; function bin_bcd(bin : in std_logic_vector(3 downto 0); flag : std_logic) return std_logic_vector; end disp_driver;
数字电压表设计-程序包的设计 第十三章 ● package body disp_driver is function bin_bcd(bin : std_logic_vector;flag : std_logic) return std_logic_vector is variable bcd_x : std_logic_vector(11 downto 0); begin if(flag='0')then case bin is when "0000" => bcd_x:="000000000000"; when "0001" => bcd_x:="000000000010"; when "0010" => bcd_x:="000000000100";when "0011"=> bcd_x:="000000000110"; when "0100"=> bcd_x:="000000001000";when "0101"=> bcd_x:="000000001010"; when "0110"=> bcd_x:="000000001100";when "0111"=> bcd_x:="000000001110"; when "1000"=> bcd_x:="000000010000";when "1001"=> bcd_x:="000000010010"; when "1010"=> bcd_x:="000000100000";when "1011"=> bcd_x:="000000100010"; when "1100"=> bcd_x:="000000100100";when "1101"=> bcd_x:="000000100110"; when "1110"=> bcd_x:="000000101000";when "1111"=> bcd_x:="000000110000"; when others => bcd_x:="111111111111"; end case; elsif(flag='1')then
数字电压表设计-程序包的设计 第十三章 ● case bin is when "0000" => bcd_x:="000000000000";when "0001" => bcd_x:="000000110010"; when "0010" => bcd_x:="000001100100";when "0011"=> bcd_x:="000010010110"; when "0100"=> bcd_x:="000100101000";when "0101"=> bcd_x:="000101100000"; when "0110"=> bcd_x:="000110010010";when "0111"=> bcd_x:="001000100100"; when "1000"=> bcd_x:="001001010110";when "1001"=> bcd_x:="001010001000"; when "1010"=> bcd_x:="001100110010";when "1011"=> bcd_x:="001101010010"; when "1100"=> bcd_x:="001110000100";when "1101"=> bcd_x:="010000010110"; when "1110"=> bcd_x:="010001001000";when "1111"=> bcd_x:="010010000000"; when others => bcd_x:="111111111111"; end case; end if; return bcd_x; end bin_bcd;
数字电压表设计-程序包的设计 第十三章 ● function display (a : std_logic_vector ) return std_logic_vector is variable r : std_logic_vector(6 downto 0); begin case a is when "0000" => r:="0111111"; when "0001" => r:="0000110"; when "0010" => r:="1011011"; when "0011" => r:="1001111"; when "0100" => r:="1100110"; when "0101" => r:="1101101"; when "0110" => r:="1111101"; when "0111" => r:="0000111"; when "1000" => r:="1111111"; when "1001" => r:="1101111"; when others => r:="1111111"; end case; return r; end display; end disp_driver;
数字电压表设计-顶层模块 第十三章 ● library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity top is port( rst : in std_logic; clk : in std_logic; int : in std_logic; cs : out std_logic; wr : out std_logic; rd : out std_logic; din : in std_logic_vector(7 downto 0); sel : out std_logic_vector(1 downto 0); seg : out std_logic_vector(6 downto 0); dp : out std_logic); end top;
数字电压表设计-顶层模块 第十三章 architecture Behavioral of top is ● architecture Behavioral of top is signal d : std_logic_vector(7 downto 0); component adc0809_controller port( clk : in std_logic; rst : in std_logic; int : in std_logic; cs : out std_logic; wr : out std_logic; rd : out std_logic; din : in std_logic_vector(7 downto 0); dout : out std_logic_vector(7 downto 0) ); end component;
数字电压表设计-顶层模块 第十三章 component disp_controller port( rst : in std_logic; ● component disp_controller port( rst : in std_logic; scan_clk : in std_logic; din : in std_logic_vector(7 downto 0); sel : out std_logic_vector(1 downto 0); seg : out std_logic_vector(6 downto 0); dp : out std_logic); end component;
数字电压表设计-顶层模块 第十三章 Inst_adc0809_controller1: adc0809_controller ● Inst_adc0809_controller1: adc0809_controller port map( clk =>clk, rst =>rst, int =>int, cs =>cs, wr =>wr, rd =>rd, din =>din, dout =>d );
数字电压表设计-顶层模块 第十三章 Inst_disp_controller1:disp_controller port map( ● Inst_disp_controller1:disp_controller port map( rst=>rst, scan_clk=>clk, din=>d, sel =>sel, seg =>seg, dp =>dp ); end Behavioral;
数字电压表设计-顶层约束 第十三章 第十三章 ● 该设计在基于xilinx的SPARTAN3的xc3s400pqg208-4c器件上实现,在百科融创的EDA-IV实验平台上测试完成,在验证前,要进行设计约束,在这里只对管脚进行约束。该约束文件的格式是Xilinx的用户约束文件UCF的格式。采用不同的EDA平台时,需要使用不同的用户约束文件格式。下面的约束仅供读者参考。
数字电压表设计-顶层约束 第十三章 ● #PACE: Start of Constraints generated by PACE #PACE: Start of PACE I/O Pin Assignments NET "clk" LOC = "p72" ; NET "cs" LOC = "p68" ; NET "din<0>" LOC = "p65" ; NET "din<1>" LOC = "p63" ; NET "din<2>" LOC = "p61" ; NET "din<3>" LOC = "p57" ; NET "din<4>" LOC = "p51" ; NET "din<5>" LOC = "p48" ; NET "din<6>" LOC = "p45" ; NET "din<7>" LOC = "p43" ; NET "dp" LOC = "p40" ; NET "int" LOC = "p37" ; NET "rd" LOC = "p35" ; NET "rst" LOC = "p33" ; NET "seg<0>" LOC = "p27" ; NET "seg<1>" LOC = "p24" ; NET "seg<2>" LOC = "p21" ; NET "seg<3>" LOC = "p19" ; NET "seg<4>" LOC = "p16" ; NET "seg<5>" LOC = "p13" ; NET "seg<6>" LOC = "p11" ; NET "sel<0>" LOC = "p9" ; NET "sel<1>" LOC = "p5" ; NET "wr" LOC = "p7" ; #PACE: Start of PACE Area Constraints #PACE: Start of PACE Prohibit Constraints #PACE: End of Constraints generated by PACE
第13章 习 题 1、说明基于PLD的数字电压表的结构及其实现原理。 2、在ISE软件和相关的硬件平台上完成本章所介绍的数字电压表的设计。