Você está na página 1de 12

--******************************************************************************

--* Company:
FTDI
*
--* Date:
23 Nov 2004
*
--* Author:
Iain Maciver
*
--*
*
--* Module Name: freq_cnt_ctl
*
--*
*
--* Description: Calculates the frequency of an unknown input signal using
*
--*
Morph-IC clk as a reference
*
--******************************************************************************
LIBRARY IEEE;
USE IEEE.std_logic_1164.ALL;
ENTITY freq_cnt_ctl IS
PORT (
clk50
: in std_logic;

-- 50MHz clock input

Signal_A : in std_logic;
-- Entre 1
Signal_B : in std_logic;
-- Entre 2
rst
FT245Din
nRXF
nTXE
FT245Dout
FT245DEn
nRD
WR
);
END freq_cnt_ctl;

:
:
:
:

in
in
in
in

:
:
:
:

out
out
out
out

std_logic;
std_logic_vector(7
std_logic;
-std_logic;
--

-- Active high reset via AD7


downto 0); -- Data Bus
Read Buffer Full
Write Buffer Empty

std_logic_vector(7 DOWNTO 0); -- Data Bus


std_logic;
-- Data Bus Enable
std_logic;
-- Read Strobe
std_logic
-- Write Strobe

ARCHITECTURE rtl OF freq_cnt_ctl IS


COMPONENT lpmcnt24
PORT (clock : IN STD_LOGIC ;
cnt_en : IN STD_LOGIC ;
sclr : IN STD_LOGIC ;
aclr : IN STD_LOGIC ;
q
: OUT STD_LOGIC_VECTOR (23 DOWNTO 0)
);
END COMPONENT;
COMPONENT lpmcnt26
PORT (clock : IN STD_LOGIC ;
cnt_en : IN STD_LOGIC ;
sclr : IN STD_LOGIC ;
aclr : IN STD_LOGIC ;
q
: OUT STD_LOGIC_VECTOR (25 DOWNTO 0)
);
END COMPONENT;
-- State Machine encoding
type mstate is (IDLE, Rx1, Rx2, Rx3, COUNT, Tx1, Tx2, Tx3, Tx4);
signal ctl_state : mstate;
type flag is (Signal_A_dec, Signal_B_dec, both, none);
signal ctl_flag : flag := none;

-- TXE : tat haut = buffer d'envoi vide


signal TXE
: std_logic;
-- RXF : tat haut = buffer pleins et dispo la lecture
signal RXF
: std_logic;
-- FT_En : tat haut = data bus enable
signal FT_En : std_logic;
-- WR_int : tat haut = autorise l'ecriture dans le buffer du FIFO
signal WR_int : std_logic;
-- RD_int : tat haut = recupere le contenu du buffer du FIFO
signal RD_int : std_logic;
-- LdCmdReg : tat haut = recuperation du contenu du Data Bus pour le mettre dan
s CmdReg
signal LdCmdReg
: std_logic;
-- CmdReg : octet des differentes commandes
signal CmdReg
: std_logic_vector(7 downto 0);
-- cnt_enable : autorise le comptage de i_freq_cnt_async et i_window
signal cnt_enable_A
: std_logic;
signal cnt_enable_B
: std_logic;
-- window_cnt : compteur du timer de la fenetre de comptage
signal window_cnt
: std_logic_vector(25 downto 0);
-- end_window : flag de fin de fenetre de comptage
signal end_window
: std_logic;
-- freq_cnt : compteur de front
signal freq_cnt_Signal_A : std_logic_vector(23 downto 0);
signal freq_cnt_Signal_B : std_logic_vector(23 downto 0);
-- rst_window : reset du compteur de la fenetre
signal rst_window
: std_logic;
-- rst_freq_cnt : reset du compteur de front du signal inconnu
signal rst_freq_cnt : std_logic;
-- FUnknown_d1 et FUnknown_d2 : copies de deux tats successifs de FUnknown pour
detecter un front positif
signal Signal_A_d1
: std_logic;
signal Signal_A_d2
: std_logic;
signal Signal_B_d1
signal Signal_B_d2

: std_logic;
: std_logic;

-- posedge_* : tat haut lors d'un front positif


