'inout' procedure signal

V

valentin tihomirov

Guest
procedure PROPAGATE(signal S: inout std_logic_vector (0 to 10)) is
begin
for I in 1 to 10 loop
S(I) <= S(I-1);
end loop;
end;

signal S: std_logic_vector(0 to 10);
begin
S(0) <= '1';
PROPAGATE(S);


Once the S0 is initialized, the PROPAGATE should be fired. I expect that it
will drive S1..10 assigining S1 <= S0. The update of the S will call
PROPAGATE once again and S2 will be driven by known S1 value in the next
simlulation loop. And so on, until all bits of the vector are filled. My
simulator fails to understand this. Where is the mistake? Seems that
sinthezier is still able to decrypt my message. Sometimes it throws warnings
though depending on the function in S(i) <= FUNC(S(i-1)). I do not see a
better way to propagate signal between the stages.
 
valentin tihomirov wrote:

procedure PROPAGATE(signal S: inout std_logic_vector (0 to 10)) is
begin
for I in 1 to 10 loop
S(I) <= S(I-1);
end loop;
end;

signal S: std_logic_vector(0 to 10);
begin
S(0) <= '1';
PROPAGATE(S);


Once the S0 is initialized, the PROPAGATE should be fired. I expect that it
will drive S1..10 assigining S1 <= S0. The update of the S will call
PROPAGATE once again and S2 will be driven by known S1 value in the next
simlulation loop. And so on, until all bits of the vector are filled. My
simulator fails to understand this. Where is the mistake? Seems that
sinthezier is still able to decrypt my message. Sometimes it throws warnings
though depending on the function in S(i) <= FUNC(S(i-1)). I do not see a
better way to propagate signal between the stages.
Hello Valentin,

I think that it is the delta delays that are the problem. Suppose S(0)
<= '1' is executed at time 0 nS, then S(0) is scheduled to become '1 at
0 nS + 1 delta. The update of S(0) at 0 nS + 1 delta does indeed cause
the procedure to execute at time 0 nS + 1 delta. The procedure then
executes the for loop at time 0 nS + 1 delta, and so executes at 0 nS +
1 delta the statement S(1) <= S(0). This schedules S(1) to take the
value of S(0) at 0 nS + 2 delta (note the 2). The next iteration around
the for loop is also executed however at 0 nS + 1 delta, and schedules
S(2) to take the CURRENT value of S(1) (which since we are not at 0 nS +
2 delta, still at the initial value of 'U') at time 0 nS + 2 delta. So
if I'm correct your simplified example should appear to work for S(1),
but not the rest of the array?

Two solutions: 1) replace, in the simple example S(I) <= S(I-1) with
S(I) <= S(0), but that may mess up your more complex real code so 2) use
something like:

...: for I in 1 to 10 generate
S(i) <= S(I-1)
end generate ...;

Kindest regards, David
 
Did you get any complaints about infinite loops?
No. The S is just undefined including S(0). As I feel the spirit of VHDL,
each bit of vector has only one driver. Saddly, the simulator fails to
understand this.
 
So if I'm correct your simplified example
should appear to work for S(1), but not
the rest of the array?
All the bits are 'U' in simulator. Even the S0 is turned to 'U'. Seems like
procedure output overrides the default S0 <= '1' driver.


Two solutions: 1) replace, in the simple
example S(I) <= S(I-1) with S(I) <= S(0)
The story behind the example is that S(i) <= SomeFunc(S(i-1)) will actually
be used and S will be an array of vectors rather than a vector of bits.


2) use something like:

...: for I in 1 to 10 generate
S(i) <= S(I-1)
end generate ...;
In fact, I was building a package of functions implementing some algorithm.
The algorithm consists of N similar stages. My idea was to put a function
calculating next stage on the previous one. Actually, something like
S <= PROPAGATE(S)
must be created instead of 'inout' procedure to allow regstering interstage
signals for a pipelined design. But the function is worse:

