Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

VHDL subprocedure call

Status
Not open for further replies.

Richard29

Member level 1
Joined
Oct 26, 2010
Messages
37
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,286
Activity points
1,646
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

Code:
    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;
 

In VHDL signals and variables are 2 very different things. The difference is that variables are updated immediatly, like varaiables in any programming language. Signals, on the other hand, are only updated at the end of the current delta cycle (usually when a process hits a wait). Until that wait occurs, the signal holds the old value, no matter how many times you change it, and it only takes the last value assigned to it.

So because of this, you cannot connect a variable to a signal or vice versa. But you can assign values from a signal to a variable and vice versa, because you are only copying the value.

Looking at your code, I dont understand why any of the inputs or outputs need to be signals at all. The In's could all be constant and outs could all be variable because all you have is boolean logic. Then you can connect the outputs to a temporary vaiable and then assign them to a signal, as is commonly done.

But a bigger question is why have you done it like this anyway. It all smacks of a software approach to me.
 

But a bigger question is why have you done it like this anyway. It all smacks of a software approach to me.

Thanks for your answer TrickyDicky, and yes you are absolutely right that I am using a bit a software approach here and it is probably not the ideal
way to write VHDL. But for my purposes the hardware has not to be optimal. I tried now to incooperate the whole computation in one procedure and
that looks as follows:

Code:
    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;

Algthough it compiles now, when I run simulation the output is always ZERO. So it seems with this approach I wont be able to describe the functionality
I want to
 
Last edited:

Your procedure is quite complicated, and it going to eat up a large number of LEs, not to mention be pretty rubbish when it comes to FMAX, because you are creating huge logic trees. Each bit of R is actually being built from a large combination of pretty much all bits in a and b.

You hardware is a long long long way from being optimal.
 
Your procedure is quite complicated, and it going to eat up a large number of LEs, not to mention be pretty rubbish when it comes to FMAX, because you are creating huge logic trees. Each bit of R is actually being built from a large combination of pretty much all bits in a and b.

You hardware is a long long long way from being optimal.

Well, the thing is I need this combinations anyway to compute the result, so there is no way to have less gates I guess. The only thing that worries me for now is,
that the result "r" is always zero. Do you see any reason why could be the case? If I get this working, then I can think about moving to the next step and try
to optimise it in some way when needed.
 

without seeing the code that calls this main procedure, or the testbench code, I cant say why its always zero.

As for optimisation, what you need to do is pipeline the function in the procedure, and that will mean re-writing your procedure or scrapping it entirely. But you'll speed it up dramatically.
 

notice that these "huge" trees really aren't that bad. subproc is an xor+and/or, which fits into a LUT4 by itself. c,d are used in an outer loop, but are both constant. An unoptimized approach would probably result in 4 levels of logic, and around 8 LUTs total, which is about 1 LAB in altera IIRC. This shouldn't be too bad. (notice that this is unrolled when c=0, d=1, which is actually uncommon in the listed constants.)

in anycase, you could start by moving the code out of the proceedures until sim works correctly, then start moving thing back. This seperates normal code issues from any possible syntax/language issues involving the proceedures.
 

Algthough it compiles now, when I run simulation the output is always ZERO.

I'm not surprised.

t0(j) := (a(j) xor b(j)) and (t0(j) xor t1(j));


t0 and t1 are initialized to zero, and so the xor of their bits wil always return zero, no matter what a and b are. You might try changing the order of the two equations, as I can't remember if procecdures are sequential, been too long for me, but I think they are.
 

I should read code properly next time.

In addition, as the output is connect to t0, t1 does nothing and will be removed when synthesised.
 

Well, if the equations are in the proper order, t1 is an input to t0, so it should stay.
 

true
but as t1(j) is 0 when it's used, it is almost useless.
And t1 is not output from the procedure.
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top