edge detection using subprograms

M

M.Randelzhofer

I'm trying to simplify my vhdl code for synchronious edge detection of
signals by using of subprograms. Unfortunately there are no examples on the
web (or difficult to find) how sequential procedures work.

Normally i use a sequential process to built a shift register for edge
detection:

process (clock)
begin
if (clock'event and clock ='1') then
shift(0) <= signal ;
shift(1) <= shift(0) ;
end if ;
rise <= not shift(1) and shift(0) ;
fall <= shift(1) and not shift(0) ;
end process;

Now i would like to use a procedure as a subprogram, to simplify the code
for lots of such situations.

As i understood, functions can not be used for sequential statements, but
procedures.

I tried some code, but it does't work:

procedure edge(
signal clk,din: in STD_LOGIC ;
signal edv: inout STD_LOGIC_VECTOR (1 downto 0)
) is
begin
if Rising_Edge(clk) then
edv(0) <= din ;
edv(1) <= edv(0) ;
end if;
end edge;

function rise(edv: STD_LOGIC_VECTOR (1 downto 0)) return std_logic is
begin
return not edv(1) and edv(0) ;
end rise ;

function fall(edv: STD_LOGIC_VECTOR (1 downto 0)) return std_logic is
begin
return edv(1) and not edv(0) ;
end fall ;

edge(clock,clkdiv(26),ed_cd26);
output <= rise(ed_cd26) ;

Any hints or suggestions for working procedures ?
Thanks in advance

MIKE
 
J

Jonathan Bromley

Normally i use a sequential process to built a shift register for edge
detection:

process (clock)
begin
if (clock'event and clock ='1') then
shift(0) <= signal ;
shift(1) <= shift(0) ;
end if ;
rise <= not shift(1) and shift(0) ;
fall <= shift(1) and not shift(0) ;
end process;

Many synthesis tools will reject this process,
because the assignments to "rise" and "fall"
are performed both on rising and on falling edges
of the clock. Consider splitting it into two
processes, one synchronous and one combinational.

Now i would like to use a procedure as a subprogram, to simplify the code
for lots of such situations.

[...]

A subprogram is called by some other sequential code, executes
for a certain length of time, and then terminates and returns
to its calling code.

A process starts executing at time zero, and then runs forever
as an independent piece of activity.

It would make no sense to bury your process in the middle
of another process, so equally it makes no sense to try to
call a subprogram to do the same thing.

The obvious way to modularise this kind of thing is by
building an entity to contain it, and then instantiating
the entity. However, there is another possibility that
is sometimes neater: use a concurrent procedure. This
is simply a way of packaging a process so that you can
"instantiate" it, but without the extra overhead of
defining a component and so on. However, a concurrent
procedure effectively becomes a process, and so it would
have the same problem that I pointed out for your
original process - it's a synchronous process with
combinational outputs, and therefore should not be
described as a single process for synthesis.
--
Jonathan Bromley, Consultant

DOULOS - Developing Design Know-how
VHDL, Verilog, SystemC, Perl, Tcl/Tk, Verification, Project Services

Doulos Ltd. Church Hatch, 22 Market Place, Ringwood, BH24 1AW, UK
Tel: +44 (0)1425 471223 mail:[email protected]
Fax: +44 (0)1425 471573 Web: http://www.doulos.com

The contents of this message may contain personal views which
are not the views of Doulos Ltd., unless specifically stated.
 
M

Mike Treseler

M.Randelzhofer said:
Thank you very much for the examples.
Interesting kind of variable processing, remembers me of some kind of state
machines.
However this doesn't simplify my code. At the end i have to explain that to
my customers.
Seems that a sequential 'macro' is not so easy to implement in VHDL.

--OK I'll bite.
--Let's get rid of the nasty variables.

--If we clean up your example we have:
------------------------------------
library ieee;
use ieee.std_logic_1164.all;
entity rise_fall is

port (clock : in std_ulogic;
serial_in : in std_ulogic;
rise : out std_ulogic;
fall : out std_ulogic
);
end entity rise_fall;

architecture plain of rise_fall is
signal shift : std_logic_vector(1 downto 0);
begin
process (clock)
begin
if (clock'event and clock = '1') then
shift(0) <= serial_in;
shift(1) <= shift(0);
rise <= not shift(1) and shift(0);
fall <= shift(1) and not shift(0);
end if;
end process;
end architecture plain;
--------------------------------------

--Now, if you like, we could do
--the rise and fall values like this

architecture fun of rise_fall is
signal shift : std_logic_vector(1 downto 0);
begin
process (clock)
impure function rise_f (arg : std_logic_vector(1 downto 0))
return std_ulogic is begin
return not arg(1) and arg(0);
end function rise_f;

impure function fall_f (arg : std_logic_vector(1 downto 0))
return std_ulogic is begin
return arg(1) and not arg(0);
end function fall_f;
begin
if (clock'event and clock = '1') then
shift(0) <= serial_in;
shift(1) <= shift(0);
rise <= rise_f(shift);
fall <= fall_f(shift);
end if;
end process;
end architecture fun; -- --

-- Or we could replace the rise and fall
-- statements with procedures like this

architecture proc of rise_fall is
signal shift : std_logic_vector(1 downto 0);
signal rise_s, fall_s : std_ulogic;
begin
process (clock)
procedure edges(
arg : in std_logic_vector(1 downto 0);
signal out_rise : out std_ulogic;
signal out_fall : out std_ulogic
) is
begin
out_rise <= not arg(1) and arg(0);
out_fall <= arg(1) and not arg(0);
end procedure edges;
begin
if (clock'event and clock = '1') then
shift(0) <= serial_in;
shift(1) <= shift(0);
edges(shift, rise, fall);
end if;
end process;
end architecture proc;


-- Mike Treseler
 
J

Jim Lewis

Mike,
Functionally the subprogram you wrote (edge) is correct.
In fact, I believe it is compliant with the 2004 version
of IEEE 1076.6 the VHDL RTL Synthesis specification.

Currently vendors have not implemented all features of
IEEE 1076.6-2004 yet. They are waiting for you to tell them
what is important. Your way to do this is to turn you
example in to your vendor as a bug and let them know it
is compliant with 1076.6-2004.

Going further 1076.6-2004 provides coding styles for a wide
variety of things. One of these is a portable coding
style for a DPRAM. If this is useful to you, let your
vendor know. I know this sounds silly at first, but think
of it from the other side - are you going to invest in
something if it does not bring significant value to your
customers?

Cheers,
Jim Lewis
P.S.
You might get more utility our of your procedure if
you used an unconstrained array. For readability,
you also might consider renaming it something like
ShiftReg rather than edge
--
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Jim Lewis
Director of Training mailto:[email protected]
SynthWorks Design Inc. http://www.SynthWorks.com
1-503-590-4787

Expert VHDL Training for Hardware Design and Verification
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,774
Messages
2,569,599
Members
45,175
Latest member
Vinay Kumar_ Nevatia
Top