Help for function calling

F

fl

Guest
Hi,
I want to program a CRC project originating from a past discussion:


function crc_shift
-- Mike Treseler
-- parallel data version
(constant X_load : in unsigned;
constant D_vec : in unsigned ;
constant Poly : in unsigned := x"3223") --Poly_16_12_5)
return unsigned is
variable X_out : unsigned(X_load'range);
begin
X_out := X_load;
for I in D_vec'range loop -- call serial version for each bit
X_out := crc_shift(X_out, D_vec(I), Poly);
end loop;
return X_out;
end function crc_shift;

end package body crc_package;

library IEEE;
use IEEE.std_logic_1164.all;
use WORK.crc_package.all;

entity tb is
end tb;

architecture structural of bit8_adder is

signal internal_carry : std_logic;
signal sum1: std_logic_vector(15 downto 0);
begin
sum1 <= crc_shift(x"3322", x"1111", x"3223");
end;


The code has an error when compiling:

** Error: C:\Users\Jeff\crc_ccitt.vhd(100): No feasible entries for subprogram "crc_shift".


I am new to VHDL, especially to function. Could you help me on what is wrong
with my code? Thanks.
 
On Monday, August 4, 2014 11:56:21 AM UTC-4, fl wrote:

I guess that there are two overloading crc_shift function in previous post
causing error. Then I explicitly define two crc_shift(0) function inside the
package. It has a new error:


** Error: C:\Users\Jeff\crc_ccitt.vhd(15):
(vcom-1115) Subtype indication found where type mark is required.


Could anybody help me on what is wrong? Thanks,





library IEEE;
use IEEE.std_logic_1164.all;

use IEEE.numeric_std.all;


package crc_package is
function crc_shift
-- Mike Treseler
-- parallel data version
(constant X_load : in unsigned (15 downto 0);
constant D_vec : in unsigned (15 downto 0);
constant Poly : in unsigned := x"3223") --Poly_16_12_5)
return unsigned (15 downto 0);
end package crc_package;

