Only few VHDL programmers know that there is something called "rising_edge()" function.Even those who know about it, they still stick to the old fashioned clk'event and clk='1' method of finding an edge transition of clock.So in this article I will explain the difference between rising_edge or falling_edge function and clk'event based edge detection.
Consider the following snippet:
clk_process :process
begin
clk <= '0';
wait for clk_period/2; --for 0.5 ns
signal is '0'.
clk <= '1';
wait for clk_period/2; --for next 0.5 ns
signal is '1'.
end process;
process(clk)
begin
if(rising_edge(clk)) then
xr<= not xr;
end if;
if(clk'event and clk='1') then
x0 <= not x0;
end if;
end process;
begin
clk <= '0';
wait for clk_period/2; --for 0.5 ns
signal is '0'.
clk <= '1';
wait for clk_period/2; --for next 0.5 ns
signal is '1'.
end process;
process(clk)
begin
if(rising_edge(clk)) then
xr<= not xr;
end if;
if(clk'event and clk='1') then
x0 <= not x0;
end if;
end process;
If you run the above code the output will look like this:
Now you may ask where is the difference? There is no difference in this case.But let us see another example:
clk_process :process
begin
clk <= 'Z'; ----------Here is the change('Z'
instead of '0').
wait for clk_period/2; --for 0.5 ns signal is '0'.
clk <= '1';
wait for clk_period/2; --for next 0.5 ns
signal is '1'.
end process;
process(clk)
begin
if(rising_edge(clk)) then
xr<= not xr;
end if;
if(clk'event and clk='1') then
x0 <= not x0;
end if;
end process;
begin
clk <= 'Z'; ----------Here is the change('Z'
instead of '0').
wait for clk_period/2; --for 0.5 ns signal is '0'.
clk <= '1';
wait for clk_period/2; --for next 0.5 ns
signal is '1'.
end process;
process(clk)
begin
if(rising_edge(clk)) then
xr<= not xr;
end if;
if(clk'event and clk='1') then
x0 <= not x0;
end if;
end process;
Now the output will look like this:
Does this ring any bells?You can see that the signal 'xr' doesn't change at all,but x0 changes as in the first code.Well this is the basic difference between both the methods.To get a clear view look at the rising_edge function as implemented in std_logic_1164 library:
FUNCTION rising_edge (SIGNAL s : std_ulogic)
RETURN BOOLEAN IS
BEGIN
RETURN (s'EVENT AND (To_X01(s) = '1') AND
(To_X01(s'LAST_VALUE) = '0'));
END;
RETURN BOOLEAN IS
BEGIN
RETURN (s'EVENT AND (To_X01(s) = '1') AND
(To_X01(s'LAST_VALUE) = '0'));
END;
As you can see the function returns a value "TRUE" only when the present value is '1' and the last value is '0'.If the past value is something like 'Z','U' etc. then it will return a "FALSE" value.This makes the code, bug free, beacuse the function returns only valid clock transitions,that means '0' to '1'.All the rules and examples said above equally apply tofalling_edge() function also.
But the statement (clk'event and clk='1') results TRUE when the present value is '1' and there is an edge transition in the clk.It doesnt see whether the previous value is '0' or not.
Note :- Use rising_edge() and falling_edge() functions instead of (clk'event and clk='1') statements in your designs.