VHDL subprocedure call

Discussion in 'VHDL' started by Richard Molgner, Jan 18, 2011.

  1. Hi all,

    I have two nested procedures, where the "main" procedure makes use of
    "subproc" to accumulates a result in variables t0 and t1, which is
    then returned at the end. This should all be computed in one clock
    cycle, and the circuit more or less just consists of simple logic
    gates (xor, or, and). When I try to describe the circuit as below I
    get the following error:

    Acutal (variable t0) for formal "a" is not a signal

    That makes sense as the subprocure requires signals as input, but I
    wanna pass it a variable during the main procedure. Is there a simple
    way to circumvent this problem with casting for example?

    Thanks

    procedure subproc
    (
    signal a : in std_logic_vector(31 downto 0);
    signal b : in std_logic_vector(31 downto 0);
    signal c : in std_logic_vector(31 downto 0);
    signal d : in std_logic_vector(31 downto 0);
    signal e : out std_logic_vector(31 downto 0);
    signal f : out std_logic_vector(31 downto 0)
    )
    is
    variable x : std_logic_vector(31 downto 0);
    variable y : std_logic_vector(31 downto 0);
    begin

    x := (others => '0');
    y := (others => '0');

    for i in 0 to 31 loop
    x(i) := (a(i) xor b(i)) and (c(i) xor d(i));
    y(i) := (a(i) xor b(i)) or ((d(i) xor c(i)) xor b(i));
    end loop;

    e <= x(31 downto 0);
    f <= y(31 downto 0);

    end;

    procedure main
    (
    signal a : in std_logic_vector(31 downto 0);
    signal b : in std_logic_vector(31 downto 0);
    signal r : out std_logic_vector(31 downto 0)
    )
    is
    variable res : std_logic_vector(31 downto 0);
    variable t0, t1 : std_logic_vector(31 downto 0);
    constant c : std_logic_vector(31 downto 0) := X"fedcba90";
    constant d : std_logic_vector(31 downto 0) := X"7654321f";
    begin

    t0 := (others => '0');
    t1 := (others => '0');

    for i in 0 to 31 loop
    if ( (c(i) = '0') && (d(i) = '1') ) then
    subproc( t0, t1,
    a, b, t0, t1 );
    end if;
    end loop;

    r <= t0;
    end;
    Richard Molgner, Jan 18, 2011
    #1
    1. Advertising

  2. Hi again,

    I updated the routine now, and it looks as follows. Although it
    compiles fine, the output
    of the computation is ALWAYS ZERO. It seems with this software-like
    implementation I wont
    be able to describe the hardware circuit I want to. Or does anyone see
    a problem with my
    VHDL description?

    procedure main
    (
    signal a : in std_logic_vector(31 downto 0);
    signal b : in std_logic_vector(31 downto 0);
    signal r : out std_logic_vector(31 downto 0)
    )
    is
    variable res : std_logic_vector(31 downto 0);
    variable t0, t1 : std_logic_vector(31 downto 0);
    constant c : std_logic_vector(31 downto 0) := X"fedcba90";
    constant d : std_logic_vector(31 downto 0) :=
    X"7654321f";
    begin

    t0 := (others => '0');
    t1 := (others => '0');

    for i in 0 to 31 loop
    if ( (c(i) = '0') and (d(i) = '1') ) then
    for j in 0 to 31 loop
    t0(j) := (a(j) xor b(j)) and (t0(j) xor t1(j));
    t1(j) := (a(j) xor b(j)) or ((t1(j) xor t0(j)) xor
    b(j));
    end loop;
    end if;
    end loop;

    r <= t0;
    end;

    many thanks
    Richard Molgner, Jan 18, 2011
    #2
    1. Advertising

  3. Richard Molgner <> writes:

    > Hi again,
    >
    > I updated the routine now, and it looks as follows. Although it
    > compiles fine, the output
    > of the computation is ALWAYS ZERO.


    In simulation or synthesis? I might expect the output to be all Us in
    simulation. Zeros seems plausible for synthesis.

    > It seems with this software-like
    > implementation I wont
    > be able to describe the hardware circuit I want to. Or does anyone see
    > a problem with my
    > VHDL description?
    >


    Have you put a call to that procedure inside an entity? Unless *you*
    call the procedure it won't get called - there's no implicit
    (well, startup-code defined) call to main like there is in c. The
    simulator "runs" a top-level entity that you tell it to. The
    synthesiser also works on a top-level entity. Procedures are not the
    "top" that you may be thinking they are.

    I'll attempt to describes what needs to go on (on the assumption that
    you are new to VHDL, not and old hand trying some new tricks :) If
    we're lucky, it's possible that Jonathan Bromley will also chip in and
    give you a description - his is likely to be much better than mine as
    he's (been) a professional trainer!

    Anyway....

    What you have to do is create an "entity" which describes the
    interface (in terms of input and/or output pins) to the logic you
    want. (This interface will look like the procedure definition
    currently does.)

    That entity then has an "architecture" which describes what goes on
    inside the block to bring the ins and outs of that interface together.

    Your procedure is a description of some logic which can go inside that
    architecture... inside a "process".

    Processes control when code "runs", and you want to run yours whenever a
    or b changes. So you need to give a sensitivity list to the process
    which has both a and b in it. Then, whenever a or b changes, the
    process will run and that can call your procedure. At the end of the
    process, it will stop and wait for the next change on any of the
    signals in the sensitivity list.

    <snip code>

    I hope that helps a little!

    Cheers,
    Martin

    --

    TRW Conekt - Consultancy in Engineering, Knowledge and Technology
    http://www.conekt.co.uk/capabilities/39-electronic-hardware
    Martin Thompson, Jan 18, 2011
    #3
  4. Richard Molgner

    rickman Guest

    On Jan 18, 9:29 am, Richard Molgner <> wrote:
    > Hi again,
    >
    > I updated the routine now, and it looks as follows. Although it
    > compiles fine, the output
    > of the computation is ALWAYS ZERO. It seems with this software-like
    > implementation I wont
    > be able to describe the hardware circuit I want to. Or does anyone see
    > a problem with my
    > VHDL description?
    >
    >  procedure main
    >     (
    >       signal a : in  std_logic_vector(31 downto 0);
    >       signal b : in  std_logic_vector(31 downto 0);
    >       signal r : out std_logic_vector(31 downto 0)
    >     )
    >     is
    >       variable res : std_logic_vector(31 downto 0);
    >       variable t0, t1 : std_logic_vector(31 downto 0);
    >       constant c : std_logic_vector(31 downto 0) := X"fedcba90";
    >       constant d : std_logic_vector(31 downto 0) :=
    > X"7654321f";
    >     begin
    >
    >       t0 := (others => '0');
    >       t1 := (others => '0');
    >
    >       for i in 0 to 31 loop
    >         if ( (c(i) = '0') and (d(i) = '1') ) then
    >              for j in 0 to 31 loop
    >                t0(j) := (a(j) xor b(j)) and (t0(j) xor t1(j));
    >                t1(j) := (a(j) xor b(j)) or ((t1(j) xor t0(j)) xor
    > b(j));
    >              end loop;
    >         end if;
    >       end loop;
    >
    >       r <= t0;
    >     end;
    >
    > many thanks


    If you don't think it is calculating the result correctly, why don't
    you simulate it where you can view all the details?

    The calculations seem a bit odd. I can't picture what problem this
    might be solving. I also don't know why you make it so complicated.
    The constants c and d are only used in the "if" condition where they
    are bit-wise anded. Why couldn't you replace that with a single
    constant that has already been bit-wise anded?

    The rest of it is a bit too complex to analyze easily and you don't
    provide your test data. It looks to me like it would require a fairly
    special set of inputs on a and b to cause bits to be set in t0. First
    you have to get past the not c and d filter which only passes the 4
    lsbs. If you computed the value of not c and d you would see this.
    Then in a bit-wise fashion, to set t0 it has to be different from t1.
    Since they are both initialized to all zeros, that means t1 has to be
    set. To set t1 either a and b must be different or t1, t0 and b must
    have an odd number of bits set.

    Are you sure your input vectors provide for anything other than zero
    bit values output?

    Rick
    rickman, Jan 18, 2011
    #4
  5. Richard Molgner wrote:

    > Hi again,
    >
    > I updated the routine now, and it looks as follows. Although it
    > compiles fine, the output
    > of the computation is ALWAYS ZERO. It seems with this software-like
    > implementation I wont
    > be able to describe the hardware circuit I want to. Or does anyone see
    > a problem with my
    > VHDL description?
    >
    > procedure main
    > (
    > signal a : in std_logic_vector(31 downto 0);
    > signal b : in std_logic_vector(31 downto 0);
    > signal r : out std_logic_vector(31 downto 0)
    > )
    > is
    > variable res : std_logic_vector(31 downto 0);
    > variable t0, t1 : std_logic_vector(31 downto 0);
    > constant c : std_logic_vector(31 downto 0) := X"fedcba90";
    > constant d : std_logic_vector(31 downto 0) :=
    > X"7654321f";
    > begin
    >
    > t0 := (others => '0');
    > t1 := (others => '0');
    >
    > for i in 0 to 31 loop
    > if ( (c(i) = '0') and (d(i) = '1') ) then
    > for j in 0 to 31 loop
    > t0(j) := (a(j) xor b(j)) and (t0(j) xor t1(j));
    > t1(j) := (a(j) xor b(j)) or ((t1(j) xor t0(j)) xor
    > b(j));
    > end loop;
    > end if;
    > end loop;
    >
    > r <= t0;
    > end;



    With the given values of constants c and d, the only bits for which the 'if'
    holds true are 0 to 3. Is that what you intended?

    As you have rewritten your code, you now modify t0 and then use it in the
    computation of t1. That is not what was intended in the original code, as
    far as I can see.

    It seems you messed up in an attempt to transform the original code.

    Let me try to modify that code so it will compile. No guarantees on
    functionality, I'll probably mess up as well!

    procedure subproc
    (
    a : inout std_logic_vector(31 downto 0);
    b : inout std_logic_vector(31 downto 0);
    c : in std_logic_vector(31 downto 0);
    d : in std_logic_vector(31 downto 0)
    )
    is
    variable x : std_logic_vector(31 downto 0);
    variable y : std_logic_vector(31 downto 0);
    begin
    x := (a xor b) and (c xor d);
    y := (a xor b) or ((d xor c) xor b);

    a := x;
    b := y;
    end;

    procedure main
    (
    constant a : in std_logic_vector(31 downto 0);
    constant b : in std_logic_vector(31 downto 0);
    signal r : out std_logic_vector(31 downto 0)
    )
    is
    variable t0, t1 : std_logic_vector(31 downto 0);
    constant c : std_logic_vector(31 downto 0) := X"fedcba90";
    constant d : std_logic_vector(31 downto 0) := X"7654321f";
    begin
    t0 := (others => '0');
    t1 := (others => '0');

    for i in c'range loop
    if (c(i) = '0') and (d(i) = '1') then
    subproc(t0, t1, a, b);
    end if;
    end loop;

    r <= t0;
    end;


    Remarks:

    1) No need to always use separate bits. Operators like and, or,
    xor also work on vectors. No loop needed.

    2) If you want to use the complete vector, there is no need to
    specify the range. So these are all equivalent:
    a := x;
    a := x(31 downto 0);
    a(31 downto 0) := x;
    a(31 downto 0) := x(31 downto 0);

    3) Parameters of procedures need not always be of class signal.
    Depends on where they are used.

    4) Parenthesis around the condition in an 'if' statement are not
    needed (style issue). VHDL is not C.

    5) There is no operator &&: it is 'and'. VHDL is not C.

    6) Variable res in procedure main was never used.

    7) If you want to loop over all bits in a vector, use the 'range
    attribute. In my opinion it is clearer and it is more robust
    against code changes (like changing the vector length).

    8) The class of parameters c and d of procedure subproc and
    parameters a and b of main all are constant. For input parameters
    that is the default. I have the habit to only actually specify
    the class of subprogram parameters if one of the parameters has
    a non-default class, such as parameter r of main in this case.

    9) Simulate before synthesize. That also means: make a testbench.

    --
    Paul Uiterlinden
    www.aimvalley.nl
    e-mail addres: remove the not.
    Paul Uiterlinden, Jan 18, 2011
    #5
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Nathan Sokalski

    Subprocedure for Oracle's SET DEFINE OFF command

    Nathan Sokalski, Nov 10, 2005, in forum: ASP .Net
    Replies:
    3
    Views:
    8,088
    =?Utf-8?B?U2ltb24=?=
    Nov 11, 2005
  2. afd
    Replies:
    1
    Views:
    8,235
    Colin Paul Gloster
    Mar 23, 2007
  3. Nathan Sokalski

    Subprocedure for Oracle's SET DEFINE OFF command

    Nathan Sokalski, Nov 10, 2005, in forum: ASP .Net Datagrid Control
    Replies:
    3
    Views:
    157
    Simon
    Nov 11, 2005
  4. steve
    Replies:
    2
    Views:
    121
    steve
    Aug 16, 2005
  5. ccc31807
    Replies:
    10
    Views:
    538
    Charlton Wilbur
    Mar 6, 2012
Loading...

Share This Page