VHDL : writing an AND function - vhdl

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;

Related

Synthesizable VHDL recursion, Vivado: simulator has terminated in an unexpected manner

I would like to implement a count min sketch with minimal update and access times.
Basically an input sample is hashed by multiple (d) hash functions and each of them increments a counter in the bucket that it hits. When querying for a sample, the counters of all the buckets corresponding to a sample are compared and the value of the smallest counter is returned as a result.
I am trying to find the minimum value of the counters in log_2(d) time with the following code:
entity main is
Port ( rst : in STD_LOGIC;
a_val : out STD_LOGIC_VECTOR(63 downto 0);
b_val : out STD_LOGIC_VECTOR(63 downto 0);
output : out STD_LOGIC_VECTOR(63 downto 0);
. .
. .
. .
CM_read_ready : out STD_LOGIC;
clk : in STD_LOGIC);
end main;
architecture Behavioral of main is
impure function min( LB, UB: in integer; sample: in STD_LOGIC_VECTOR(long_length downto 0)) return STD_LOGIC_VECTOR is
variable left : STD_LOGIC_VECTOR(long_length downto 0) := (others=>'0');
variable right : STD_LOGIC_VECTOR(long_length downto 0) := (others=>'0');
begin
if (LB < UB)
then
left := min(LB, ((LB + UB) / 2) - 1, sample);
right := min(((LB + UB) / 2) - 1, UB, sample);
if (to_integer(unsigned(left)) < to_integer(unsigned(right)))
then
return left;
else
return right;
end if;
elsif (LB = UB)
then
-- return the counter's value so that it can be compared further up in the stack.
return CM(LB, (to_integer(unsigned(hasha(LB)))*to_integer(unsigned(sample))
+ to_integer(unsigned(hashb(LB)))) mod width);
end if;
end min;
begin
CM_hashes_read_log_time: process (clk, rst)
begin
if (to_integer(unsigned(instruction)) = 2)
then
output <= min(0, depth - 1, sample);
end if;
end if;
end process;
end Behavioral;
When I run the above code, I get the following errors:
The simulator has terminated in an unexpected manner. Please review
the simulation log (xsim.log) for details.
[USF-XSim-62] 'compile' step failed with error(s). Please check the
Tcl console output or '/home/...sim/sim_1/behav/xsim/xvhdl.log' file
for more information.
[USF-XSim-62] 'elaborate' step failed with error(s). Please check the
Tcl console output or
'/home/...sim/sim_1/synth/func/xsim/elaborate.log' file for more
information.
I was not able to find any file called xsim.log and xvhdl.log was empty, but elaborate.log had some content:
Vivado Simulator 2018.2
Copyright 1986-1999, 2001-2018 Xilinx, Inc. All Rights Reserved.
Running: /opt/Xilinx/Vivado/2018.2/bin/unwrapped/lnx64.o/xelab -wto c199c4c74e8c44ef826c0ba56222b7cf --incr --debug typical --relax --mt 8 -L xil_defaultlib -L secureip --snapshot main_tb_behav xil_defaultlib.main_tb -log elaborate.log
Using 8 slave threads.
Starting static elaboration
Completed static elaboration
INFO: [XSIM 43-4323] No Change in HDL. Linking previously generated obj files to create kernel
Removing the following line solves the above errors:
output <= min(0, depth - 1, sample);
My questions:
Why am I not able to simulate this code?
Will this code be synthsizable once it is working?
Is there a better (and/or faster) way to obtain the minimum of all relevant hash buckets?
not that I was able to find any real world use for recursion, but just to surprise #EML (as requested in the comments above): you actually can define recursive hardware structures in VHDL.
In Quartus at least, this only works if you give the compiler a clear indication of the maximum recursion depth, otherwise it will try to unroll the recursion to any possible input, eventually dying from a stack overflow:
entity recursive is
generic
(
MAX_RECURSION_DEPTH : natural
);
port
(
clk : in std_ulogic;
n : in natural;
o : out natural
);
end recursive;
architecture Behavioral of recursive is
function fib(max_depth : natural; n : natural) return natural is
variable res : natural;
begin
if max_depth <= 1 then
res := 0;
return res;
end if;
if n = 0 then
res := 0;
elsif n = 1 or n = 2 then
res := 1;
else
res := fib(max_depth - 1, n - 1) + fib(max_depth - 1, n - 2);
end if;
return res;
end function fib;
begin
p_calc : process
begin
wait until rising_edge(clk);
o <= fib(MAX_RECURSION_DEPTH, n);
end process;
end Behavioral;
With a MAX_RECURSION_DEPTH of 6, this generates one single combinational circuit with more than 500 LEs (so the pracical use is probably very limited), but at least it works.
Is recursion possible in VHDL?
I would say, yes, but not recursion as we know it. That's the short answer. I have code (if anyone is interested that implements Quicksort) and it will synthesize quite happily. If anyone knows about Quicksort, it normally won't be anywhere near the context of synthesis. But I managed to do it.
The trick (which is vexatious and hard to follow) is to emulate recursion with a strange state machine that backtracks to the beginning state, after pushing a "state" onto a (hardware) stack. You can synthesize this sort of data structure quite easily if you want.
I recall some fascinating stuff written by Thatcher, Goguen and Wright about semantic transformations from one kind of coding domain to others (different models of computation, in short).
It does strike me that this is possibly a genesis point for actual recursive expressions in a more general sense. But do be warned, it's very difficult.

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 - Do Functions used only in the architecture header take up FPGA logic?

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.

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