signal posedge_Signal_A : std_logic;
signal posedge_Signal_B : std_logic;
-- Tx_Status : indique l'etape de la transmission selon sa valeur de 0 a 3
signal Tx_Status
: std_logic_vector(1 downto 0);
-- Overflow_async : flag de depassement du compteur de front du signal FUnknow
n

signal Overflow_async : std_logic;


-- Freq_Out : nombre de front de FUnknown compt dans la fenetre
signal Freq_Out
: std_logic_vector(23 downto 0);
-- timeout_enable : activation du compteur timeout
signal timeout_enable : std_logic;
-- timeout_cnt : valeur du compteur timeout
signal timeout_cnt
: std_logic_vector(25 downto 0);
-- timeout : flag de temps depass
signal timeout
: std_logic;
-- ???
signal remainder_en : std_logic;
signal remainder_cnt : std_logic_vector(23 downto 0);
-signal
signal
signal
signal
signal
signal
signal
signal
signal
signal

cnt_coincidence : std_logic_vector(23 downto 0);


cnt_coincidence_old : std_logic_vector(23 downto 0);
window_enable : std_logic;
rst_timeout : std_logic;
cnt_coincidence_enable : std_logic;
fenetre_cnt : std_logic_vector(23 downto 0);
fenetre_enable : std_logic;
rst_fenetre_cnt : std_logic;
fenetre_out : std_logic;
freq_cnt_Signal_A_old : std_logic_vector(23 downto 0); -- new

signal low

: std_logic;

