VHDL - Do Functions used only in the architecture header take up FPGA logic? - compilation

If I have some code like so:
...
architecture behaviour of ExampleEntity is
-- type definitions
type Matrix is array(0 to 1,0 to 1) of signed(NumOfBitsForSignals_1 downto 0);
-- function definitions
function TransposeMatrix(MatrixArg : Matrix) return Matrix is
-- variable decleration
variable Result : Matrix;
begin
-- behaviour
for columnNo in Result'range loop
for rowNo in Result'range loop
Result(columnNo, rowNo) := MatrixArg(rowNo, columnNo);
end loop;
end loop;
return Result;
end function;
-- constant definitions
constant A00 : std_logic_vector(NumOfBitsForSignals_1 downto 0) := "A00Value";
constant A01 : std_logic_vector(NumOfBitsForSignals_1 downto 0) := "A01Value";
constant A10 : std_logic_vector(NumOfBitsForSignals_1 downto 0) := "A10Value";
constant A11 : std_logic_vector(NumOfBitsForSignals_1 downto 0) := "A11Value";
constant A : Matrix := ((signed(A00), signed(A01)),
constant A_Transpose : Matrix := TransposeMatrix(A);
...
And the TransposeMatrix function is only used once in this place is this function still synthesised or will the compiler assign the appropriate value to A_Transpose and remove this function from the synthesis? If this isn't the case and it synthesised the transpose function would it be better to remove this function and transpose the matrix manually and enter it?

As a general rule, a synthesis tool will try it's very best to reduce the complexity of the generated net list. This includes working out the results of functions that have constant inputs, even if these inputs are themselves generated by other functions, depend on generic parameters, etc. The tools are so good at this process, that a simple mistake in your code can lead to whole parts of your design being optimised away.
That being the case, it doesn't actually matter whether the function is only called in a declarative region; no matter where a function is called, any simplifications or optimisations possible will be carried out by the synthesis tool.
Some tools do have limitations, for example if your function reads from files, or in some scenarios if it contains a loop with bounds that are determined by parameters. However, this will tend to result in either an error or a warning, as opposed to extra logic in the net list.

Related

How to determine direction of a vector in VHDL (downto vs to)?

I need to write a function that will shift data into an input vector. The input could be of type signed or unsigned. In order to make the function robust, I need to know the direction of the input vector i.e range declared using downto vs to. This information will be used to determine what index has the least significant bit.
How do I find out how the range has been declared and choose the correct least significant and most significant bit based on that information?
Array types have the default attributes 'ascending and 'descending which are both functions that return true/false depending on whether the range is actually to (ascending) or downto (descending). Hence, you will likely need to have the following coding style if you explicitly need to investigate the direction:
if p'ascending then
-- do code for to direction
else
-- do code for downto direction
end if;
Alternatively, you can use an alias to "normalise" the direction inside the function, which means an if/else is not needed depending on direction, as you know the direction inside the function:
function do_something( p : bit_vector ) return bit_vector is
alias p_a : bit_vector(p'length-1 downto 0) is p; -- normalise p
variable r : p_a'subtype;
begin
-- use p_a as a downto vector
return r;
end function;

VHDL pass range to procedure

I'm writing my own package to deal with generic matrix-like objects due to unavailability of VHDL-2008 (I'm only concerned with compilation and simulation for the time being).
My aim is getting a matrix M_out from a matrix M_in such that:
M_out(i downto 0, j downto 0) <= M_in(k+i downto k, l+j downto l);
using a subroutine of sort. For, let's say, semantic convenience and analogy with software programming languages my subroutine prototype should ideally look something like this:
type matrix is array(natural range <>, natural range <>) of std_logic;
...
procedure slice_matrix(signal m_out: out matrix;
constant rows: natural range<>;
constant cols: natural range<>;
signal m_in: in matrix);
The compiler does however regard this as an error:
** Error: custom_types.vhd(9): near "<>": syntax error
** Error: custom_types.vhd(9): near "<>": syntax error
Is it possible to pass a range as an argument in some way or shall I surrender and pass 4 separate indexes to calculate it locally?
An unconstrained index range natural range <> is not a VHDL object of class signal, variable, constant, or file. Thus it can not be passed into a subprogram. I wouldn't implement a slice operations as a procedure, because it's a function like behavior.
An implementation for working with matrices and slices thereof is provided by the PoC-Library. The implementation is provided in the vectors package.
function slm_slice(slm : T_SLM; RowIndex : natural; ColIndex : natural; Height : natural; Width : natural) return T_SLM is
variable Result : T_SLM(Height - 1 downto 0, Width - 1 downto 0) := (others => (others => '0'));
begin
for i in 0 to Height - 1 loop
for j in 0 to Width - 1 loop
Result(i, j) := slm(RowIndex + i, ColIndex + j);
end loop;
end loop;
return Result;
end function;
More specialized functions to slice off a row or column can be found in that file too. It also provides procedures to assign parts of a matrix.
This package works in simulation and synthesis.
Unfortunately, slicing multi dimensional arrays will not be part of VHDL-2017. I'll make sure it's discuss for VHDL-202x again.
Passing ranges into a subprogram will be allowed in VHDL-2017. The language change LCS 2016-099 adds this capability.

VHDL : writing an AND function

So im trying to write a function that performs an AND gate, the intput is a vector of the gate inputs, and the number of inputs. But for some reason the compiler gives me an error that it doesn't recognize the "and" logic operator im using inside for some reason. can anyone spot the issue?
p.s this is all part of a bigger project that is a 16counter (0-15) thats made of 4 chained JK flip flops and 2 AND gates (using my "myand" function).
function myand (x: std_logic_vector; n : integer range 7 downto 0) return std_logic is
variable result: integer :=0;
begin
for i in 0 to n-1 loop
result:=result and x(i);
end loop;
return result;
end function;
The compiler error is:
Error (10327): VHDL error at counter16.vhd(16): can't determine definition of operator ""and"" -- found 0 possible definitions
I even tried using '+' instead of 'and' but its the same error.
The builtin libraries of VHDL don't define a operator and that takes a integer and std_logic.
How to fix this:
result should be a std_logic instead of an integer.
result should be initialized to '1' instead of 0.
The function interface can be simplified by removal of the ´n´ argument if the 'range attribute is used on x to get the index values. If a subrange of a std_logic_vector is used as argument, then the myand function can be called with that subrange only. Including sharth suggestions, the function is:
function myand (x : std_logic_vector) return std_logic is
variable result : std_logic := '1';
begin
for i in x'range loop
result := result and x(i);
end loop;
return result;
end function;

Number of bits to represent an integer in VHDL

I have to convert an integer to find how many bits are required to represent that integer.
Let say, integer value is 22. I know 5 bits are required to represent this integer.
Is there any attribute in VHDL to do this?
Important: The result should also be an integer, which should represent number of bits.
There is no VHDL attribute or function, but you can create a function like:
-- Returns number of bits required to represent val in binary vector
function bits_req(val : natural) return natural is
variable res_v : natural; -- Result
variable remain_v : natural; -- Remainder used in iteration
begin
res_v := 0;
remain_v := val;
while remain_v > 0 loop -- Iteration for each bit required
res_v := res_v + 1;
remain_v := remain_v / 2;
end loop;
return res_v;
end function;
However, sometimes a ceil_log2 function is also useful, since that gives the number of required address bits based on entries in a memory map, and ceil_log2(val) = bits_req(val - 1).
Use the math_real library. It's not for synthesis, but works great between the architecture and begin statements.
use ieee.math_real.all;
constant nbits : natural := integer(ceil(log2(real(n))));
I use math_real a lot for in-line generating sin/cos tables... again it's between architecture and begin... again, don't try to use math_real in synthesis.
I've used this in Quartus, ISE, Vivado, Modelsim successfully; it might not be supported by everything out there.

How can I check if a VHDL Integer is even or odd?

What is the easiest or simplest way to check if an integer signal is even or odd in VHDL?
if (A mod 2) = 0 then
-- it's even
else
-- it's odd
end if;
As a side note if the signal is a vector, then you can do the following:
if (A(0)) then
-- it's odd
else
-- it's even
function is_even(val : integer) return boolean is
constant vec: signed(31 downto 0) := to_signed(val, 32);
begin
return vec(0) = '0';
end;
or
function is_even(val : integer) return boolean is
begin
return val mod 2 = 0;
end;
depending on whether your synthesiser is bright enough to figure out mod 2
Another way if you are not storing as an integer * is to register the LSB from the standard logic vector holding the value and check if it is 0 or 1.
EDIT: Re-storing integers
removed * (which can be a problem on many FPGA's)
My mistake here, I was thinking along two different paths and mixed the two up. I have had trouble before passing character and string types between components when coding on FPGA's. While I cannot list the error messages off hand, I took a mental note to use std logic vectors instead of the pre-compile types. I found that they always seemed to work in simulation but never on the board.

Resources