Community
cancel
Showing results for 
Search instead for 
Did you mean: 
Altera_Forum
Honored Contributor I
1,627 Views

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!
0 Kudos
10 Replies
Altera_Forum
Honored Contributor I
100 Views

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
Honored Contributor I
100 Views

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
Honored Contributor I
100 Views

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
Honored Contributor I
100 Views

 

--- 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
Honored Contributor I
100 Views

 

--- 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
Honored Contributor I
100 Views

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?
Altera_Forum
Honored Contributor I
100 Views

 

--- 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
Honored Contributor I
100 Views

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
Honored Contributor I
100 Views

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
Honored Contributor I
100 Views

 

--- 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.