'inout' procedure signal

Discussion in 'VHDL' started by valentin tihomirov, Jun 28, 2005.

  1. 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, Jun 28, 2005
    #1
    1. Advertisements

  2. valentin tihomirov

    Andy Peters Guest

    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
     
    Andy Peters, Jun 28, 2005
    #2
    1. Advertisements

  3. valentin tihomirov

    David Hendry Guest

    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
     
    David Hendry, Jun 29, 2005
    #3
  4. 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.
     
    valentin tihomirov, Jun 29, 2005
    #4
  5. All the bits are 'U' in simulator. Even the S0 is turned to 'U'. Seems like
    procedure output overrides the default S0 <= '1' driver.

    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.

    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.
     
    valentin tihomirov, Jun 29, 2005
    #5
  6. valentin tihomirov

    David Hendry Guest

    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
     
    David Hendry, Jun 29, 2005
    #6
  7. valentin tihomirov

    fe Guest

    function PROPAGATE(constant S: in std_logic_vector (0 to 10)) return
    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
     
    fe, Jun 30, 2005
    #7
  8. This "begin" is the beginning of an ARCHITECTURE, I assume...
    so this line creates a process that puts a driver on S(0)...
    and this line creates a process that puts a driver on
    every element of 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:
    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.
     
    Jonathan Bromley, Jun 30, 2005
    #8
    1. Advertisements

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 (here). After that, you can post your question and our members will help you out.