0
votes

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;
2
Please clarify what exactly you want as output. Because of if SYNC_edge = '1' then counter <= counter + 1; counter counts the number of number of rising edge of SYNC. Initialise counter as well. What does the TEMP mean? If you initialise counter to 0, it will be high till you get first rising edgemaximus
Have you written a testbench? did it function as you expected from your simulation?Tricky
@Rakend Counter counts up on SYNC_edge, not SYNC, which detects a rising edge of the sync signalTricky
@Rakend the TEMP is OUTPUT, I pass the output from process. I stuck in the logic implementation. How do I check weather the counter is running for not.maestros
@Tricky Yes. That's what I've written. counter indicates the number of rising edge occured on SYNC it doesn't count as long as the SYNC is high. Since SYNC is pulsating, it can be usedmaximus

2 Answers

0
votes

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.

0
votes

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