Generic Multiplexer warning - vhdl

I created a generic multiplexer( on number of inputs and bits per input) in VHDL. I tested it and it works correctly but I get a width mismatch warning:
Width mismatch. < output > has a width of 8 bits but assigned expression is 64-bit wide.
This is the code of my generic MUX. Can anyone explain me why I get this warning? WHat's wrong with my code? My professor wants me to implement this without the use of process. Thanks
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use work.package_log.all;
use IEEE.NUMERIC_STD.ALL;
entity mux_generic is
generic(N : natural :=8;
M : natural := 8);
-- N: number of inputs
-- M: bit per input/output
Port ( input : in STD_LOGIC_VECTOR (N*M-1 downto 0);
sel: in STD_LOGIC_VECTOR (log2ceil(N)-1 downto 0);
output : out STD_LOGIC_VECTOR (M-1 downto 0));
end mux_generic;
architecture DataFlow of mux_generic is
begin
output <= input(M*(to_integer(unsigned(sel))+1) - 1 downto M*(to_integer(unsigned(sel))));
end DataFlow;
The function log2ceil is defined in this way:
library IEEE;
use IEEE.STD_LOGIC_1164.all;
package package_log is
function log2ceil( n : natural) return natural;
end package_log;
package body package_log is
function log2ceil (N : natural) return natural is
variable i, j : natural;
begin
i := 0;
j := 1;
while (j < N) loop
i := i+1;
j := 2*j;
end loop;
return i;
end function log2ceil;
end package_log;

Please update to the lastest ISE version 14.7, if you haven't done so far. Then enable the new parser for your Spartan-3E FPGA:
Right click on Synthesize -> Process Properties.
Change property display level to "Advanced".
For property "Other XST Command Line Options" enter -use_new_parser yes.
Now the warning goes away. A new warning appears, just noting, that the new parser is not the default one. But, I didn't experienced a problem with this yet.
By the way, your multiplexer description is not yet efficient. Take at look at my other post, for different implementations and their effects on resource usage and timing analysis.

Related

Vivado VHDL width mismatch - how can I fix it?

