1.1 设计题目:数字频率计的EDA设计
1.2 设计要求
频率计EDA设计
1)简要说明
根据频率计的测频原理,按照测频量程需要,选择合适的时基信号即闸门时间,对输入被测信号进行技数,实现测频的目的。
2)任务和要求
设计一个3位十进制数字显示的数字式频率计,其频率测量范围在1MHZ内。量程分为10kHz,100kHz和1MHZ三档,即最大读数分别为9.99kHz,99.9kHz和999kHz。这里要求量程能够自动转换,具体要求如下:当读数大于999时,频率计处于超量程的状态,下一次测量时,量程自动增大1档。当读数小于099时,频率计处于欠量程的状态,下一次测量时,量程自动减小1档。当超过频率测量范围时,显示器显示出溢出。采用记忆显示方式,即计数过程中不显示数据,待计数结束后,显示测频结果,并将此显示结果保持到下次计数结束。显示时间不短于1秒。小数点位置随量程变化自动移位。数码管动态显示。
3)训练目标
具备硬件编程语言VHDL设计数字系统的初步能力,熟悉开发环境和流程,掌握技术方法。
2 设计思路
2.1数字频率计的测量方案选取
设计数器的计数值为N,则可得到被测信号频率为f =N。但是由于闸门的开通、关闭的时间与被测频率信号的跳变难以同步,因此采用此测量方法在低频段的相对测量误差可能达到50% ,即在低频段不能满足设计要求。在频率测量方法中,常用的有直接测频法、倍频法和等精度测频法。这三种方案各有利弊,其中直接测频法是依据频率的含义把被测频率信号加到闸门的输入端,只有在闸门开通时间T (以1 s计)内,被测(计数)的脉冲送到十进制计数器进行计数。但根据三个方案的分析,直接测频法比其他两个方案更加简单方便可行,直接测频法虽然在低频段测量时误差较大,但在低频段我们可以采用直接测周法测量,这样就可以提高测量精度了。
2.2 数字频率计的总体结构与原理
2.2.1总体结构
将被测信号通过整形电路,产生同频率的矩形波;计数部分根据所提供的矩形波的上升沿进行计数,计数时间则由选通时间控制部分决定,根据频率所处的范围来决定档位;将计数的结果输出给扫描显示电路,通过扫描,在数码管上显示频率的大小。
当系统复位时,开启电路,选通时间控制模块提供10MHz选通信号,并通过选通时间控制模块对选通时间长短进行控制,从而实现数字频率计的换挡。计数部分根据所提供的矩形波的上升沿进行计数,然后通过扫描显示模块对计数结果进行动态扫描显示。从而实现数字频率计的测量和显示过程。
2.2.2测频的原理
测频的原理归结成一句话,即在单位时间对被测信号进行计数。图2.2.1说明了测频的原理及误差产生的原因。
图 2.2.1 测频原理
在图2.2.1中,假设时基信号为1KHz,则用此法测得的待测信号为1KHz×7=70KHz。但从图中可以看出,待测信号应该在77 KHz左右,误差约有7/77~9.1%。这个误差是比较大的,实际上,测量的脉冲个数的误差会在±1之间。假设所测得的脉冲个数为N,则所测频率的最大误差为△=1/(N-1)×100%。显然,减小误差的方法就是增大N。本频率计要求测量结果以3位表示,则测频误差应为1%~0.1%,则N的取值范围为: 100≤N<1000
即时基信号的频率为量程中最地频率的1/100(同时约为最高频率的1/1000)。通过计算,得出表2.2.1中的数据。
表2.2.1 待测信号与时基信号的关系
待测信号/KHz | 时基信号/Hz |
100~999 | 1000 |
10~99.9 | 100 |
1~9.99 | 10 |
图3.1系统框图
4 各部分电路设计及参数计算
4.1分频模块的设计
当收到使能信号, 分频器启动, 将标准1 kHz 信号经3 次10 分频, 得到100 Hz, 10 Hz, 1 Hz 信号。1 Hz 信号既作为开关控制的时钟信号, 也作为显示电路自锁存器的取样时钟(即锁存器的输出使能信号)。1 kHz, 100 Hz,10 Hz 信号作为计数器闸门信号来控制计数, 以实现不同量程。分频部分程序:
library ieee;
use ieee.std_logic_11.all;
use ieee.std_logic_unsigned.all;
entity clk1hz is
port(clk:in std_logic;
q:out std_logic_vector(23 downto 0));
end clk1hz;
architecture func of clk1hz is
signal tq:std_logic_vector(23 downto 0);
begin
process(clk)
begin
if clk'event and clk='1' then tq<=tq+1;
end if;
end process;
q<=tq;
end func;
图4.1分频部分电路图
4.2计数模块设计
选通信号给定后,开始计数;从低位到高位,以十进制计数,最高能计到999;计数溢出,换档重计;当所测频率超过测量范围,则ov=1,使输出始终清零。选通时间内,在上升沿开始计数。
计数部分程序:
library ieee;
use ieee.std_logic_11.all;
use ieee.std_logic_unsigned.all;
entity count10 is
port(clk,clr,en:in std_logic;
cq:out std_logic_vector(3 downto 0);
carry_out:out std_logic);
end count10;
architecture func of count10 is
signal temp: std_logic_vector(3 downto 0);
begin
process(clk,clr,en)
begin
if clr='1' then temp<="0000";
elsif clk'event and clk='1' then
if en='1'then
if temp<"1001" then temp<=temp+1;
else temp<="0000";
end if;
end if;
end if;
end process;
process(temp)
begin
if temp="1001" then carry_out<='1';
else carry_out<='0';
end if;
end process;
cq<=temp;
end func;
图4.2.1 计数模块仿真图
图4.2.2 计数模块电路图
4.3选通时间控制模块设计
当计数到999时,由一个overflow正脉冲触发依次,change从状态“00”,“01”,“10”换档。
cout:process(res,overflow)
begin
if res='1' then
state<="000";
ov<='0';
change<="00";
elsif(overflow'event and overflow='1')then
case state is
when "000"=>state<="001";
change<="01";
when "001"=>state<="010";
change<="10";
when others=>state<="010";
change<="10";
ov<='1';
end case;
end if;
end process cout;
当CHANGE对应不同状态时limit_cnt的不同取值,大小将决定下一个选通时间。
begin
case state is
when"000"=>limit_cnt<=1000000;
when"001"=>limit_cnt<=100000;
when others=>limit_cnt<=10000;
end case;
end process limit;
4.4动态扫描模块设计
将计数输出的ONE,TEN,HUN信号通过数码管输出。SEL是位选信号,用来选择数码管。Q是输出的7位数据。从而实现了待测频率的动态显示输出。
library ieee;
use ieee.std_logic_11.all;
use ieee.std_logic_unsigned.all;
entity scan7 is
port(clk_scan: in std_logic;
en:out std_logic;
end scan7;
architecture behave of scan7 is
signal sl:std_logic_vector(2 downto 0);
signal bcd_out:std_logic_vector(3 downto 0);
begin
process(clk_scan)
begin
if clk_scan'event and clk_scan='1' then
end process;
process(sl)
begin
case sl is
when"000"=>bcd_out<="0001";
when"001"=>bcd_out<="0010";
when"010"=>bcd_out<="0011";
when"011"=>bcd_out<="0100";
when"100"=>bcd_out<="0101";
when"101"=>bcd_out<="0110";
when"110"=>bcd_out<="0111";
when others=>bcd_out<="0000";
end case;
end process;
process(bcd_out)
begin
case bcd_out is
when"0000"=>q<="0111111";
when"0001"=>q<="0000110";
when"0010"=>q<="1011011";
when"0011"=>q<="1001111";
when"0100"=>q<="1100110";
when"0101"=>q<="1101101";
when"0110"=>q<="1111101";
when"0111"=>q<="0000111";
when others=>q<="1111001";
end case;
end process;
en<='0';
sel<=sl;
endbehave;
仿真波形和动态扫描模块示意图
图4.4.1 动态扫描模块仿真图
图4.4.2 动态扫描模块示意图
4.5数字频率计仿真
程序清单如下:
library ieee;
use ieee.std_logic_11.all;
use ieee.std_logic_unsigned.all;
entity second is
port(en,irq,start,res,clk:in std_logic;
ov:buffer std_logic;
sel:out std_logic_vector(2 downto 0);
signal outdata:out std_logic_vector(6 downto 0));
end second;
architecture rtl of second is
signal one,ten,hun: std_logic_vector(3 downto 0);
signal cn,dn: std_logic;
signal limit_cnt: integer range 0 to 10000000;
signal overflow: std_logic;
signal state: std_logic_vector(2 downto 0);
signal disp_clk: std_logic;
signal change: std_logic_vector(1 downto 0);
type allowed_seg_states is (seg_a,seg_b, seg_c,seg_d,
seg_e,seg_f,seg_g,seg_dp);
type allowed_digit_states is(digit_o,digit_t,digit_h);
signal state_seg:allowed_seg_states;
signal state_digit:allowed_digit_states;
signal indata: std_logic_vector(3 downto 0);
signal dp_sel: std_logic;
begin
p2:process(clk)
variable dnt:integer range 0 to 1000000;
begin
if clk'event and clk='1' then
if res='1' or overflow='1' then
cn<='0';
dnt:=0;
else
if en='1' then
if(dnt cn<='0'; else cn<='1'; end if; end if; end if; end if; end process p2; p3:process(en,cn) begin if en='1' and cn='0' then dn<='1'; else dn<='0'; end if; end process p3; one_counter:process(res,irq,dn) begin if res='1' or ov='1' then one<="0000"; elsif irq'event and irq='1' then if(dn='1')then if(one<9)then one<=one+1; else one<="0000"; end if; end if; end if; end process one_counter; ten_counter:process(res,irq,dn) begin if res='1' or ov='1' then ten<="0000"; elsif irq'event and irq='1' then if(dn='1')then if ten=9 and one=9 then ten<="0000"; elsif(one=9)then ten<=ten+1; end if; end if; end if; end process ten_counter; hun_counter:process(res,irq,dn) begin if res='1' or ov='1' then hun<="0000"; elsif irq'event and irq='1' then if(hun=9 and ten=9 and one=9)then hun<="0000"; elsif(ten=9 and one=9)then hun<=hun+1; end if; end if; end process hun_counter; oveflow:process(res,irq,dn) begin if res='1' then overflow<='0'; elsif(irq'event and irq='1')then if(hun=9 and ten=9 and one=9)then overflow<='1'; else overflow<='0'; end if; end if; end process oveflow; cout:process(res,overflow) begin if res='1' then state<="000"; ov<='0'; change<="00"; elsif(overflow'event and overflow='1')then case state is when "000"=>state<="001"; change<="01"; when "001"=>state<="010"; change<="10"; when others=>state<="010"; change<="10"; ov<='1'; end case; end if; end process cout; limit:process(state) begin case state is when"000"=>limit_cnt<=1000000; when"001"=>limit_cnt<=100000; when others=>limit_cnt<=10000; end case; end process limit; clk_disp:process(clk) variable count:integer range 0 to 49; begin if res='1' then count:=0; disp_clk<='0'; elsif clk'event and clk='1'then if count=49 then disp_clk<=not disp_clk; count:=0; else count:=count+1; end if; end if; end process clk_disp; state_digitq:process(res,disp_clk) variable digit_state:allowed_digit_states; begin if res='1' then digit_state:=digit_o; elsif disp_clk'event and disp_clk='1' then case digit_state is when digit_o=> if state_seg=seg_dp then digit_state:=digit_t; end if; when digit_t=> if state_seg=seg_dp then digit_state:=digit_h; end if; when digit_h=> if state_seg=seg_dp then digit_state:=digit_o; end if; end case; end if; state_digit<=digit_state; end process state_digitq; state_segq:process(res,disp_clk) variable seg_state:allowed_seg_states; begin if res='1' then seg_state:=seg_a; elsif disp_clk'event and disp_clk='1' then case seg_state is when seg_a=>seg_state:=seg_b; when seg_b=>seg_state:=seg_c; when seg_c=>seg_state:=seg_d; when seg_d=>seg_state:=seg_e; when seg_e=>seg_state:=seg_f; when seg_f=>seg_state:=seg_g; when seg_g=>seg_state:=seg_dp; when seg_dp=>seg_state:=seg_a; end case; end if; state_seg<=seg_state; end process state_segq; selec:process(state_digit) variable dp:std_logic; variable gate:std_logic_vector(2 downto 0); begin dp:='0'; case state_digit is when digit_o=> indata<=one; gate:="000"; when digit_t=> indata<=ten; gate:="001"; if change="01" then dp:='1'; end if; when digit_h=> indata<=hun; gate:="010"; if change="10" then dp:='1'; end if; end case; dp_sel<=dp; sel<=gate; end process selec; bcdseg:process(indata) variable temp:std_logic_vector(6 downto 0); begin case indata is when"0000"=>temp:="0111111"; when"0001"=>temp:="0000110"; when"0010"=>temp:="1011011"; when"0011"=>temp:="1001111"; when"0100"=>temp:="1100110"; when"0101"=>temp:="1101101"; when"0110"=>temp:="1111101"; when"0111"=>temp:="0100111"; when"1000"=>temp:="1111111"; when"1001"=>temp:="1101111"; when others=>temp:="1000000"; end case; outdata(6 downto 0)<=temp; end process bcdseg; end rtl; 当输入频率irp为500KHz时,经过10ms仿真之后,change处于01状态即二挡,one,ten,hun分别为0,0,5即500,因为处于第二挡,所以小数点不显示,当数码管位选端处于2时,应显示hun位的7段译码数据,outdata为11011010即数码管显示5。当数码管位选端处于0时,应显示one位的7段译码数据,outdata为011111110即数码管显示0。当数码管位选端处于0时,应显示one位的7段译码数据,outdata为011111110即数码管显示0。 图4.5系统示意图 结 论 本次课程设计是实现基于VHDL语言设计一个数字频率计,该设计的可靠性高,成本低。硬件描述语言打破了硬件和软件设计人员之间互不干涉的界限,可以使用语言的形式来进行数字系统的硬件结构、行为的描述,直接设计数字电路硬件系统。使用语言描述的形式,大大缩短了开发周期,减少了开发难度,并使得系统更加灵活、稳健。利用EDA 软件进行编译优化仿真极大的减少了电路设计时间和可能发生的错误,降低了开发成本,这种设计方法将在未来的数字系统设计中发挥越来越重要的作用。 在这次为期2周的课程设计中,通过程序设计以及上机的软件操作使我更加熟悉VHDL语言的设计方法以及对MAX+plusII软件的应用。课设给我带来不少的收获,我了解VHDL设计的语言使用方法,并进一步熟悉MAX+plusII软件的使用和操作方法、波形仿真。提高了将理论应用于实践的能力,同时对我思考和解决问题的能力有了很大的锻炼。从课程设计中学到了不少平时上课难以学习的知识,提升了自我钻研、提出问题、发现问题解决问题的能力。 致 谢 在论文即将完成之际,谨向所有关心我的老师、同学和朋友表示衷心的感谢! 本论文是在伊老师的悉心指导、鼓励和支持下完成的。老师为我们的学业提供了良好的学习条件,还大力支持我们外出培训和实习,特别在此次设计中这些老师为我们提供了先进的硬件设备和学习材料,设计与实践相结合让我们对图像处理有了更深刻的了解,衷心感谢他的谆谆教导和悉心关怀。老师渊博的知识、丰富的经验、踏实认真的科研作风,严谨的治学态度给我留下了深刻的印象,特别是对科研方向的把握,对实验室的发展呕心沥血,这些将在今后的工作中继续给我以激励和指导。 此外还要衷心感谢我的同学,在报告的撰写期间,他们无私的帮助我,尽量为我创造条件和空间。 同时要感谢图书馆的工作人员,没有他们的热心服务,我也不会完成这次课程设计,在这里我感谢他们。 在这里我也要感谢学校,学校为我们提供了先进的学习设备和温馨的学习环境,我才能完成这次课程设计。 参考文献 [1] 孙延鹏,张芝贤,尹常永. VHDL与可编程逻辑器件应用. 北京:航空工业出版社,2006 [2] 曾繁泰,侯亚宁,崔元明. 可编程应用导论. 北京:清华大学出版社,2000 [3] 侯伯亨,顾新. VHDL硬件描述语言与数字逻辑电路设计. 西安:电子科技大学出版社,2002 [4] 谭会生,张昌凡.EDA技术及应用(第二版).西安:西安电子科技大学出版社,2004 [5] 李国洪,沈明山,胡辉.可编程器件EDA技术与实践.北京:机械工业出版社,2004