Reputation: 1
I want to detect a external signal connection to a CPLD (only connected or not connected). My system clock is 1MHz and external signal is 4KHz. I have developed a logic that will detect rising edge of external signal and start a counter. If the counter is counting then external signal is connected and if the counter is not counting then external signal is not connected. I write the code but its not working, what is the problem? I am beginner in VHDL. Please help, How to check a counter running in vhdl?
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.numeric_std.all;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity SYNC_detection1 is
Port ( SYNC : in STD_LOGIC;
CLK : in STD_LOGIC;
EDGE : out STD_LOGIC;
OUTPUT : out STD_LOGIC;
BITSOUT : out STD_LOGIC_VECTOR (3 downto 0)
);
end SYNC_detection1;
architecture workingarchi of SYNC_detection1 is
signal SYNC_reg : std_LOGIC := '0';
signal SYNC_edge : std_LOGIC := '0';
signal TEMP : std_LOGIC := '0';
signal counter : STD_LOGIC_VECTOR (3 downto 0);
begin
SYNC_edge_p : process(CLK)
begin
if (rising_edge(CLK)) then
SYNC_reg <= SYNC;
end if;
end process;
SYNC_edge <= not SYNC_reg and SYNC;
counter_p: process(CLK)
begin
if (rising_edge(CLK)) then
if SYNC_edge = '1' then
counter <= counter + 1;
if (counter = "0000") then
TEMP <= '1';
end if;
end if;
end if;
end process;
OUTPUT <= TEMP;
BITSOUT <= counter;
EDGE <= SYNC_edge;
end workingarchi;
Upvotes: 0
Views: 1685
Reputation: 1
first of all, you are managing an external clock and want to process it with your 1MHz internal clock, for this application you must use a synchronization block.
I will proceed as follow. Manage the external SYNC signal as a clock, and use it to count the rising_edge, another tips is to avoid std_logic_vector to count (using integer to count get the code more readable)
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.numeric_std.all;
entity SYNC_detection1 is
Port ( SYNC : in STD_LOGIC;
EDGE : out STD_LOGIC;
OUTPUT : out STD_LOGIC;
BITSOUT : out STD_LOGIC_VECTOR (3 downto 0)
);
end SYNC_detection1;
architecture workingarchi of SYNC_detection1 is
signal SYNC_edge : std_LOGIC := '0';
signal TEMP : std_LOGIC := '0';
signal counter : integer := 0;
begin
SYNC_edge_p : process(SYNC)
begin
SYNC_edge <= '0';
if (rising_edge(SYNC)) then
counter <= counter + 1;
SYNC_edge <= '1';
if (counter = 0) then
TEMP <= '1';
end if;
end if;
end process;
OUTPUT <= TEMP;
BITSOUT <= std_logic_vector(to_unsigned(counter, BITSOUT'length));
EDGE <= SYNC_edge;
end workingarchi;
With this implementation you now have your output signals in the 4KHz clock domain, you just need to add a synchronization block for each output line with source clock 4KHz and destination clock 1MHz.
For the synchronization block just as reference I write the following block that is able to synchronize an edge:
library ieee;
use ieee.std_logic_1164.all;
entity edge_sync is
port(
data : in std_logic;
clk_src : in std_logic;
clk_dst : in std_logic;
line_out: out std_logic
);
end edge_sync;
architecture beha of edge_sync is
component ff_D is
port(
lineD : in std_logic;
clk : in std_logic;
lineQ : out std_logic
);
end component ff_D;
signal input_s : std_logic := '0';
signal meta : std_logic:= '0';
signal Q2_D3 : std_logic:= '0';
signal Q3 : std_logic:= '0';
begin
FFsrc : ff_D port map (
lineD => input_s,
clk => clk_src,
lineQ => meta
);
FFdst1 : ff_D port map(
lineD => meta,
clk => clk_dst ,
lineQ => Q2_D3
);
FFdst2 : ff_D port map(
lineD => Q2_D3,
clk => clk_dst ,
lineQ => Q3
);
input_s <= data;
line_out <= (not Q3) and Q2_D3;
end beha;
But on line you can find other implementations.
From your code:
SYNC_edge <= not SYNC_reg and SYNC;
This line could work only if SYNC changes between CLK rising edges. Are you sure you are not generating the 2 clock synchronously? If the 2 clocks are generated with 0 phase since they are multiple you'll never get an edge between the CLK rising edges, as consequences you don't see SYNC_edge change.
PS You are facing with two main fpga subjects, clock domain crossing and metastability management, I suggest you to study theory material about these arguments. It can help you to focus on hardware aspects as well as VHDL coding.
Regards
Upvotes: 0
Reputation: 183
If you just want to check that the counter is running and you don't want to write a testbench, which you should do by the way, you can put an if condition that if the counter equals to 1, then turn a led on in your board. something like this:
if counter = "0001" then
led <= '1';
end if;
if the led is ON then you counter is running.
Upvotes: 0