Please consider this very simple minimal reproducible code:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity test is
generic ( LENGTH : integer range 1 to 16 := 5 );
Port ( x : in STD_LOGIC;
y : out STD_LOGIC_VECTOR(15 downto 0)
);
end test;
architecture Behavioral of test is
signal a : std_logic_vector (15 downto 0);
signal b : std_logic_vector (LENGTH - 1 downto 0);
signal i : integer range 0 to LENGTH-1 := 1;
begin
y <= a;
process
begin
if i = LENGTH then
i <= 1;
else
a <= a(15 downto i + 1) & b(i downto 0);
end if;
i <= i + 1;
end process;
end Behavioral;
My need is to join some elements of b into a, depending on i. By running the RTL on Vivado, it says:
[Synth 8-690] width mismatch in assignment; target has 16 bits, source has 20 bits
I don't really get why. Anyhow, the overall range will be 15 - (i + 1) + (i - 0) = 15 ... 0 and fits in the 16 bits of output -- what's the deal for 20 bits?
I should say the problem vanishes (obviously) if I use plain constants instead of i, but I still don't get what's going on.
For runtime variable I (as per the question)...
instead of a big CASE, you can use the value of I to generate masks, and evaluate (A and MASKA) or (B and MASKB). Which is equivalent to the multiplexer the synthesis tool would generate if it wasn't broken.
For generic I (it's not fair to move the goalposts in the comments!)
this approach generates unnecessary hardware, which will be optimised out by any competent synthesis tool.
(There are of course other problems with this code; I assume you deleted the clock, taking the MCVE notion a bit too far. You should leave it valid synthesisable code)

Adding two vectors of 5 bit numbers in vhdl

I am new to vhdl, I am trying to add 2 vectors of 5 bit unsigned numbers.In the following code the signal firstsum gives proper output in waveform but the vector sum does not show any output, I am using quartus ii. What is the error in this code?
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use ieee.numeric_std.all;
package UVEC is
subtype UINT5 is std_logic_vector (4 downto 0);
type UVEC5 is array (2 downto 0) of UINT5;
subtype UINT6 is std_logic_vector (5 downto 0);
type UVEC6 is array (2 downto 0) of UINT6;
end UVEC;
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use ieee.numeric_std.all;
use work.UVEC.all;
entity FP_Vecsum1 is
port(
a,b : in UVEC5;
sum : out UVEC6;
firstsum : out UINT6
);
end FP_Vecsum1;
architecture FP_Vecsum1_MX of FP_Vecsum1 is
begin
firstsum <= std_logic_vector(('0'&unsigned(a(0)))+('0'&unsigned(b(0))));
sum(0) <= std_logic_vector(('0'&unsigned(a(0)))+('0'&unsigned(b(0))));
sum(1) <= std_logic_vector(('0'&unsigned(a(1)))+('0'&unsigned(b(1))));
sum(2) <= std_logic_vector(('0'&unsigned(a(2)))+('0'&unsigned(b(2))));
end FP_Vecsum1_MX;
welcome to the VHDL world.
I also haven't found anything wrong with your code, but you can try the following, maybe this will help:
first, try to cast the signals to unsigned in the beginning of your architecture, before doing the math:
a_us(0) <= unsigned(a(0));
a_us(1) <= unsigned(a(1));
a_us(2) <= unsigned(a(2));
this is quite convenient: if your ports to the outside world are neutral vectors, the math inside your component is either signed or unsigned. do the conversion once, and you're free.
second, instead of manually doing the sign extension, now that you have determined your vectors as unsigned, you can use resize function to automatically set the summed vectors to the result length:
sum(0) <= std_logic_vector(resize(a_us(0),sum(0)'length) + resize(b_us(0),sum(0)'length));
you can also do a little trick by adding a zero with a relevant vector width:
sum(0) <= std_logic_vector( to_unsigned(0,sum(0)'length) + a_us(0) + b_us(0) );
it might look a little longer, but in my opinion it's a more robust code.
hope this helps,
ilan.

Add and assign to a signal in VHDL

I am developing a 10 point moving average filter for an assignment. I am taking small steps so that I can be sure each stage of my code is working. My first step is to take an input which is a standard logic vector (5 bits) and convert it to a signal of type integer for processing before converting back to a standard logic vector for output. My first block of code is:
library IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.NUMERIC_STD.ALL;
entity AveFilter is
port( CLK : in STD_LOGIC;
RST : in STD_LOGIC;
ADC_In : in STD_LOGIC_VECTOR ( 4 downto 0);
AveOut : out STD_LOGIC_VECTOR ( 4 downto 0)
);
end AveFilter;
architecture Behavioral of AveFilter is
signal adc_sum : integer := 0;
type Circ_Buf is array (0 to 9) of STD_LOGIC_VECTOR (4 downto 0);
signal ave_buf : Circ_Buf;
begin
process (CLK, RST, ADC_In)
variable idx : integer := 5;
begin
ave_buf(0) <= ADC_In;
adc_sum <= to_integer(unsigned(ave_buf(0)));
AveOut <= std_LOGIC_VECTOR(to_unsigned(adc_sum, AveOut'length));
end process;
end architecture;
The above code simply takes the input value and assigns to the output; I have tested this with modelsim and it works as expected. I can also assign various hard coded values to adc_sum and they also apear on the out put as expected.
The problem I have is when I modify the code so that the current adc input is added to the previous value of adc_sum and then stored in adc_sum ie by doing this:
adc_sum <= adc_sum + to_integer(unsigned(ave_buf(0)));
When I view AveOut in model sim the values are always XXXX. I have looked at some VHDL examples and it looks like and I beleive that I should be able to perorm the above operation. Could someone please give me a clue as to what I'm missing here?
Thanks
Andrew
ave_buf is probably undefined at the beginning. Try initializing it. If this works, you should also implement reset on it. Also, you should take action on rising edge of the clock. And ADC_In is unnecessary in the sensitivity list.

Calculate the module of a vector, in VHDL

How can I calculate the module of a vector?
As a vector is not a pre-defined type in VHDL it makes sense to me that there is no function implementing the modue of a vector. If there is such I have not found it.
This is basically a problem of obtaining the square root of a number, as the module can be defined as:
sqrt(a^2+b^2+...+n^2)
Implementing the sum of all the members of the vector squared is not a challenge so I think the most necessary part is having a function to calculate the square root of a number.
As far as I'm concerned there isn't any official package implementing this function. How to implement a function to calculate the module of a vector?
Or if you prefer it, how to implement a square root?
This is one possible solution. I will provide you 3 codes.
-The first one provides the type definition used for the vector. Its not important but it is needed to make it work.
-The second one is the package in which the function is defined. It is commented so that you can easily adapt it to any kind of vector. It can probably be upgraded to make it adapt by itself using some parameters by this works fine.
-The third one is a testbench to try it out.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
package tipos is
constant bandas : positive := 4;
type vector32 is array (0 to bandas-1) of signed (31 downto 0);
end package tipos;
Be aware of calling properly the library with the vector definition. In my case it was compiled to work for the ModelSim simulation
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
library work; use work.tipos.all;
package propios is
--function declaration.
function module (a : vector32; bands: natural) return unsigned;
end propios; --end of package.
package body propios is --start of package body
--definition of function
--based on: https://en.m.wikipedia.org/wiki/Methods_of_computing_square_roots#Binary_numeral_system_.28base_2.29
function module (a : vector32; bands: natural) return unsigned is --To adapt it to a diferent number of bits in the input vector:
--substitute the 71 for the needed number. Number of bits in each element of the vector *2 + power of two that can represent the maximum
--number of bands, or fields. In this case, 32bit numbers, maximum number of bands, 256, so 2^8. 32*2+8=72.
variable sum : unsigned(71 downto 0):= (others => '0');
variable b : unsigned(71 downto 0):=(0=>'0', 70 => '1', others => '0');
variable a_unsig: unsigned(31 downto 0):=(others =>'0');--for this vector use the same length as the input vector, 32bit in my case.
variable result: unsigned (71 downto 0):= (others => '0');
begin
for i in 0 to bands-1 loop--Sum of all the elements squared
a_unsig:=unsigned(a(i));
sum:=sum + (a_unsig * a_unsig);
end loop;
--Square root of sum
while b>sum loop--Do any needed changes here. You only have to change the 71's
b:='0'&'0'& b(71 downto 2);
end loop;
while (b/=0) loop
if (sum>=result+b) then
sum:=sum - (result + b);
result:=('0'& result(71 downto 1))+b;
else
result:='0'& result(71 downto 1);
end if;
b:='0' & '0' & b(71 downto 2);
end loop;
return result(35 downto 0);--sqrt(2^72)=2^36. Use half of the bits you put in place of 71
end module;
end propios; --end of the package body
And here is the testbench. Again take care of calling the packages properly
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
use work.propios.all;
use work.tipos.all;
ENTITY test IS
END test;
Architecture simple of test is
signal a:vector32;
signal c: unsigned(35 downto 0);
signal b: natural:= 4;
begin
a(0)<="00000000110010011010011100000000";
a(1)<="00000000110010011010011100000000";
a(2)<="00000000110010011010011100000000";
a(3)<="00000000110010011010011100000000";
process
begin
wait for 200ps;
c<= module (a , b);
wait;
end process;
end simple;

What's the right way to cast a sfixed to std_logic_vector in vhdl?

I am trying to cast a sfixed (from ieee.fixed_pkg) to std_logic_vector and I wonder what the correct syntax is and why the following is (appearently wrong). I tried compiling the following 3 architectures:
library ieee;
use ieee.std_logic_1164.all;
use ieee.fixed_pkg.all;
entity test is
port (input: in sfixed(0 downto -7) := x"00";
output: out std_logic_vector(7 downto 0) := x"00");
end;
Architecture a:
architecture a of test is begin
output <= std_logic_vector(input);
end;
Architecture b:
architecture b of test is begin
proc: process (input) begin
output <= std_logic_vector(input);
end process;
end;
Architecture c:
architecture c of test is begin
proc: process (input) begin
if ('1' and '1') then
output <= std_logic_vector(input);
end if;
end process;
end;
The compiler I've used was "ModelSim ALTERA vcom 10.3d Compiler 2014.10 Oct 7 2014".
Architectures a and b don't compile with the error message:
Error: [...] Index value -7 (of type std.STANDARD.NATURAL) is out of range 0 to 2147483647.
But architecture c compiles, while still giving me the warning message:
Warning: [...] Index value -7 (of type std.STANDARD.NATURAL) is out of range 0 to 2147483647.
So my question is: what is the correct way to cast this, and why is there any difference between the three architectures posted above?
The range issues resulting for type casting an sfixed that has negative indices to std_logic_vector that #BrianDrmmond discusses was an issue identified during the development of the standard. It is a real issue for simulators other than GHDL as well.
Hence, the package provides type conversion functions to handle this. To convert from either sfixed or ufixed to std_logic_vector use either to_slv and to_std_logic_vector:
output <= to_slv(input);
To convert from std_logic_vector to sfixed / ufixed use one of the flavors of to_sfixed/to_ufixed. There is one that takes the indices as a parameter and another that takes the object.
signal a_sfixed : sfixed(0 downto -7) := x"00";
signal a_slv : std_logic_vector(7 downto 0) := x"00";
a_sfixed <= to_sfixed(a_slv, 0, -7);
. . .
a_sfixed <= to_sfixed(a_slv, a_sfixed);
Yes, you can use a type conversion (aka casting) for an assignment instead of the above, however, if you wanted to then use the converted value in an expression, the range of the result would be incorrect since it is determined by the range of the inputs.
signal a_sfixed : sfixed(0 downto -7) := x"00";
signal a_slv : std_logic_vector(7 downto 0) := x"00";
signal y_sfixed : sfixed(1 downto -7) := x"00";
y_sfixed <= a_sfixed + to_sfixed(a_slv, 0, -7);
Funnily enough, this might actually be a grey area in the specification of the VHDL language itself. The same problematic conversion has been discussed as a possible "bug" against the open-source simulator, ghdl.
The essence of the problem is that input is declared as sfixed(0 downto -7) while the definition of std_logic_vector requires its index to be natural, i.e. a positive integer or 0.
Thus a type conversion to an unconstrained std_logic_vector
output <= std_logic_vector(input);
inherits the bounds of the source vector, (0 and -7) and fails because one bound is out of range.
There is a simple workaround, however : type conversion to a constrained std_logic_vector ... such as std_logic_vector (input'length-1 downto 0) ... which by using the 'length attribute is guaranteed to be the right size. The semantics of this conversion keep the indexes valid, so the conversion succeeds, transferring leftmost bit to leftmost bit, and so on.
In a bit more detail, the code looks like:
-- declarations
subtype result_type is std_logic_vector (input'length-1 downto 0);
signal output : result_type;
-- assignment
output <= result_type (arg);
I cannot guarantee Altera will accept the same workaround, but I'm reasonably confident that it will, it's more clearly valid VHDL. I also haven't tried declaring output as a port as you need.
As far as we can tell, ghdl (which is usually rigorous in its interpretation of VHDL) is correct in rejecting this construct according to the letter of the VHDL language reference manual (LRM) and the "bug" report has accordingly been closed.
However, further clarification has been sought from the VHDL standards committee - and possibly a future relaxation of the rule - IF - it can be shown to be completely proof against the sort of array bounds errors and buffer overruns that plague some other languages.
I found this post facing the same error in GHDL 0.35 (mcode, windows) using David Bishop's fixed_pkg_c (FPHDL, on github).
Note, while the answer here appears correct; I had to add to the following in fixed_pkg_c in order to get GHDL to compile and simulate:
function to_sulv (
arg : UNRESOLVED_sfixed) -- fixed point vector
return STD_ULOGIC_VECTOR is
variable result : STD_ULOGIC_VECTOR (arg'length-1 downto 0);
-- This was added
subtype result_type is STD_ULOGIC_VECTOR (arg'length-1 downto 0);
begin
if arg'length < 1 then
return NSLV;
end if;
-- originally: result := STD_ULOGIC_VECTOR (arg)
result := result_type (arg);
return result;
end function to_sulv;
The same change was needed to the to_sulv function for ufixed types.
I'm not sure why the previous 'type conversion' using STD_ULOGIC_VECTOR did not work, and I haven't spent more thought on this.
If others find this, please update on whether the original fixed_pkg_c file works in its original implementation.
The fixed package conversion function is not the solution to the OP's reported error, see posting of the function to convert to std_ulogic_vector below. Note that 'result' is a std_ulogic_vector and is obtained by performing a type cast of the operand 'arg', exactly the same as the OP did (except OP used std_logic_vector). The fixed point package will produce the same error as reported by the OP.
-- Conversion functions. These are needed for synthesis where typically
-- the only input and output type is a std_logic_vector.
function to_sulv (
arg : UNRESOLVED_ufixed) -- fixed point vector
return STD_ULOGIC_VECTOR is
variable result : STD_ULOGIC_VECTOR (arg'length-1 downto 0);
begin
if arg'length < 1 then
return NSLV;
end if;
result := STD_ULOGIC_VECTOR (arg);
return result;
end function to_sulv;
KJ

Resources