function PROPAGATE(constant S: in std_logic_vector (0 to 10)) return
std_logic_vector is
variable RESULT: std_logic_vector (0 to 10);
begin
RESULT(0) := S(0); -- drive S0 <= S0
for I in 1 to 10 loop
RESULT(I) := not S(I-1);
end loop;
return RESULT;
end;

As you see, a 2nd driver apperars at S0 in addition to S0 <= '1'. I'm stuck,
I cannot see a way to process vectors using VHDL procedures/functions. Your
idea with a component is working in the simulator though:

entity PROPAGATOR is
port (
I: in std_logic_vector (0 to 10);
O: out std_logic_vector (0 to 10)
);
end PROPAGATOR;
architecture IMPL of PROPAGATOR is
begin
L1: for X in 1 to 10 generate
O(X) <= not I(X-1);
end generate;
end;

signal S: std_logic_vector (0 to 10);
begin
S(0) <= '0';
p: entity PROPAGATOR port map (S, S);

However, now it time of synthesier is to fail with "Multiple non-tristate
drivers for net s(0) error". The S0 is not driven by the PROPAGATOR, it is
defenetly sinthersiers's logic error. So, this issue can fray through from
one form to another. Therefore, I specify the goal once again so you can
suggest a typical solution. The goal is to derive succeeding stages of a
vector from the ancestor stages of the same or another vector. An explicit
value is given to the only to STAGE0. So the signal is propageted from the
lower stages to the higher ones. It is desirable if the dataflow would be a
confinable into a function to be placed into a package.

Kindest regards.
 
entity PROPAGATOR is
port (
I: in std_logic_vector (0 to 10);
O: out std_logic_vector (0 to 10)
);
end PROPAGATOR;
architecture IMPL of PROPAGATOR is
begin
L1: for X in 1 to 10 generate
O(X) <= not I(X-1);
end generate;
end;

signal S: std_logic_vector (0 to 10);
begin
S(0) <= '0';
p: entity PROPAGATOR port map (S, S);

However, now it time of synthesier is to fail with "Multiple non-tristate
drivers for net s(0) error". The S0 is not driven by the PROPAGATOR, it is
defenetly sinthersiers's logic error. So, this issue can fray through from
one form to another. Therefore, I specify the goal once again so you can
suggest a typical solution. The goal is to derive succeeding stages of a
vector from the ancestor stages of the same or another vector. An explicit
value is given to the only to STAGE0. So the signal is propageted from the
lower stages to the higher ones. It is desirable if the dataflow would be a
confinable into a function to be placed into a package.

Kindest regards.
OK, I think I understand now, I think my original comments were wrong,
even if the solution proposed sort of works! But I think there are
indeed two drivers generated for S(0) by the above code, one by S(0) <=
'0', and the other by "p: entity PROPAGATOR port map (S, S); ", the 1993
LRM says about drivers (sec 12.6.1 page 164 in my edition), " There is a
single driver for a given scalar signal S (-- in this case S(0)),
provided there is at least on signal assignment statement .. and that
.... the target signal .. denotes S or denotes a composite signal of
which S is a subelement (-- and the composite in this case is S!)", so
the instantiation statement should create a driver for S(0).

Does your simulator let you list the drivers associated with each
signal? I don't understand then why the simulation works, both drivers
should be initialised to 'U', so correctly giving 'U' at time 0, then
when the S(0) <= '0' driver is updated there should then be two values
to resolve, 'U' and '0', so resolving to a 'U' (resolution table in
package std_logic_1164 body), instead of the desired '0'. So I'm lost
as to why the simulation works.

All I can suggest is use of a "for .. generate" at the top level and for
individual statements to be generated, something along the lines of
"p:entity propagator port map(S(0 to 9), S(1 to 10))"?

Kindest regards, David
 
