problem in procedure

A

ashu

Guest
hi ,

is it possible to write any clocked function in procedure i.e. i had
written a simple DOWNCOUNTER by using procedure, but when i m calling
the procedure it is counting only up to one place like 15, 14....

can any body suggest some remedy ........code is given below

------------------------------------------------------------------------------------------------------------------------------------
ibrary ieee ;
use ieee.std_logic_1164.all ;
use ieee.std_logic_unsigned.all ;
use ieee.std_logic_arith.all ;



entity check is

port (
clk ,rst : in std_logic ;
count : out std_logic_vector(3 downto 0)
);

end check ;

architecture a of check is

--- declaration of procedure ---
procedure my (
signal clock ,reset : in std_logic ;
signal co : out std_logic_vector(3 downto 0)
) is



variable q : integer range 15 downto 0 ;

begin

if ( reset = '1' ) then


if (clock'event and clock = '1') then


if (q = 0) then

q := 15 ;

else

q := q - 1 ;

end if ;

co <= conv_std_logic_vector(q,4) ;

end if ;

else

q := 15 ;

co <= "1111" ;


end if ;


end my ;

begin

-------------- -------- procedure call ----- -----------------
----------------

my (clk,rst,count); ------ here it is counting only upto
14 i.e. only one place


end a ;
 
ashu wrote:
hi ,

is it possible to write any clocked function in procedure i.e. i had
written a simple DOWNCOUNTER by using procedure, but when i m calling
the procedure it is counting only up to one place like 15, 14....

can any body suggest some remedy ........code is given below
if i remember correctly, you can not have wait statements inside a
procedure in synthesizable VHDL code.


check out the UART code by Mike Treseler for a simple example:
http://home.comcast.net/~mike_treseler/uart.vhd
 
ashu wrote:

hi ,

is it possible to write any clocked function in procedure i.e. i had
written a simple DOWNCOUNTER by using procedure, but when i m
calling the procedure it is counting only up to one place like 15,
14....

can any body suggest some remedy ........code is given below
Yikes, the indentation is awfull! There seem t be funny characters in
you code.

Anyhow, your problem is caused by the local variable q of procedure
my.

Everytime the procedure exits, the value the local variable is lost.
On entering the procedure again, it is initialized again to the left
most value of its type, 15 in this case. Hence, you see only value
14.

To avoid losing the value of a local variable, the procedure must not
exit. So an endless loop is needed. With that, also a wait statement
is needed.

I've rewritten the code below.

Please note that I use package numeric_std and function to_unsigned.
Packages std_logic_arith and std_logic_unsigned are not IEEE
standardized and should not be used anymore.

Furthermore, I've rewritten the reset a bit, so that there's only one
assignment to co and no need for the magical constant "1111". This
improves maintainability of the code.

I've not tested the code and I have no idea whether it is
synthesizable. It should simulate though.


library ieee ;
use ieee.std_logic_1164.all ;
use ieee.numeric_std.all ;

entity check is
port
(
clk ,rst : in std_logic ;
count    : out std_logic_vector(3 downto 0)
);
end check ;

architecture a of check is

--- declaration of procedure ---
procedure my
(
signal clock, reset : in  std_logic ;
signal co     : out std_logic_vector(3 downto 0)
) is
variable q : integer range 15 downto 0 ;
begin
forever: loop
wait on clock, reset;

if clock'event and clock = '1' then
if q = 0 then
q := 15 ;
else
q := q - 1 ;
end if ;
end if ;

if reset = '0' then
q := 15 ;
end if ;

co <= std_logic_vecctor(to_unsigned(q, 4)) ;
end loop ;
end my ;

begin
my (clk,rst,count); 
end a;

--
Paul.
 
You cannot do this with a variable, since you can't declare one outside
the procedure and outside of a process, but you could use an inout
signal parameter that remembers the value from one invocation to the
next.

Keep in mind that a concurrent procedure call is really inside an
implied process, with "wait on" list equal to all the in or inout
parameters in the procedure call. When the procedure exits and
re-enters when the implied process triggers again, the internal
variables are reset to their initial conditions (implied or explicit in
their declarations).

You could also put the procedure call in an explicit process, with an
appropriate sensitivity list or wait statement prior to the procedure
call. If the procedure is declared within the process, and after a
process variable, then the process sutomatically has visibility of that
variable, and it need not be even passed as a parameter. Because the
variable would be declared (and initialized, either explicilty or
implicitly) in the process, which never exits, it would retain its
value between procedure invocations.

process (clk, rst) is

-- declare variable to be used inside procedure here
variable q integer range 15 downto 0; -- initializes to 15!

-- declare procedure that uses variable here
procedure my (clk,rst .... ) is
....
begin
-- call procedure here
my(clk, rst, co);
end process;

Andy


Paul Uiterlinden wrote:
ashu wrote:

hi ,

is it possible to write any clocked function in procedure i.e. i had
written a simple DOWNCOUNTER by using procedure, but when i m
calling the procedure it is counting only up to one place like 15,
14....

can any body suggest some remedy ........code is given below

Yikes, the indentation is awfull! There seem t be funny characters in
you code.

Anyhow, your problem is caused by the local variable q of procedure
my.

Everytime the procedure exits, the value the local variable is lost.
On entering the procedure again, it is initialized again to the left
most value of its type, 15 in this case. Hence, you see only value
14.

To avoid losing the value of a local variable, the procedure must not
exit. So an endless loop is needed. With that, also a wait statement
is needed.

I've rewritten the code below.

Please note that I use package numeric_std and function to_unsigned.
Packages std_logic_arith and std_logic_unsigned are not IEEE
standardized and should not be used anymore.

Furthermore, I've rewritten the reset a bit, so that there's only one
assignment to co and no need for the magical constant "1111". This
improves maintainability of the code.

I've not tested the code and I have no idea whether it is
synthesizable. It should simulate though.


library ieee ;
use ieee.std_logic_1164.all ;
use ieee.numeric_std.all ;

entity check is
port
(
clk ,rst : in std_logic ;
count : out std_logic_vector(3 downto 0)
);
end check ;

architecture a of check is

--- declaration of procedure ---
procedure my
(
signal clock, reset : in std_logic ;
signal co : out std_logic_vector(3 downto 0)
) is
variable q : integer range 15 downto 0 ;
begin
forever: loop
wait on clock, reset;

if clock'event and clock = '1' then
if q = 0 then
q := 15 ;
else
q := q - 1 ;
end if ;
end if ;

if reset = '0' then
q := 15 ;
end if ;

co <= std_logic_vecctor(to_unsigned(q, 4)) ;
end loop ;
end my ;

begin
my (clk,rst,count);
end a;

--
Paul.
 
Andy wrote:

You cannot do this with a variable,
Yes, you can (see below).

since you can't declare one
outside the procedure and outside of a process, but you could use an
inout signal parameter that remembers the value from one invocation
to the next.

Keep in mind that a concurrent procedure call is really inside an
implied process, with "wait on" list equal to all the in or inout
parameters in the procedure call. When the procedure exits and
re-enters when the implied process triggers again, the internal
variables are reset to their initial conditions (implied or explicit
in their declarations).
I think you missed the fact that I added an endless loop in the
procedure. By doing so, the procedure never exits, hence the value of
the local variable is not lost. I use this technique quite often in
behavioural models.

library ieee ;
use ieee.std_logic_1164.all ;
use ieee.numeric_std.all ;

entity check is
port
(
clk ,rst : in std_logic ;
count : out std_logic_vector(3 downto 0)
);
end check ;

architecture a of check is

--- declaration of procedure ---
procedure my
(
signal clock, reset : in std_logic ;
signal co : out std_logic_vector(3 downto 0)
) is
variable q : integer range 15 downto 0 ;
begin
-- Endless loop to retain value of variable
-- <<<<<<<<<
forever: loop
wait on clock, reset;

if clock'event and clock = '1' then
if q = 0 then
q := 15 ;
else
q := q - 1 ;
end if ;
end if ;

if reset = '0' then
q := 15 ;
end if ;

co <= std_logic_vecctor(to_unsigned(q, 4)) ;
end loop forever;
end my ;

begin
my (clk,rst,count);
end a;
--
Paul.
 
Paul Uiterlinden wrote:
Andy wrote:

You cannot do this with a variable,

Yes, you can (see below).
I'm assuming we are talking about synthesizable code here (e.g. clocks
and resets)...

