采用时钟频率为2MHz,不同的时钟频率需要修改相应的参数。在此只给出本时钟下的程序,其他时钟下请自行修正。
----------------------------------------------------------------------------------
-- Company: XJTU
-- Engineer: 唐剑峰
--
-- Create Date: 10:29:14 12/10/2008
-- Module Name: Cymometer
-- Project Name: 恒精度频率计
-- Target Devices: FPGA or CPLD
-- Revision 0.01 - File Created
-- Comments: clk--系统工作时钟,2MHz
-------------reset--系统复位信号,高电平有效
-------------Fx--为待测信号
-------------FreqNx--为待测信号的计数值
-------------FreqNs--为标准信号的计数值
-------------Freq--为待测信号的频率
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
----------------------------------------------------------
entity Cymometer is
generic(clk_freq : integer := 2000000);--系统工作时钟频率
Port ( clk : in STD_LOGIC;
reset : in STD_LOGIC;
Fx : in STD_LOGIC; ----待测信号
FreqNs : out natural;
FreqNx : out natural);
--Freq : out natural);
end Cymometer;
----------------------------------------------------------
architecture Behavioral of Cymometer is
----------------------------------------
signal start : STD_LOGIC;--此信号为高电平时计数器开始计数
signal CTRL : STD_LOGIC;--CTRL信号为待测信号和门控信号产生的计数器启动信号
signal CNTx : natural;--待测信号计数器
signal CNTs : natural;--标准信号计数器
----------------------------------------
begin
--***************************************--
--产生一个门控信号,高电平有效
GateCtrl : process(clk)
---------------------------
variable CNT0 : integer range 0 to 2_097_152;--门控信号计数器
---------------------------
begin
if rising_edge(clk) then
if reset='1' then
CNT0 := 0;
else
CNT0 := CNT0 + 1;
end if;
---------
if reset='1' then
start <= '0';
elsif CNT0 < (clk_freq*3/4) then
start <= '1';
else
start <= '0';
end if;
end if;
end process GateCtrl;
--***************************************--
--产生CTRL信号,由待测信号和门控信号产生的计数器启动信号
CtrlGen : process(Fx)
begin
if rising_edge(Fx) then
if reset='1' then
CTRL <= '0';
else
CTRL <= start;
end if;
end if;
end process CtrlGen;
--***************************************--
--用两个计数器分别对标准信号clk和待测信号signal计数
----------------------------------
--计数标准信号,CTRL高电平期间有效
CountS : process(clk)
begin
if rising_edge(clk) then
if reset='1' then
CNTs <= 0;
elsif CTRL='1' then
CNTs <= CNTs + 1;
else
CNTs <= 0;
end if;
end if;
end process CountS;
----------------------------------
--计数待测信号,CTRL高电平期间有效
CountX : process(Fx)
begin
if rising_edge(Fx) then
if reset='1' then
CNTx <= 0;
elsif CTRL='1' then
CNTx <= CNTx + 1;
else
CNTx <= 0;
end if;
end if;
end process CountX;
--***************************************--
--CTRL下降沿将技术结果和测量值输出
CountOut : process(CTRL)
begin
if falling_edge(CTRL) then
if reset='1' then
FreqNs <= 0;
FreqNx <= 0;
-- Freq <= 0;
else
FreqNs <= CNTs;
FreqNx <= CNTx;
-- Freq <= (clk_freq / CNTs * CNTx);
end if;
end if;
end process CountOut;
end Behavioral;
下面是为上面的模块编写的测试平台,在Modelsim下仿真通过,因为数据量较大,建议不要使用Altera及ISE仿真。
--------------------------------------------------------------------------------
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.std_logic_unsigned.all;
USE ieee.numeric_std.ALL;
ENTITY tb IS
END tb;
ARCHITECTURE behavior OF tb IS
-- Component Declaration for the Unit Under Test (UUT)
COMPONENT Cymometer
PORT(
clk : IN std_logic;
reset : IN std_logic;
Fx : IN std_logic;
FreqNs : OUT natural;
FreqNx : OUT natural;
Freq : OUT natural
);
END COMPONENT;
--Inputs
signal clk : std_logic := '0';
signal reset : std_logic := '1';
signal Fx : std_logic := '0';
--Outputs
signal FreqNs : natural;
signal FreqNx : natural;
-- signal Freq : natural;
-- Clock period definitions
constant clk_period : time := 500ns;
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut: Cymometer PORT MAP (
clk => clk,
reset => reset,
Fx => Fx,
FreqNs => FreqNs,
FreqNx => FreqNx,
-- Freq => Freq
);
-- Clock process definitions
clk_process :process
begin
clk <= '0';
wait for clk_period/2;
clk <= '1';
wait for clk_period/2;
end process;
--产生待测信号
Fx_process : process
begin
Fx <= '0';
wait for 2*clk_period;
Fx <= '1';
wait for 2*clk_period;
end process;
-- Stimulus process
stim_proc: process
begin
-- hold reset state for 100ms.
wait for clk_period*10;
reset <= '0';
-- insert stimulus here
wait;
end process;
END;
参考原理M/T测频法。
----------------------------------------------------------------------------------
-- Company: XJTU
-- Engineer: 唐剑峰
--
-- Create Date: 10:29:14 12/10/2008
-- Module Name: Cymometer
-- Project Name: 恒精度频率计
-- Target Devices: FPGA or CPLD
-- Revision 0.01 - File Created
-- Comments: clk--系统工作时钟,2MHz
-------------reset--系统复位信号,高电平有效
-------------Fx--为待测信号
-------------FreqNx--为待测信号的计数值
-------------FreqNs--为标准信号的计数值
-------------Freq--为待测信号的频率
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
----------------------------------------------------------
entity Cymometer is
generic(clk_freq : integer := 2000000);--系统工作时钟频率
Port ( clk : in STD_LOGIC;
reset : in STD_LOGIC;
Fx : in STD_LOGIC; ----待测信号
FreqNs : out natural;
FreqNx : out natural);
--Freq : out natural);
end Cymometer;
----------------------------------------------------------
architecture Behavioral of Cymometer is
----------------------------------------
signal start : STD_LOGIC;--此信号为高电平时计数器开始计数
signal CTRL : STD_LOGIC;--CTRL信号为待测信号和门控信号产生的计数器启动信号
signal CNTx : natural;--待测信号计数器
signal CNTs : natural;--标准信号计数器
----------------------------------------
begin
--***************************************--
--产生一个门控信号,高电平有效
GateCtrl : process(clk)
---------------------------
variable CNT0 : integer range 0 to 2_097_152;--门控信号计数器
---------------------------
begin
if rising_edge(clk) then
if reset='1' then
CNT0 := 0;
else
CNT0 := CNT0 + 1;
end if;
---------
if reset='1' then
start <= '0';
elsif CNT0 < (clk_freq*3/4) then
start <= '1';
else
start <= '0';
end if;
end if;
end process GateCtrl;
--***************************************--
--产生CTRL信号,由待测信号和门控信号产生的计数器启动信号
CtrlGen : process(Fx)
begin
if rising_edge(Fx) then
if reset='1' then
CTRL <= '0';
else
CTRL <= start;
end if;
end if;
end process CtrlGen;
--***************************************--
--用两个计数器分别对标准信号clk和待测信号signal计数
----------------------------------
--计数标准信号,CTRL高电平期间有效
CountS : process(clk)
begin
if rising_edge(clk) then
if reset='1' then
CNTs <= 0;
elsif CTRL='1' then
CNTs <= CNTs + 1;
else
CNTs <= 0;
end if;
end if;
end process CountS;
----------------------------------
--计数待测信号,CTRL高电平期间有效
CountX : process(Fx)
begin
if rising_edge(Fx) then
if reset='1' then
CNTx <= 0;
elsif CTRL='1' then
CNTx <= CNTx + 1;
else
CNTx <= 0;
end if;
end if;
end process CountX;
--***************************************--
--CTRL下降沿将技术结果和测量值输出
CountOut : process(CTRL)
begin
if falling_edge(CTRL) then
if reset='1' then
FreqNs <= 0;
FreqNx <= 0;
-- Freq <= 0;
else
FreqNs <= CNTs;
FreqNx <= CNTx;
-- Freq <= (clk_freq / CNTs * CNTx);
end if;
end if;
end process CountOut;
end Behavioral;
下面是为上面的模块编写的测试平台,在Modelsim下仿真通过,因为数据量较大,建议不要使用Altera及ISE仿真。
--------------------------------------------------------------------------------
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.std_logic_unsigned.all;
USE ieee.numeric_std.ALL;
ENTITY tb IS
END tb;
ARCHITECTURE behavior OF tb IS
-- Component Declaration for the Unit Under Test (UUT)
COMPONENT Cymometer
PORT(
clk : IN std_logic;
reset : IN std_logic;
Fx : IN std_logic;
FreqNs : OUT natural;
FreqNx : OUT natural;
Freq : OUT natural
);
END COMPONENT;
--Inputs
signal clk : std_logic := '0';
signal reset : std_logic := '1';
signal Fx : std_logic := '0';
--Outputs
signal FreqNs : natural;
signal FreqNx : natural;
-- signal Freq : natural;
-- Clock period definitions
constant clk_period : time := 500ns;
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut: Cymometer PORT MAP (
clk => clk,
reset => reset,
Fx => Fx,
FreqNs => FreqNs,
FreqNx => FreqNx,
-- Freq => Freq
);
-- Clock process definitions
clk_process :process
begin
clk <= '0';
wait for clk_period/2;
clk <= '1';
wait for clk_period/2;
end process;
--产生待测信号
Fx_process : process
begin
Fx <= '0';
wait for 2*clk_period;
Fx <= '1';
wait for 2*clk_period;
end process;
-- Stimulus process
stim_proc: process
begin
-- hold reset state for 100ms.
wait for clk_period*10;
reset <= '0';
-- insert stimulus here
wait;
end process;
END;
参考原理M/T测频法。