Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
9 years ago

Edge detection asynchronous signal fails

Hello,

I am working on a fairly simple VHDL design where I am trying to detect the rising_edge of an input. Whenever a rising_edge is detected I want to multiply another input by 2 and output it. The input that serves the "start" siginal is data_ready and it changes asynchronously. Since data_ready is not a clock it is my understanding that I cannot use rising_edge( data_ready ) so I store the previous value of data_ready. in an internal signal previous_value and compare it to the current value data_ready.

It feel my code should work but during simulation it fails. What am I doing wrong?

entity mul is port(
 my_input     : in std_logic_vector( 7 downto 0 );
 data_ready   : in std_logic;
 my_output    : out std_logic_vector( 8 downto 0 )
);
end mul;
architecture behavior of mul is
  signal previous_value : std_logic := '0';
begin
  
 mul_2 : process( data_ready )
 begin
   if data_ready = '1' AND previous_value = '0' then  -- detect rising edge
     previous_value <= data_ready;                          -- set previous value
     my_output <= my_input( 7 downto 0 ) & "0";     -- mul by 2, shift left
   else
     my_output <= "111000111";
   end if;
 end process;
     
end behavior; 

Testbench:

BEGIN                                                        
        -- code that executes only once            
   dataReady  <= '0';
   heading_in <= "11100011"; 
   wait for 40ns;
   
   dataReady <= '1';               -- generate rising edge
   wait for 40ns;                     -- expected output 111000110
   
   dataReady <= '0';
WAIT;                                                       
END PROCESS init;  

Thanks for your help!

10 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Your circuit design will not work in real hardware. Because you have no clock to time the registering of your signals, you're basically asking it to store the value of data_ready from 0s ago. Think about the circuit you expect and draw it on paper before writing the code.

    FOr simulation, your code does work as you expected, assuming you're doing RTL simulation. If you're doing a netlist simulation (that you get with Quartus) then the problem will be because of what I said above.

    I suggest using a clock and synchronising your design. Memory elements are not really possible without one.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    I think what causes confusion to beginners is the term "edge detection".

    We are used to think of "edge" as clock rising or falling edge.

    For other signals(apart from clock) we can't detect rising or falling edge but we want to identify the first transition pulse (that extends over one clock period).

    It is better defined as rising sample.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Thanks both for your replies. I changed my code (see below) so it works on a rising_edge of a clock input and also removed the else statement since I got glitches on my_output. Seems like my_output was changed to quick. It works now

    A follow up question to @Tricky comment: how do concurrent statements outside a process work then? Don't say also assume that the values are ready from 0s? e.g.

    my_output <= '111111111' when data_ready = '1';

    Or would i use the after statement here?

    Changed code of the original question:(working now):

    entity mul is port(
    	clk			: in std_logic;
    	my_input 	: in std_logic_vector( 7 downto 0 );
    	data_ready 	: in std_logic;
    	my_output	: out std_logic_vector( 8 downto 0 )
    );
    end mul;
    architecture behavior of mul is
    	signal previous_value : std_logic := '0';
    begin	
    	mul_2 : process( clk )
    	begin
    		if rising_edge( clk ) then
    			previous_value <= data_ready;							   -- set previous value
    			if data_ready = '1' AND previous_value = '0' then				-- detect rising edge
    				my_output <= my_input(7 downto 0) & "0";		-- mul by 2, shift left
    			end if;
    		end if;
    	end process;					
    end behavior;	

    Testbench:

    
    BEGIN                                                        
            -- code that executes only once                      
    	data_ready <= '0';
    	my_input <= "11100011";  -- expected output 111000110
    	wait for 200ns;
    	
    	data_ready <= '1';
    	wait for 200ns;
    	
    	data_ready <= '0';
    	my_input <= "00110011";
    	wait for 200ns;
    	
    	data_ready <= '1';		
    	wait for 200ns;
    WAIT;                                                       
    END PROCESS init;    
                                           
    -- clock generation - 50MHz
    process
    begin
      clk <= '1';
      wait for 10 ns;
      clk <= '0';
      wait for 10 ns;
    end process;  

    Cheers and thanks.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    A follow up question to @Tricky comment: how do concurrent statements outside a process work then? Don't say also assume that the values are ready from 0s? e.g.

    my_output <= '111111111' when data_ready = '1';

    Or would i use the after statement here?

    --- Quote End ---

    They work exactly as you expect the underlying hardware to work. This example is fairly pointless - as it would set the output to all 1s when some data_ready input is '1', so you've built a latch because it does not have an else clause.

    The after keyword is purely for simulation. It has no meaning in a real circuit as absolute delay elements do not exist. They are meant to model the propogation delay that may occur in a real circuit. They will be removed for synthesis (with associated warnings). So unless you want them for modelling purposes, do not use them. If you have a synchronous design you will never need them.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    They work exactly as you expect the underlying hardware to work. This example is fairly pointless - as it would set the output to all 1s when some data_ready input is '1', so you've built a latch because it does not have an else clause.

    The after keyword is purely for simulation. It has no meaning in a real circuit as absolute delay elements do not exist. They are meant to model the propogation delay that may occur in a real circuit. They will be removed for synthesis (with associated warnings). So unless you want them for modelling purposes, do not use them. If you have a synchronous design you will never need them.

    --- Quote End ---

    Thanks for the clarification!
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    Unfortunately my earlier statement was wrong. I still see glitches with the synchronous code above. Here is the output from my test bench:

    https://www.alteraforum.com/forum/attachment.php?attachmentid=13378

    Is that normal?

    --- Quote End ---

    Well, now that I think about it. I guess it does not matter since my_output is stable at the next rising_edge. Before that my_output is not read by any other component.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Are you simulating the code or the post place and route netlist? This would be normal in the netlist as the tracks for each bit will be different lengths. As long as they dont violate the setup/hold times in timequest it will be ok.

    This assumes that my_input and data_ready are synchronised to the clock domain. Using asynchronous signals will cause bad glitches.

    Note: in your testbench you are using absolute time delays - I recommend synchronising your testbench to your clock otherwise you might get delta problems if any input aligns with the clock.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    I don't know whether it is the code or the post place & netlist. I am running a Gate Level Simulation. I am using Quartus II.

    Thanks for your tip with the time delays!
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- Quote Start ---

    I don't know whether it is the code or the post place & netlist. I am running a Gate Level Simulation. I am using Quartus II.

    Thanks for your tip with the time delays!

    --- Quote End ---

    Qate level simulation is the quartus compiled code you are simulating. You are not simulating your RTL directly.