I should have said "... in a synthesizable, concurrent procedure call",
since the loop to keep the procedure from exiting requires a wait
statement to allow time to elapse, which is not allowed inside a
subprogram for synthesis.

Andy
since you can't declare one
outside the procedure and outside of a process, but you could use an
inout signal parameter that remembers the value from one invocation
to the next.

Keep in mind that a concurrent procedure call is really inside an
implied process, with "wait on" list equal to all the in or inout
parameters in the procedure call. When the procedure exits and
re-enters when the implied process triggers again, the internal
variables are reset to their initial conditions (implied or explicit
in their declarations).

I think you missed the fact that I added an endless loop in the
procedure. By doing so, the procedure never exits, hence the value of
the local variable is not lost. I use this technique quite often in
behavioural models.

library ieee ;
use ieee.std_logic_1164.all ;
use ieee.numeric_std.all ;

entity check is
port
(
clk ,rst : in std_logic ;
count : out std_logic_vector(3 downto 0)
);
end check ;

architecture a of check is

--- declaration of procedure ---
procedure my
(
signal clock, reset : in std_logic ;
signal co : out std_logic_vector(3 downto 0)
) is
variable q : integer range 15 downto 0 ;
begin
-- Endless loop to retain value of variable
--
forever: loop
wait on clock, reset;

if clock'event and clock = '1' then
if q = 0 then
q := 15 ;
else
q := q - 1 ;
end if ;
end if ;

if reset = '0' then
q := 15 ;
end if ;

co <= std_logic_vecctor(to_unsigned(q, 4)) ;
end loop forever;
end my ;

begin
my (clk,rst,count);
end a;

--
Paul.
 
Andy wrote:

Paul Uiterlinden wrote:
Andy wrote:

You cannot do this with a variable,

Yes, you can (see below).

I'm assuming we are talking about synthesizable code here (e.g.
clocks and resets)...
No. I don't like synthesizable code. All those restrictions... ;-)

I should have said "... in a synthesizable, concurrent procedure
call", since the loop to keep the procedure from exiting requires a
wait statement to allow time to elapse, which is not allowed inside
a subprogram for synthesis.
Yes, now you say it that way, I fully agree. No argument about that.

--
Paul.
 

Welcome to EDABoard.com

Sponsor

Back
Top