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;
: Edited by Moderator
maestros wrote: > use ieee.numeric_std.all; > use IEEE.STD_LOGIC_UNSIGNED.ALL; Never ever both together! By ignoring this hint you will encounter some fairly strange errors due to multiple defined data types. > I write the code but its not working, what is the problem? I am > beginner in VHDL. What do you expect? What does the code instead? How do you see that? What does your testbench look like? > If the counter is counting then external signal is connected and if the > counter is not counting then external signal is not connected. A external signal is always connected in some way. Only its value changes. So do you mean "high" and "low" or '1' and '0'? BTW: The signal TEMP is only set once. Afterwards its never reset. That looks kind of strange... BTW2: Pls read the manual above each text box and use the [ vhdl ] tags for your code:
Reply Rules — please read before posting Post long source code as attachment, not in the text : Formatting options [vhdl]VHDL code[/vhdl] :
: Edited by Moderator
Hi Lothar M., Thanks for your immediate reply and guidance. I will change my code accordingly. This is a part of my entire code written separately for easy understanding. You said it correctly. A external signal is always connected in some way. In my case, when external signal is disconnected... the CPLD input pin is pulled 'high' and when the external signal is connected the CPLD will get 3.9KHz square wave as input. I want to create a 'status' for external signal weather it is connected or not by giving high or low repectively on CPLD pin. Since it is incomplete code, i have not simulated the testbench. I stuck in the counter condition checking. How to check the counter running or counter stop, so that i can generate proper output. Please help.
maestros wrote: > the CPLD input pin is pulled 'high' and when the external signal is > connected the CPLD will get 3.9KHz square wave as input. I want to > create a 'status' for external signal weather it is connected or not by > giving high or low repectively on CPLD pin. So the most easy way would be to check wether there is a change on the square-input now and then. What I would do is nearly the same like you did: Count up a counter with each system clock. When the counter reaches a time of a little bit more than 1/(2*4kHz) = 125µs = 125 system clock cycles (lets assume here that the square signal is a perfect 50:50 square, otherwise it would be a rectangle and the time must be longer...) then there is no signal at the square input, so set "NoSignal" output is '1'. Then check the square input for changes. When a change occures, reset the counter and additionally set the "NoSignal" output to '0'. All in all it looks like this:
library IEEE; use IEEE.STD_LOGIC_1164.ALL; use ieee.numeric_std.all; entity SYNC_det is Port ( CLK : in STD_LOGIC; Square : in STD_LOGIC; SquareDetected : out STD_LOGIC := '0' ); end SYNC_det; architecture arch of SYNC_det is signal sqsr : std_LOGIC_vector(1 downto 0) := "11"; -- shift register for edge detection, default value: external pullup signal cnt : integer range 0 to 127 := 0; begin counter_p: process(CLK) begin if (rising_edge(CLK)) then -- never ever use a async input without sync'ing it to the system clock! sqsr <= sqsr(0)□ -- check for edges if sqsr="10" or sqsr="01" then -- edge on SQUARE cnt <= 0; SquareDetected <= '1'; else if cnt<127 then -- count to highest value cnt <= cnt + 1; else SquareDetected <= '0'; -- end of counter reached --> timeout, no more edges end if; end if; end if; end process; end arch;
And the description above togehter with this testbench...
LIBRARY ieee; USE ieee.std_logic_1164.ALL; ENTITY tb_sd IS END tb_sd; ARCHITECTURE behavior OF tb_sd IS COMPONENT SYNC_det PORT( CLK : IN std_logic; Square : IN std_logic; SquareDetected : OUT std_logic ); END COMPONENT; signal CLK : std_logic := '0'; signal Square : std_logic := '1'; signal sq : std_logic := '1'; -- default value = 'high' due to pullup signal sqen : std_logic := '1'; signal SquareDetected : std_logic; BEGIN uut: SYNC_det PORT MAP ( CLK => CLK, Square => Square, SquareDetected => SquareDetected ); clk <= not clk after 500 ns; -- 1MHz system clock sq <= not sq after 125 us; -- 4kHz square wave sqen <= not sqen after 2250 us; -- enable for the square wave signal Square <= sq and sqen; END;
... results in the waveform in the screenshot. Looks ok for me... ;-)
: Edited by Moderator
Hello Lothar M., Your code is perfectly working, I have tested it on hardware also. Thanks a lot for your help and prompt reply.
maestros wrote: > Your code is perfectly working, I have tested it on hardware also. Nice to hear. A hint: check out the symmetry of your square wave. When its changing a little bit from 50:50 to 48:52, then you will get short spikes on the SquareDetected output, because there is only a little margin on the counter (from 125 to 127). See WF_SD_DC48.PNG for that. To get this waveform I changed the test bench a little to invoke the duty cycle in the 4kHz signal:
: constant dc : real := 0.48; : BEGIN : process begin sq <= '1'; wait for dc * 250 us; sq <= '0'; wait for (1.0-dc) * 250 us; end process; :
To be much more tolerant there it would be best to increase the top value of the counter to 255:
: signal cnt : integer range 0 to 255 := 0; : if cnt<255 then -- count to highest value :
The reaction to detect a missing 4kHz square wave signal is then delayed by 129us. See WF_SD_DC48_cnt255.PNG at around 2.2ms.
: Edited by Moderator