function PROPAGATE(constant S: in std_logic_vector (0 to 10)) return
std_logic_vector is
variable RESULT: std_logic_vector (0 to 10);
begin
RESULT(0) := S(0); -- drive S0 <= S0
for I in 1 to 10 loop
RESULT(I) := not S(I-1);
end loop;
return RESULT;
end;

As you see, a 2nd driver apperars at S0 in addition to S0 <= '1'. I'm
stuck,
I cannot see a way to process vectors using VHDL procedures/functions.
Your
idea with a component is working in the simulator though:
use an intermediate variable

process (s)
variable v_s : std_logic_vector(s'range); -- for method 1 and 2
variable v_s0 : std_logic; -- for method 3
begin
-- method 1
v_s := s;
v_s(0) := '1';
s <= PROPAGATE(v_s);

-- method 2
s(0) <= '1';
v_s := PROPAGATE(s);
s(1 to 10) <= v_s(1 to 10);

-- method 3
v_s0 := '1';
s <= PROPAGATE(v_s0 & s(1 to 10));
end process;

or just

s <= PROPAGATE('1' & s(1 to 10));

or return less bit from your function like this:

function modified_PROPAGATE(constant S: in std_logic_vector (0 to 10))
return std_logic_vector is
variable RESULT: std_logic_vector (1 to 10);
begin
for I in 1 to 10 loop
RESULT(I) := not S(I-1);
end loop;
return RESULT;
end;

S(0) <= '1';
S(1 to 10) <= modified_PROPAGATE(S)

regards
fe
 
On Tue, 28 Jun 2005 22:53:47 +0300, "valentin tihomirov"
<spam@abelectron.com> wrote:

procedure PROPAGATE(signal S: inout std_logic_vector (0 to 10)) is
begin
for I in 1 to 10 loop
S(I) <= S(I-1);
end loop;
end;

signal S: std_logic_vector(0 to 10);
This "begin" is the beginning of an ARCHITECTURE, I assume...
so this line creates a process that puts a driver on S(0)...
S(0) <= '1';
and this line creates a process that puts a driver on
every element of S...
PROPAGATE(S);
and since PROPAGATE never assigns to S(0), the procedure
permanently drives S(0) with 'U'. Everything is working
exactly as it should :)

You could hack your way around it by writing
S(0) <= 'Z';
as the first line of the procedure PROPAGATE. Ugh.

As someone else said, use a generate loop so that you
can control the drivers on S element-by-element.
--
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:jonathan.bromley@doulos.com
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.
 
valentin tihomirov wrote:
procedure PROPAGATE(signal S: inout std_logic_vector (0 to 10)) is
begin
for I in 1 to 10 loop
S(I) <= S(I-1);
end loop;
end;

signal S: std_logic_vector(0 to 10);
begin
S(0) <= '1';
PROPAGATE(S);


Once the S0 is initialized, the PROPAGATE should be fired. I expect that it
will drive S1..10 assigining S1 <= S0. The update of the S will call
PROPAGATE once again and S2 will be driven by known S1 value in the next
simlulation loop. And so on, until all bits of the vector are filled. My
simulator fails to understand this. Where is the mistake? Seems that
sinthezier is still able to decrypt my message. Sometimes it throws warnings
though depending on the function in S(i) <= FUNC(S(i-1)). I do not see a
better way to propagate signal between the stages.
There's no timing information in this! Ask yourself: "when does S(0)
update?" Further ask yourself: "When does S(I) update?"

If I read Ashenden correctly, the signal inout parameter means that
when the procedure is called, it is given both the signal and a
reference to its driver. This means that it uses the signal part as
the input (basically, everything on the RHS of your assignment's <=)
and it schedules a transaction on the driver.

So, if there is no wait or other statement that advances simulation
time, you don't get useful results.

Did you get any complaints about infinite loops?

-a
 

Welcome to EDABoard.com

Sponsor

Back
Top