2.1数字频率计功能概述
数字频率计数器的基本功能是测量一个频率稳定度高的频率源的频率。通常情况下计算每秒内待测信号的脉冲个数,此时我们称闸门时间为1秒。闸门时间也可以大于或小于一秒。闸门时间越长,得到的频率值就越准确,但闸门时间越长则没测一次频率的间隔就越长。闸门时间越短,测的频率值刷新就越快,但测得的频率精度就受影响。本数字频率计是用数字显示被测信号频率的仪器,被测信号可以是正弦波,方波或其它周期性变化的信号。
2.2 基本工作原理及设计思路
根据频率计设计的设计要求,我们可将整个电路系统划分为几个基本模块,各模块均有几种不同的设计方案。
频率测量模块
直接测频法:把被测频率信号经脉冲整形电路处理后加到闸门的一个出入端,只有在闸门开通时间T(以秒计)内,被计数的脉冲送到十进制计数器进行计数;设计数器的值为N,则可得到被测信号频率为f=N/T,经分析,本测量在低频率的相对测量误差较大,即在低频段不能满足本设计的要求。
组合测频法:是指在高频是采用直接测频法,低频是采用直接测量周期法测信号的周期,然后换算成频率;这种方法可以在一定程度上弥补方法(1)中的不足,但是难以确定最佳分测点,且电路实现较复杂。
倍频法:是指把频率测量范围分成多个频段,使用倍频技术,根据频段设置倍频系数,将经整形的低频信号进行倍频后在进行测量,对高频段则直接进行测量。倍频法较难实现。
等精度测频法:其实现方式可用图来说明。图中,预置门控信号是宽度为TPR的一个脉冲,CNT1和CNT2是两个可控计数器。标准频率信号从CNT1的时钟输出端CLK输入,其频率为fs,经整形后的被测信号从CNT2的时钟输入端CLK输入,设其实际频率为fx;当预置门控信号为高时,经整形后的被测信号的上升沿通过D触发器的Q端同时启动计数器CNT1和CNT2。CNT1和CNT2分别对被测信号(频率为fs)和标准频率信号(频率为fx)同时计数。当预置门信号为低时,随后而至的被测信号的上升沿将两个计数器同时关闭。设在一次预置门时间Tpr内对被测信号的计数值为Nx,对标准信号的计数值为Ns。则下式成立:
fx/Nx=fs/Ns (2-1)
由此推得
fx=fs*Nx/Ns (2-2)
等精度原理框架图如下:
若所测频率值为fx,其真实值为fxe,标准频率为fs,一次测量中,由于fx计数的起停时间都是该信号的上跳沿触发的,因此在Tpr时间内对fx的计数Nx无误差,在此时间内的计数Ns最多相差一个脉冲,则下式成立:
fx/Nx=fs/Ns (2-3)
fex/Nx=fs/Ns+△et (2-4)
可分别推得
fx=fs*Nx/Ns (2-5)
fex=fs*Nx/Ns+△et (2-6)
根据相对误差的公式有:
△fxe/fxe=fxe-fx/fxe (2-7)
经整理可得到:
△fxe/fxe=△et/Ns (2-8)
因△et≤1,故△fxe/fxe≤1/Ns
Ns=Tpr*fs (2-9)
根据以上分析,我们可知等精度测频法具有三个特点:1,相对测量误差与被测频率的高低无关;2,增大Tpr或fs可以增大Ns,减少测量误差,提高测量精度;3,测量精度与预置门宽度和标准频率有关,与被测信号的频率无关,在预置门和常规测频闸门时间相同而被测信号频率不同的情况下,等精度测量法的测量精度不变。
3.1总FPGA仿真图
图3.1 软件仿真总GDF图
3.2 模块分图
3.2.1 数据产生模块
Nb,Nx.为16bit。
图3.2 数据产生模块
上图数据产生的工作原理:fb频率是由24M400分频提供,由2个D触发器构成控制电路,在fx输入的时候,对第一个D触发器开始时Q=1,此时计数器处于计数状态,当控制循环信号来一个时钟上升沿第二个D触发器Q=D=0,由于那个1经非门得0,此时由门控制电路得到第一个触发器Q=D=0,当第一个D触发器由1变为0时,两计数器停止计数,此信号经后一个非门得到一个上升沿,在上升沿时两个数所存到buffer中,在接下来的高电平时,两计数器清零。由D触发器的性质得:第二个触发器瞬间被置位为1,从而反馈到上一个触发器使其Q=D=1,从而让两计数器又开始计数,当控制信号再来下一个时钟上升沿的时候,又对上第一个D触发器置位是0,而两个计数器还在计数,当fx得时钟上升沿刚好来的时候与fb刚好,此时计数完成,而对计数器清零则延时一段时间再清,从而避免数据丢失,这样在门控信号的作用下,计数器循环计数。
3.2.2 数据处理模块
图3.3 数据处理模块1
分析:对于两个buffer输出的数据接由FPGA生成的LPM除法和乘法模块进行计算,最后得到的数据是16进制,为了能在数码管上显示我们将其转化为10进制,用BCD码显示。而在转换模块里我们用的是除法取商舍余,最后输出显示。原理图如下:
图3.3 数据处理模块2
4.1 计数器设计
计数模块在闸门时间内对被测信号进行计数, 并根据被测输入信号的频率范围自动切换量程, 控制小数点显示位置。
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
ENTITY CNT10 IS
PORT(
C : IN STD_LOGIC; CLK : IN STD_LOGIC; --计数时钟信号--
C_EN : IN STD_LOGIC; --计数使能--
CARRY_OUT : OUT STD_LOGIC; --进位输出--
Q_OUT : OUT STD_LOGIC_VECTOR(3 DOWNTO 0)
);
END CNT10;
ARCHITECTURE BEHAVIOR OF CNT10 IS
SIGNAL CNT_SL:STD_LOGIC_VECTOR(3 DOWNTO 0);
BEGIN
PROCESS(C,CLK,C_EN)
BEGIN
IF C='0' THEN --计数器异步清零--
CNT_SL<=(OTHERS=>'0');
ELSIF(CLK'EVENT AND CLK='1')THEN
IF C_EN='1' THEN
IF CNT_SL < 9 THEN
CNT_SL<=CNT_SL+1;
ELSE CNT_SL <= (OTHERS=>'0');
END IF;
END IF;
END IF;
IF(CNT_SL= 9 AND C_EN='1')THEN
CARRY_OUT<='1';
ELSE CARRY_OUT<='0';
END IF;
END PROCESS;
Q_OUT<=CNT_SL;
END BEHAVIOR;
4.2 测频控制信号发生器设计
图2给出了系统的工作时序。CLK是由脉冲发生器产生的频率为1Hz的标准时钟信号,当测频控制信号发生器TESTCTL的TSTEN端为高电平时允许计数、低电平时停止计数,在停止计数期间,测频控制信号发生器TESTCTL的Load端产生一个上升沿,将计数器在前1s的计数值锁存进32b锁存器REG32B中,并由8个7段译码器将计数结果译出稳定显示。锁存信号之后经过半个CLK周期,测频控制信号发生器TESTCTL的CLR_CNT端产生一个上升沿,对计数器进行清零。为下1s的计数操作做准备。
为了产生这个时序图,首先有一个D触发器构成二分频器,在每次时钟CLK的上升沿到来使其值翻转。D触发器的输出高电平正好是1s,因此可以作为测频控制信号发生器TESTCTL的TSTEN端,用来控制计数。而Load信号正好是TSTEN端信号的翻转。在计数结束后半个CLK周期,CLK与TSTEN都为低电平,这时CLR_CNT产生一个上升沿作为清零信号。
图4.1 测频控制信号发生器TESTCTL的工作时序
程序如下:
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
ENTITY TESTCTL IS
PORT(
C :IN STD_LOGIC;
CLK :IN STD_LOGIC;
C_EN :OUT STD_LOGIC;
RST_EN :OUT STD_LOGIC;
LOAD :OUT STD_LOGIC
);
END TESTCTL;
ARCHITECTURE BEHAVIOR OF TESTCTL IS
SIGNAL DIV2CLK:STD_LOGIC;
SIGNAL TEST_EN:STD_LOGIC;
BEGIN
PROCESS(CLK,C)
VARIABLE CNT:INTEGER RANGE 0 TO 20000000;
BEGIN
IF C='0' THEN
CNT:=0;
ELSIF(CLK'EVENT AND CLK='1')THEN
CNT:=CNT+1;
IF CNT<10000000 THEN
TEST_EN<='1';
ELSIF CNT<20000000 THEN
TEST_EN<='0';
ELSE CNT:=0;TEST_EN<='0';
END IF;
END IF;
END PROCESS;
PROCESS(TEST_EN)
BEGIN
IF(TEST_EN'EVENT AND TEST_EN='1')THEN
DIV2CLK<=NOT DIV2CLK;
END IF;
END PROCESS;
PROCESS(TEST_EN,DIV2CLK,C) --产生清0信号---
BEGIN
IF((TEST_EN='0' AND DIV2CLK='0') OR C='0' ) THEN
RST_EN<='0';
ELSE RST_EN<='1';
END IF;
END PROCESS;
LOAD<=NOT DIV2CLK;C_EN<=DIV2CLK;
END BEHAVIOR;
4.3 锁存器设计
当系统正常工作时,脉冲发生器提供的1 Hz的输入信号,经过测频控制信号发生器进行信号的变换,产生计数信号,被测信号通过信号整形电路产生同频率的矩形波,送入计数模块,计数模块对输入的矩形波进行计数,将计数结果送入锁存器中,保证系统可以稳定显示数据。
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
ENTITY REG32B IS
PORT(
LOAD :IN STD_LOGIC;
DIN :IN STD_LOGIC_VECTOR(31 DOWNTO 0);
DOUT :OUT STD_LOGIC_VECTOR(31 DOWNTO 0)
);
END REG32B;
ARCHITECTURE BEHAVIOR OF REG32B IS
BEGIN
PROCESS(LOAD,DIN)
BEGIN
IF(LOAD'EVENT AND LOAD='1') THEN
DOUT<=DIN;
END IF;
END PROCESS;
END BEHAVIOR;
4.4 除法器模块程序
LIBRARY ieee;
USE ieee.std_logic_1164.all;
LIBRARY lpm;
USE lpm.all;
ENTITY div32b IS
PORT
(
denom : IN STD_LOGIC_VECTOR (31 DOWNTO 0);
numer : IN STD_LOGIC_VECTOR (31 DOWNTO 0);
quotient : OUT STD_LOGIC_VECTOR (31 DOWNTO 0);
remain : OUT STD_LOGIC_VECTOR (31 DOWNTO 0)
);
END div32b;
ARCHITECTURE SYN OF div32b IS
SIGNAL sub_wire0 : STD_LOGIC_VECTOR (31 DOWNTO 0);
SIGNAL sub_wire1 : STD_LOGIC_VECTOR (31 DOWNTO 0);
COMPONENT lpm_divide
GENERIC (
lpm_drepresentation : STRING;
lpm_hint : STRING;
lpm_nrepresentation : STRING;
lpm_type : STRING;
lpm_widthd : NATURAL;
lpm_widthn : NATURAL
);
PORT (
denom : IN STD_LOGIC_VECTOR (31 DOWNTO 0);
quotient : OUT STD_LOGIC_VECTOR (31 DOWNTO 0);
remain : OUT STD_LOGIC_VECTOR (31 DOWNTO 0);
numer : IN STD_LOGIC_VECTOR (31 DOWNTO 0)
);
END COMPONENT;
BEGIN
quotient <= sub_wire0(31 DOWNTO 0);
remain <= sub_wire1(31 DOWNTO 0);
lpm_divide_component : lpm_divide
GENERIC MAP (
lpm_drepresentation => "UNSIGNED",
lpm_hint => "LPM_REMAINDERPOSITIVE=TRUE",
lpm_nrepresentation => "UNSIGNED",
lpm_type => "LPM_DIVIDE",
lpm_widthd => 32,
lpm_widthn => 32
)
PORT MAP (
denom => denom,
numer => numer,
quotient => sub_wire0,
remain => sub_wire1
);
END SYN;
4.5 动态扫描信号输出
显示译码驱动电路将二进制表示的计数结果转换成相应的能够在七段数码显示管上可以显示的十进制结果。在数码显示管上可以看到计数结果。
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
ENTITY SCAN8 IS
PORT(
CLK :IN STD_LOGIC;
NO1_BCD :IN STD_LOGIC_VECTOR(3 DOWNTO 0);
NO2_BCD :IN STD_LOGIC_VECTOR(3 DOWNTO 0);
NO3_BCD :IN STD_LOGIC_VECTOR(3 DOWNTO 0);
NO4_BCD :IN STD_LOGIC_VECTOR(3 DOWNTO 0);
NO5_BCD :IN STD_LOGIC_VECTOR(3 DOWNTO 0);
NO6_BCD :IN STD_LOGIC_VECTOR(3 DOWNTO 0);
NO7_BCD :IN STD_LOGIC_VECTOR(3 DOWNTO 0);
NO8_BCD :IN STD_LOGIC_VECTOR(3 DOWNTO 0);
IED_CS :OUT STD_LOGIC_VECTOR(7 DOWNTO 0);
IED_DATA :OUT STD_LOGIC_VECTOR(7 DOWNTO 0)
);
END SCAN8;
ARCHITECTURE BEHAVIOR OF SCAN8 IS
SIGNAL S1 :STD_LOGIC_VECTOR(2 DOWNTO 0);
SIGNAL BCD_OUT:STD_LOGIC_VECTOR(3 DOWNTO 0);
SIGNAL TEST_EN:STD_LOGIC;
BEGIN
PROCESS(CLK)
VARIABLE CNT: INTEGER RANGE 0 TO 2000;
BEGIN
IF(CLK'EVENT AND CLK='1') THEN
CNT:=CNT+1;
IF CNT<1000 THEN
TEST_EN<='1';
ELSIF CNT<2000 THEN
TEST_EN<='0';
ELSE CNT:=0;TEST_EN<='0';
END IF;
END IF;
END PROCESS;
PROCESS(TEST_EN)
BEGIN
IF (TEST_EN'EVENT AND TEST_EN='0')THEN
IF S1="111" THEN S1<="000";
ELSE S1<=S1+1;
END IF;
END IF;
END PROCESS;
PROCESS(S1)
BEGIN
CASE S1 IS
WHEN"000"=>BCD_OUT<=NO1_BCD; IED_CS<="00000001";
WHEN"001"=>BCD_OUT<=NO2_BCD; IED_CS<="00000010";
WHEN"010"=>BCD_OUT<=NO3_BCD; IED_CS<="00000100";
WHEN"011"=>BCD_OUT<=NO4_BCD; IED_CS<="00001000";
WHEN"100"=>BCD_OUT<=NO5_BCD; IED_CS<="00010000";
WHEN"101"=>BCD_OUT<=NO6_BCD; IED_CS<="00100000";
WHEN"110"=>BCD_OUT<=NO7_BCD; IED_CS<="01000000";
WHEN"111"=>BCD_OUT<=NO8_BCD; IED_CS<="10000000";
END CASE;
END PROCESS;
PROCESS(BCD_OUT)
BEGIN
CASE BCD_OUT IS
WHEN"0000"=>IED_DATA<="11000000";--0
WHEN"0001"=>IED_DATA<="11111001";--1
WHEN"0010"=>IED_DATA<="10100100";--2
WHEN"0011"=>IED_DATA<="10110000";--3
WHEN"0100"=>IED_DATA<="10011001";--4
WHEN"0101"=>IED_DATA<="10010010";--5
WHEN"0110"=>IED_DATA<="10000010";--6
WHEN"0111"=>IED_DATA<="11111000";--7
WHEN"1000"=>IED_DATA<="10000000";--8
WHEN"1001"=>IED_DATA<="10010000";--9
WHEN OTHERS=>NULL;
END CASE;
END PROCESS;
END BEHAVIOR;
4.6 频率计
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
ENTITY freq IS
PORT(
C :IN STD_LOGIC;
CLK :IN STD_LOGIC;
TEST_CLK:IN STD_LOGIC;
IED_CS :OUT STD_LOGIC_VECTOR(7 DOWNTO 0);
IED_DATA:OUT STD_LOGIC_VECTOR(7 DOWNTO 0)
);
END freq;
ARCHITECTURE BEHAVIOR OF freq IS
COMPONENT CNT10 IS --计数器的例化--
PORT(
C : IN STD_LOGIC;
CLK : IN STD_LOGIC;
C_EN : IN STD_LOGIC;
CARRY_OUT : OUT STD_LOGIC;
Q_OUT : OUT STD_LOGIC_VECTOR(3 DOWNTO 0)
);
END COMPONENT CNT10;
COMPONENT TESTCTL IS --测频部分例化--
PORT(
C :IN STD_LOGIC;
CLK :IN STD_LOGIC;
C_EN:OUT STD_LOGIC;
RST_EN:OUT STD_LOGIC;
LOAD :OUT STD_LOGIC
);
END COMPONENT TESTCTL;
COMPONENT REG32B IS --锁存器例化---
PORT(
LOAD :IN STD_LOGIC;
DIN :IN STD_LOGIC_VECTOR(31 DOWNTO 0);
DOUT :OUT STD_LOGIC_VECTOR(31 DOWNTO 0)
);
END COMPONENT REG32B;
COMPONENT SCAN8 IS --扫描部分例化---
PORT(
CLK :IN STD_LOGIC;
NO1_BCD :IN STD_LOGIC_VECTOR(3 DOWNTO 0);
NO2_BCD :IN STD_LOGIC_VECTOR(3 DOWNTO 0);
NO3_BCD :IN STD_LOGIC_VECTOR(3 DOWNTO 0);
NO4_BCD :IN STD_LOGIC_VECTOR(3 DOWNTO 0);
NO5_BCD :IN STD_LOGIC_VECTOR(3 DOWNTO 0);
NO6_BCD :IN STD_LOGIC_VECTOR(3 DOWNTO 0);
NO7_BCD :IN STD_LOGIC_VECTOR(3 DOWNTO 0);
NO8_BCD :IN STD_LOGIC_VECTOR(3 DOWNTO 0);
IED_CS :OUT STD_LOGIC_VECTOR(7 DOWNTO 0);
IED_DATA:OUT STD_LOGIC_VECTOR(7 DOWNTO 0)
);
END COMPONENT SCAN8;
SIGNAL SE,SC,SL:STD_LOGIC;
SIGNAL S1,S2,S3,S4,S5,S6,S7,S8:STD_LOGIC;
SIGNAL SD:STD_LOGIC_VECTOR(31 DOWNTO 0);
SIGNAL ST:STD_LOGIC_VECTOR(31 DOWNTO 0);
BEGIN
U0 : TESTCTL PORT MAP(CLK=>CLK,C=>C,C_EN=>SE,RST_EN=>SC,LOAD=>SL);
U1 : CNT10 PORT MAP(CLK=>TEST_CLK,C=>SC,C_EN=>SE,Q_OUT=>SD(3 DOWNTO 0),CARRY_OUT=>S1);
U2 : CNT10 PORT MAP(CLK=>S1,C=>SC,C_EN=>SE,Q_OUT=>SD(7 DOWNTO 4),CARRY_OUT=>S2);
U3 : CNT10 PORT MAP(CLK=>S2,C=>SC,C_EN=>SE,Q_OUT=>SD(11 DOWNTO 8 ),CARRY_OUT=>S3);
U4 : CNT10 PORT MAP(CLK=>S3,C=>SC,C_EN=>SE,Q_OUT=>SD(15 DOWNTO 12),CARRY_OUT=>S4);
U5 : CNT10 PORT MAP(CLK=>S4,C=>SC,C_EN=>SE,Q_OUT=>SD(19 DOWNTO 16),CARRY_OUT=>S5);
U6 : CNT10 PORT MAP(CLK=>S5,C=>SC,C_EN=>SE,Q_OUT=>SD(23 DOWNTO 20),CARRY_OUT=>S6);
U7 : CNT10 PORT MAP(CLK=>S6,C=>SC,C_EN=>SE,Q_OUT=>SD(27 DOWNTO 24),CARRY_OUT=>S7);
U8 : CNT10 PORT MAP(CLK=>S7,C=>SC,C_EN=>SE,Q_OUT=>SD(31 DOWNTO 28),CARRY_OUT=>S8);
U9 : REG32B PORT MAP(LOAD=>SL,DIN=>SD(31 DOWNTO 0), DOUT=>ST(31 DOWNTO 0));
U10: SCAN8 PORT MAP(CLK=>CLK,
NO1_BCD=>ST(3 DOWNTO 0),
NO2_BCD=>ST(7 DOWNTO 4),
NO3_BCD=>ST(11 DOWNTO 8),
NO4_BCD=>ST(15 DOWNTO 12),
NO5_BCD=>ST(19 DOWNTO 16),
NO6_BCD=>ST(23 DOWNTO 20),
NO7_BCD=>ST(27 DOWNTO 24),
NO8_BCD=>ST(31 DOWNTO 28),
IED_CS=>IED_CS,
IED_DATA=>IED_DATA);
END BEHAVIOR;
4.7 系统的功能仿真
在对源程序仿真过程中,时序问题的解决是本论文的一个重要之处,为此,假如信号CLK00 和FS,在输入CLK_IN不变的情况下,在信号CLK00 代入时附加延时,由信号CLK00 和FS 来控制本数字频率计。
图4.2 仿真波形
我们利用EDA 工具MAX+PLUS II对VHDL 的源程序进行编译,适配,优化,逻辑总和,自动地把VHDL 描述转变成门级电路,进而完成电路分析,纠错和验证,自动布局布线,仿真等各项测试工作,仿真后得到波形图如图4.2 所示。