package body crc_package is
function crc_shift0
-- Mike Treseler
-- serial data version, see overload for parallel data below
-- Purpose : Single bit shift for a CRC register using any polynomial.
-- Inputs : X_load : Current CRC vector.
-- D_bit : Data to shift into CRC vector.
-- Poly : CRC polynomial. Default is Frame Relay.
--
-- Outputs : CRC vector after CRC shift.
(
constant X_load : in unsigned; -- register start value
constant D_bit : in std_ulogic := '0'; -- input bit
constant Poly : in unsigned := x"3223" --Poly_16_12_5 -- poly bits
)
return unsigned is
variable X_out : unsigned(X_load'range); -- CRC register
begin ----------------------------------------------------------------------
-- we assume that X and Poly are in downto format
-- to match the textbook definition of LSFR
-- and to match the CCITT FCS bit assigments
-- for frame relay, note that X(15) becomes the lsb of octet n-2
-- and that X(7 ) becomes the lsb of octet n-1
----------------------------------------------------------------------
-- Procedure: Left shift a '0' into the current X0
-- and the previous X(14) into the current X15 etc.
-- if the original X15 is '1' or the data is '1'
-- but not both, then invert the poly bit locations
----------------------------------------------------------------------
-- Sample Invocation:
-- crc_shift( "0001000100010001", '1'));
-- SLL 0010001000100010 -- shift the variable
-- D (not X15) [ ! ! !] -- invert poly locations?
-- expect("shift1 0011001000000011"); -- expected result
----------------------------------------------------------------------
assert X_load'length = Poly'length
report "crc_shift: Vectors X_load and Poly must be of equal length."
severity error;
X_out := X_load sll 1;
if (X_load(X_load'left) xor D_bit) = '1' then
X_out := X_out xor Poly;
end if;
return unsigned(X_out); -- returns each shift
end function crc_shift0;

-----------------------------------------------


function crc_shift
-- Mike Treseler
-- parallel data version
(constant X_load : in unsigned (15 downto 0);
constant D_vec : in unsigned (15 downto 0);
constant Poly : in unsigned := x"3223") --Poly_16_12_5)
return unsigned is
variable X_out : unsigned(X_load'range);
begin
X_out := X_load;
for I in D_vec'range loop -- call serial version for each bit
X_out := crc_shift0(X_out, D_vec(I), Poly);
end loop;
return X_out;
end function crc_shift;

end package body crc_package;

library IEEE;
use IEEE.std_logic_1164.all;
use WORK.crc_package.all;

entity tb is
end tb;

architecture structural of tb is

signal internal_carry : std_logic;
signal sum1: unsigned (15 downto 0);
begin
sum1 <= crc_shift(x"3322", x"1111", x"3223");

end;
 
On Monday, August 4, 2014 11:56:21 AM UTC-4, fl wrote:
I am new to VHDL, especially to function. Could you help me on what is wrong
with my code?

You declared sum1 as a std_logic_vector, not an unsigned. The crc_shift function returns unsigned.

Change this...
signal sum1: std_logic_vector(15 downto 0);
To this...
signal sum1: unsigned(15 downto 0);

Kevin Jennings
 
On Tuesday, August 5, 2014 4:19:27 AM UTC+12, fl wrote:
On Monday, August 4, 2014 11:56:21 AM UTC-4, fl wrote:

Hi,

I guess that there are two overloading crc_shift function in previous post
causing error. Then I explicitly define two crc_shift(0) function inside the
package. It has a new error:


** Error: C:\Users\Jeff\crc_ccitt.vhd(15):
(vcom-1115) Subtype indication found where type mark is required.

You could consider posting code with line numbers.

I believe this is line 15:

return unsigned (15 downto 0);

And a different error message may help:

ghdl -a crc_shft.vhdl
crc_shft.vhdl:47:25: index constraint not allowed here
ghdl: compilation error

subprogram_specification ::=
procedure designator [ ( formal_parameter_list ) ]
| [ pure | impure ] function designator [ ( formal_parameter_list ) ]
return type_mark

type_mark ::=
type_name
| subtype_name

Notice the lack of subtype indication associated with the return type_mark.

It should be:

return unsigned ; -- (15 downto 0);

It also doesn't match the function's subprogram specification in the package body.

There are other problems with entity tb. You're missing a use statement for
package ieee.numeric_std.all for the type declaration unsigned.

After which your code analyzes, elaborates and runs.

With a little added monitoring:

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

entity tb is
end tb;

architecture structural of tb is

signal internal_carry : std_logic;
signal sum1: unsigned (15 downto 0);

function unsigned_image(inp: unsigned) return string is
variable image_str: string (1 to inp'length);
alias input_str: unsigned (1 to inp'length) is inp;
begin
for i in input_str'range loop
image_str(i) := character'VALUE(std_ulogic'IMAGE(input_str(i)));
end loop;
return image_str;
end;

begin
sum1 <= crc_shift(x"3322", x"1111", x"3223");

MONITOR:
process
begin
wait for 1 ns;
report "sum1 = " & unsigned_image(sum1);
wait;
end process;
end architecture;

gives:

crc_shft.vhdl:114:9:mad:1ns:(report note): sum1 = 1011100111100000

Which is x"B9E0"
 
On Tuesday, 5 August 2014 00:19:27 UTC+8, fl wrote:
package crc_package is
function crc_shift
-- Mike Treseler
-- parallel data version
(constant X_load : in unsigned (15 downto 0);
constant D_vec : in unsigned (15 downto 0);
constant Poly : in unsigned := x"3223") --Poly_16_12_5)
return unsigned (15 downto 0);
end package crc_package;

package body crc_package is
function crc_shift0
....

Just adding to what others have said. You need to declare the function crc_shift0 at the package declarative area as well, since you have that function in the package body and intend to use it.

package crc_package is
function crc_shift(...) return unsigned;
function crc_shift0(...) return unsigned;
end package crc_package;


Make sure the subprogram "signature" is the same for both the declarative region and the body. E.g. if you declared your subprogram to return an 'unsigned(15 downto 0)', then to be consistent, you should use the same return type in your subprogram specification (the one in the package body).

-dan
 
On Wednesday, August 6, 2014 3:26:11 AM UTC+12, Daniel Kho wrote:

Just adding to what others have said. You need to declare the function
crc_shift0 at the package declarative area as well, since you have that function
in the package body and intend to use it.

Err, no, not necessarily. A declaration in a package declaration makes the
function visible through a use statement. (i.e. use work.package.all;) while the
function is directly visible in the package body by through the function's
subprogram body. The effect of not having the function declared in the package
declaration is to make it private (only visible) to the package body. You can find
examples for both locally visible functions and declarations in package
std_logic_1164's body.

IEEE Std 1076-2008, 4.3 Subprogram bodies, para 8:

"The declaration of a subprogram is optional. In the absence of such a
declaration, the subprogram specification of the subprogram body acts as the
declaration. For each subprogram declaration, there shall be a corresponding
body. If both a declaration and a body are given, the subprogram specification
of the body shall lexically conform (see 4.10) to the subprogram specification
of the declaration. Furthermore, both the declaration and the body shall occur
immediately within the same declarative region (see 12.1)."

Which also tells us a function declaration within the package body has to
match the function body.

4.7 Package declarations, para 1:

"A package declaration defines the interface to a package. The scope of a
declaration within a package can be extended to other design units or to other
parts of the design unit containing the package declaration."

12.4 Use clauses, para 1 - 3:

"A use clause achieves direct visibility of declarations that are visible by
selection.

use_clause ::=
use selected_name { , selected_name } ;

Each selected name in a use clause identifies one or more declarations that will
potentially become directly visible. If the suffix of the selected name is a
simple name other than a type mark, or is a character literal or operator
symbol, then the selected name identifies only the declaration(s) of that simple
name, character literal, or operator symbol contained within the package or
library denoted by the prefix of the selected name."

12.4 para 3:

"If the suffix is the reserved word all, then the selected name identifies all
declarations that are contained within the package or library denoted by the
prefix of the selected name."

(Which tells us that .all at the end of a use clause makes all the declarations
in a package visible.)

12.3 Visibility, para 2, excerpted:

"For each identifier and at each place in the text, the visibility rules
determine a set of declarations (with this identifier) that define the possible
meanings of an occurrence of the identifier. A declaration is said to be visible
at a given place in the text when, according to the visibility rules, the
declaration defines a possible meaning of this occurrence. ..."

In this specific case crc_shift0 isn't visible outside crc_package, and the case
presented by fi only shows it called from function crc_shift inside the
crc_package body where it is visible.

It only has to be declared in the crc_package declaration if it is required to be
visible externally.

Make sure the subprogram "signature" is the same for both the declarative region
and the body. E.g. if you declared your subprogram to return an 'unsigned(15
downto 0)', then to be consistent, you should use the same return type in your
subprogram specification (the one in the package body).

And a return type declaration in a function declaration may not contain a subtype
indication, the previously quoted EBNF in another comment is normative.

Both of these and require extensive reading of the standard (and is the more
difficult in the -2008 version of the standard) or can be demonstrated by simple
experimentation.

Those of us who don't trust tools to be right do both.

The VHDL language standard is large enough those of us trying to make
authoritative statements tend to keep it to hand. It's too big to keep in your
head (short term memory is the first to go), which is why over time tool error
messages improve.

(And if I hadn't checked yesterday before a previous comment I might not have
raised the issues, I too saw there was no declaration in the package and checked
why. I had a tool complain about a subtype indication on the function return,
but also noted fi had corrected it when presenting the entire package.)
 
On Wednesday, 6 August 2014 08:24:24 UTC+8, Dio Gratia wrote:
On Wednesday, August 6, 2014 3:26:11 AM UTC+12, Daniel Kho wrote:



Just adding to what others have said. You need to declare the function

crc_shift0 at the package declarative area as well, since you have that function

in the package body and intend to use it.



Err, no, not necessarily. A declaration in a package declaration makes the

function visible through a use statement. (i.e. use work.package.all;) while the

function is directly visible in the package body by through the function's

subprogram body. The effect of not having the function declared in the package

declaration is to make it private (only visible) to the package body. You can find

examples for both locally visible functions and declarations in package

std_logic_1164's body.

Yes, I agree. However, I was not speaking strictly from the LRM - instead I was speaking based on the OP's intention. From what I guess, the OP intends to use the subprogram outside of the package body (i.e. probably use it in a real design, whose entity-architecture is probably in another file).

Defining a subprogram within the package body but not in the package declarative part will not give you any errors (IINM), but that makes the subprogram private to the package body (as what you've mentioned) and you can't use the subprogram outside of the package.

I think the intent of the OP is eventually to be able to use the subprogram outside of the package body.

-dan
 

Welcome to EDABoard.com

Sponsor

Back
Top