maestros
maestros

Reputation: 1

VHDL: counter checking

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

Answers (2)

namabo
namabo

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

Ahmad Zaklouta
Ahmad Zaklouta

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

Related Questions