BEGIN
low <= '0';
--------------------------------------------------------------------------------- Resync incoming signals to 50MHz clk
-------------------------------------------------------------------------------r_TXE : process (clk50, rst)
begin
if (rst = '1') then
TXE <= '0';
RXF <= '0';
elsif (clk50'event and clk50 = '1') then
TXE <= not nTXE;
RXF <= not nRXF;
end if;
end process r_TXE;
--------------------------------------------------------------------------------- Store Command when read from FT Chip
-------------------------------------------------------------------------------r_Cmd : process (clk50, rst)
begin
if (rst = '1') then
CmdReg <= "00000000";

elsif (clk50'event and clk50 = '1') then


if (LdCmdReg = '1') then
CmdReg <= FT245Din;
else
CmdReg <= CmdReg;
end if;
end if;
end process r_Cmd;
--------------------------------------------------------------------------------- Detection des fronts positifs
-------------------------------------------------------------------------------r_edge_signal : process (clk50, rst)
begin
if (rst = '1') then
Signal_A_d1 <= '0';
---------------Signal_A_d2 <= '0';
s de front si -Signal_B_d1 <= '0';
-Signal_B_d2 <= '0';
---------------elsif (clk50'event and clk50 = '1') then
Signal_A_d1 <= Signal_A;
---------------Signal_A_d2 <= Signal_A_d1;
eux tats en -Signal_B_d1 <= Signal_B;
pour chacun des signaux -Signal_B_d2 <= Signal_B_d1;
---------------end if;
end process r_edge_signal;

----------------------- RESET des detecteur


-- rst = '1'
-------------------------------------------- Actualisation des d
-- d1 et d2
----------------------

------------------------------------posedge_Signal_A <= Signal_A_d1 and not Signal_A_d2;


positif sur -posedge_Signal_B <= Signal_B_d1 and not Signal_B_d2;
et B
--

-- Detection de front
-- les deux signaux A
----------------------

------------------------------------------------------------------------------------------------ Cration des 5 compteurs


--------------------------------------------------------------------------------- i_timeout :
-- i_window : compteur pour le timer de la fenetre d'acquisition
-- i_freq_cnt_Signal_A : compteur de front du signal A
-- i_freq_cnt_Signal_B : compteur de front du signal B
-- i_cnt_coincidence : compteur des coincidences
-- i_fenetre_co : compteur pour le timer de la fenetre de coincidence
-------------------------------------------------------------------------------i_timeout : lpmcnt26 PORT MAP(

clock
cnt_en
sclr
aclr
q
);
i_window
clock
cnt_en
sclr
aclr
q
);

=>
=>
=>
=>
=>

clk50,
timeout_enable,
rst_window,
rst,
timeout_cnt

-----------------------------------------------------------------

: lpmcnt26 PORT MAP(


=> clk50,
=> cnt_enable_A or cnt_enable_B,
=> rst_window,
=> rst,
=> window_cnt

-------------------------------- Compteur pour timer de la --- fenetre d'acquisition


--------------------------------

i_freq_cnt_Signal_A : lpmcnt24 PORT MAP(


clock => Signal_A,
---------cnt_en => cnt_enable_A and not Overflow_async,
ignal A -sclr => low,
---------aclr => rst or rst_freq_cnt,
q
=> freq_cnt_Signal_A
);
i_freq_cnt_Signal_B : lpmcnt24 PORT MAP(
clock => Signal_B,
---------cnt_en => cnt_enable_B and not Overflow_async,
ignal B -sclr => low,
---------aclr => rst or rst_freq_cnt,
q
=> freq_cnt_Signal_B
);

-------------------------- Compteur de front du s


-------------------------

-------------------------- Compteur de front du s


-------------------------

i_cnt_coincidence : lpmcnt24 PORT MAP(


clock => Signal_B,
----------------cnt_en => cnt_coincidence_enable and not fenetre_out,
coincidences -sclr => low,
----------------aclr => rst or rst_freq_cnt,
q
=> cnt_coincidence
);
i_fenetre_co : lpmcnt24 PORT MAP(
clock => clk50,
---------cnt_en => fenetre_enable,
de la -sclr => rst_fenetre_cnt,
s
-aclr => rst,
---------------------------q
=> fenetre_cnt
);

-------------------

Compteur des

------------------

-------------------------- Compteur pour le timer


-- fenetre de coincidence
-------

----------------------------------------------------------------------------------------- Process de count des coincidences


----------------------------------------------------------------------------------------- Gestion de :
-- - cnt_coincidence_enable
-- - rst_fenetre_cnt
-- - fenetre_enable
----------------------------------------------------------------------------------------p_cnt_coincidence : process (clk50, freq_cnt_Signal_A, cnt_coincidence, fenetr
e_out, posedge_Signal_A)
begin
--

if(freq_cnt_Signal_A/=freq_cnt_Signal_A_old)
if(posedge_Signal_A='1') then

then
--------------------

cnt_coincidence_enable <= '1';

-- Si front sur A

rst_fenetre_cnt <= '1';

------------------

--fenetre_enable <='1';
elsif(fenetre_out='1') then

------------------

cnt_coincidence_enable <= '0';

-- Si fenetre fini

rst_fenetre_cnt <='1';

------------------

-----fenetre_enable <='0';
elsif(cnt_coincidence/=cnt_coincidence_old) then
--------cnt_coincidence_enable <='0';
compt -rst_fenetre_cnt <='1';
--------fenetre_enable <='0';
else
cnt_coincidence_enable <= cnt_coincidence_enable;
rst_fenetre_cnt <='0';
fenetre_enable <= fenetre_enable;

------------------- Si coincidence
------------------

------------ Sinon ------------

end if;
cnt_coincidence_old <= cnt_coincidence;
freq_cnt_Signal_A_old <= freq_cnt_Signal_A;

--

end process p_cnt_coincidence;

--------------------------------------------------------------------------------- Process de depassement d'un des compteurs


--------------------------------------------------------------------------------

p_overflow_async : process (freq_cnt_Signal_A, freq_cnt_Signal_B)


begin
if (freq_cnt_Signal_A = "111111111111111111111111") then
Overflow_async <= '1';
elsif(freq_cnt_Signal_B = "111111111111111111111111") then
Overflow_async <= '1';
else
Overflow_async <= '0';
end if;
end process p_overflow_async;
--------------------------------------------------------------------------------- Process si timeout_cnt ou end_window ont atteint leur maximum
-------------------------------------------------------------------------------p_end_window : process (window_cnt, timeout_cnt, fenetre_cnt, CmdReg)
begin
if (fenetre_cnt = "00000000000000000000000101") then
fenetre_out <= '1';
else
fenetre_out <= '0';
end if;
case CmdReg(2 downto 0) is
-- 1 sec
when "100" =>
if (timeout_cnt = "10111110101111000001111111") then
timeout <= '1';
else
timeout <= '0';
end if;
if (window_cnt = "10111110101111000001111111") then
end_window <= '1';
else
end_window <= '0';
end if;
-- 500 ms
when "011" =>
if (timeout_cnt = "01011111010111100000111111") then
timeout <= '1';
else
timeout <= '0';
end if;
if (window_cnt = "01011111010111100000111111") then
end_window <= '1';
else
end_window <= '0';
end if;
-- 100 ms
when "010" =>
if (timeout_cnt = "00010011000100101100111111") then
timeout <= '1';
else
timeout <= '0';
end if;
if (window_cnt = "00010011000100101100111111") then
end_window <= '1';
else
end_window <= '0';

end if;
-- 10 ms
when "001" =>
if (timeout_cnt = "00000001111010000100011111") then
timeout <= '1';
else
timeout <= '0';
end if;
if (window_cnt = "00000001111010000100011111") then
end_window <= '1';
else
end_window <= '0';
end if;
-- 1 ms
when others =>
if (timeout_cnt = "00000000001100001101001111") then
timeout <= '1';
else
timeout <= '0';
end if;
if (window_cnt = "00000000001100001101001111") then
end_window <= '1';
else
end_window <= '0';
end if;
-end case;
end process p_end_window;
--------------------------------------------------------------------------------- State Machine Controller
-------------------------------------------------------------------------------sm_freq_cnt : process (clk50, rst)
begin
if (rst = '1') then
ctl_state

<= IDLE;

cnt_enable_A <= '0';


cnt_enable_B <= '0';
timeout_enable <= '0';
remainder_en

<= '0';

rst_window

<= '0';

------------ Reset ------------

rst_freq_cnt <= '0';


FT_En
<= '0';
RD_int
<= '0';
WR_int
<= '0';
LdCmdReg
<= '0';
Tx_Status
<= "00";
elsif (clk50'event and clk50 = '1') then
case (ctl_state) is
-- Wait until data is available to be received from Rx Buffer

when IDLE =>


if (RXF = '1')
ctl_state
RD_int
else
ctl_state
RD_int
end if;

then
<= Rx1;
<= '1';
<= IDLE;
<= '0';

cnt_enable_A
cnt_enable_B
timeout_enable <= '0';
remainder_en <= '0';
rst_window
<= '0';
rst_freq_cnt <= '0';
FT_En
<= '0';
WR_int
<= '0';
LdCmdReg
<= '0';
Tx_Status
<= "00";

<= '0';
<= '0';

-when Rx1 =>


ctl_state
<= Rx2;
cnt_enable_A <= '0';
cnt_enable_B <= '0';
timeout_enable <= '0';
remainder_en <= '0';
rst_window
<= '0';
rst_freq_cnt <= '0';
FT_En
<= '0';
RD_int
<= '1';
WR_int
<= '0';
LdCmdReg
<= '1';
Tx_Status
<= "00";
-when Rx2 =>
ctl_state
<= Rx3;
cnt_enable_A <= '0';
cnt_enable_B <= '0';
timeout_enable <= '0';
remainder_en <= '0';
rst_window
<= '0';
rst_freq_cnt <= '0';
FT_En
<= '0';
RD_int
<= '1';
WR_int
<= '0';
LdCmdReg
<= '1';
Tx_Status
<= "00";
-- If Cmd is X"Bx" start Frequency measurement
when Rx3 =>
if (RXF = '1') then
ctl_state
<= Rx3;
cnt_enable_A <= '0';
cnt_enable_B <= '0';
timeout_enable <= '0';
elsif (CmdReg(7 downto 4) = "1011") then
ctl_state
<= COUNT;
cnt_enable_A <= posedge_Signal_A;
cnt_enable_B <= posedge_Signal_B;
timeout_enable <= '1';
else

ctl_state

<= IDLE;
cnt_enable_A <= '0';
cnt_enable_B <= '0';
timeout_enable <= '0';
end if;
rst_window <= '0';
remainder_en <= '0';
rst_freq_cnt <= '0';
FT_En
<= '0';
RD_int
<= '0';
WR_int
<= '0';
LdCmdReg
<= '0';
Tx_Status
<= "00";
-- wait until measurement window has completed
when COUNT =>
if (end_window = '1') then
ctl_state
<= Tx1;
cnt_enable_A <= '0';
cnt_enable_B <= '0';
remainder_en <= '0';
FT_En
<= '1';
else
ctl_state
<= COUNT;
cnt_enable_A <= cnt_enable_A or posedge_Signal
_A or timeout;
cnt_enable_B <= cnt_enable_B or posedge_Signal
_B or timeout;
remainder_en <= '0';
FT_En
<= '0';
end if;
timeout_enable <= '1';
rst_window
<= '0';
rst_freq_cnt <= '0';
RD_int
<= '0';
WR_int
<= '0';
LdCmdReg
<= '0';
Tx_Status
<= "00";
-- Transfer Frequency count to Tx Buffer in four bytes
when Tx1 =>
if (TXE = '1') then
ctl_state
<= Tx2;
WR_int
<= '1';
else
ctl_state
<= Tx1;
WR_int
<= '0';
end if;
cnt_enable_A <= '0';
cnt_enable_B <= '0';
timeout_enable <= '0';
remainder_en <= '0';
rst_window
<= '0';
rst_freq_cnt <= '0';
FT_En
<= '1';
RD_int
<= '0';
LdCmdReg
<= '0';
Tx_Status
<= Tx_Status;
-when Tx2 =>
ctl_state
<= Tx3;
cnt_enable_A <= '0';

timeout_enable
remainder_en
rst_window
rst_freq_cnt
FT_En
RD_int
WR_int
LdCmdReg
Tx_Status
-when Tx3 =>
ctl_state

cnt_enable_B <= '0';


<= '0';
<= '0';
<= '0';
<= '0';
<= '1';
<= '0';
<= '1';
<= '0';
<= Tx_Status;

<= Tx4;
cnt_enable_A <= '0';
cnt_enable_B <= '0';
timeout_enable <= '0';
remainder_en <= '0';
rst_window
<= '0';
rst_freq_cnt <= '0';
FT_En
<= '1';
RD_int
<= '0';
WR_int
<= '1';
LdCmdReg
<= '0';
Tx_Status
<= Tx_Status;
-- Return to Idle when last byte has been transferred
when Tx4 =>
if (TXE = '1') then
ctl_state
<= Tx4;
rst_window
<= '0';
rst_freq_cnt <= '0';
Tx_Status
<= Tx_Status;
elsif (Tx_Status = "11") then
ctl_state
<= IDLE;
rst_window
<= '1';
rst_freq_cnt <= '1';
Tx_Status
<= Tx_Status;
else
ctl_state
<= Tx1;
rst_window
<= '0';
rst_freq_cnt <= '0';
case Tx_Status is
when "10" => Tx_Status <= "11";
when "01" => Tx_Status <= "10";
when "00" => Tx_Status <= "01";
when others => Tx_Status <= "00";
end case;
end if;
cnt_enable_A <= '0';
cnt_enable_B <= '0';
timeout_enable <= '0';
remainder_en <= '0';
FT_En
<= '1';
RD_int
<= '0';
WR_int
<= '0';
LdCmdReg
<= '0';
-when others =>
ctl_state
<= IDLE;
cnt_enable_A <= '0';
cnt_enable_B <= '0';

timeout_enable <= '0';


remainder_en <= '0';
rst_window
<= '0';
rst_freq_cnt <= '0';
FT_En
<= '0';
RD_int
<= '0';
WR_int
<= '0';
LdCmdReg
<= '0';
Tx_Status
<= "00";
end case;
end if;
end process sm_freq_cnt;
--------------------------------------------------------------------------------- Assign Outputs
-------------------------------------------------------------------------------Freq_Out <= cnt_coincidence;
Freq_Out <= freq_cnt_Signal_A;
Freq_Out <= freq_cnt_Signal_B;

---

-- Encode Frequency bytes using upper two bits


p_FT_Data : process (Tx_Status, Freq_Out)
begin
case Tx_Status is
when "11" => FT245Dout <= "11" & Freq_Out(23 downto 18);
--------------------------------------------------when "10" => FT245Dout <= "10" & Freq_Out(17 downto 12);
oi de la frequence de FUnknown en 4 octets selon -when "01" => FT245Dout <= "01" & Freq_Out(11 downto 6);
tat de Tx_Status
-when others => FT245Dout <= "00" & Freq_Out(5 downto 0);
--------------------------------------------------end case;
end process p_FT_Data;
FT245DEn <= FT_En;
WR
<= WR_int;
nRD
<= not RD_int;
END rtl;

------- Env
-- l'e
------

Você também pode gostar