In the following type and constant declaration, the last value in the array will not actually be 2**35-1, since integers greater than 2**31-1 are not standard VHDL (2002)
library ieee;
use ieee.numeric_std.all;
-- Boilerplate elided...
constant X_SIZE : natural := 40; -- Really, anything greater than 32
type x_array is array(natural range <>) of signed;
constant XS : x_array := (
to_signed(0, X_SIZE),
to_signed(1, X_SIZE),
to_signed(2**35 - 1, X_SIZE) -- Not possible!
);
I can't do to_signed(2, X_SIZE)**35 - 1 because exponentiation is not defined on signed. I'm loathe to type out the full array because it seems clunky and X_SIZE might change in the future. So how do I create the value I want here? Is there a better way than literally typing out 40 0s and 1s?
Depending on the value, there are a few ways to do it.
Using a hexadecimal literal is good for arbitrary numbers and will save a bit of space: x"1FFFFFFFF"
Aggregate assignment gives a way to specify a pattern (eg. for any size, one zero followed by all ones): (X_SIZE-1 downto 35 => '0', others => '1') — be warned though, if you try to combine this with other operators or functions, the compiler will not be able to infer the required size of the vector. You'll need to do something like: (X_SIZE-1 downto 35 => '1', 35 downto 0 => '0'). At this point you might not be saving much space, but depending on what you're doing, it might make your intent much clearer than a literal.
You can also construct a unit in the desired type, and shift it around: shift_left(to_unsigned(1, X_SIZE), 35) - 1.
Related
I am writing a code in vhdl quite full of algebraic operations and I declared some signed variables (I know that there are better types, but I needed to reduce the bits used). I was wondering if it is better to declare them as
variable foo1 := signed (7 downto 0);
or
variable foo2 := signed (0 to 7);
I know it is related to endianess, but I am fairly confused. For example, if I declare
variable foo3 := signed (0 to 7) := "01100100";
Will it be interpreted as 100 or 38 in decimal? And if I have a condition on foo3 as
if (foo3(1) = '1') then
-- whatever you want
endif;
Will foo3(1) = '1' be true or false?
For consistency across VHDL's math packages, it is better to use downto.
variable foo1 : signed (7 downto 0);
This has nothing to do with numeric_std package. As with the numeric_std package, the leftmost element is always the most significant element, independent of whether you use downto or to. Also interesting with numeric_std, the value is in no way dependent on the indices - so (15 downto 8) works the same as (7 downto 0).
On the other hand, with VHDL-2008's fixed point and floating point packages, the only direction supported is downto. The actual range has meaning. With fixed point, the indices have weight. Negative indices are the fractional part.
variable foo4 : sfixed(7 downto -2) ; -- 8 bits of integer, 2 bits of fraction
variable foo5 : sfixed(7 downto 1) ; -- even numbers only.
For more on fixed and floating point, see:
https://synthworks.com/papers/vhdl_fixedfloat_lewis_bishop_date_2007.pdf
For more on unsigned / signed, see:
https://synthworks.com/papers/vhdl_math_tricks_mapld_2003.pdf
In IEEE Standard VHDL Synthesis Packages:
The type UNSIGNED represents an unsigned binary integer with the most
significant bit on the left, while the type SIGNED represents a
two’s-complement binary integer with the most significant bit on the
left. In particular, a one-element SIGNED vector represents the
integer values –1 and 0.
So the number will be interpreted as 100, regardless the range direction. However, accessing or assigning a single element will match with the to range, i.e. foo3(1) = '1'.
I would like to know what is corresponding VHDL code for $clog2(DATA_WIDTH) , for example in this line:
parameter DATA_OUT_WIDTH = $clog2(DATA_WIDTH)
and also for this sign " -: " in this example
if ( Pattern == In[i_count-:PATTERN_WIDTH] )
I will appreciate if anyone can help me.
You can do something like this
constant DATA_OUT_WIDTH : positive := positive(ceil(log2(real(DATA_WIDTH))));
or define a clog2 function encapsulating that expression. ceil and log2 can be found in math_real
use ieee.math_real.all;
In VHDL you can just specify the full range, for example
foo(i_count to i_count + 7)
foo(i_count downto i_count - 7)
Don't use In as an identifier though, it's a reserved word in VHDL.
In addition to Lars example you can easily write a function for finding the ceiling log 2 to determine the number of element address 'bits' necessary for some bus width. Some vendors or verification support libraries provide one already.
The reason there isn't a predefined function in an IEEE library already is expressed in Lars answer, you tend not to use it much, you can assign the value to a constant and an expression can be cobbled together from existing functions.
An example clog2 function
A borrowed and converted log2 routine from IEEE package float_generic:
function clog2 (A : NATURAL) return INTEGER is
variable Y : REAL;
variable N : INTEGER := 0;
begin
if A = 1 or A = 0 then -- trivial rejection and acceptance
return A;
end if;
Y := real(A);
while Y >= 2.0 loop
Y := Y / 2.0;
N := N + 1;
end loop;
if Y > 0.0 then
N := N + 1; -- round up to the nearest log2
end if;
return N;
end function clog2;
The argument A type NATURAL prevents passing negative integer values. Rounding is strict, any remainder below 2.0 causes rounding up.
Note that because this uses REAL and uses division it's only suitable for use during analysis and elaboration. It's a pure function.
You could note Lars example:
constant DATA_OUT_WIDTH : positive := positive(ceil(log2(real(DATA_WIDTH))));
has the same constraints on use for analysis (locally static) and elaboration (globally static). REAL types are generally not supported for synthesis and floating point operations can consume lots of real estate.
The if condition
if ( Pattern == In[i_count-:PATTERN_WIDTH] )
Is a base index (an lsb or msb depending on ascending or descending declared bit order) and a width.
See IEEE Std 1800-2012 (SystemVerilog), 11.5.1 Vector bit-select and part-select addressing.
An indexed part-select is given with the following syntax:
logic [15:0] down_vect;
logic [0:15] up_vect;
down_vect[lsb_base_expr +: width_expr]
up_vect[msb_base_expr +: width_expr]
down_vect[msb_base_expr -: width_expr]
up_vect[lsb_base_expr -: width_expr]
The msb_base_expr and lsb_base_expr shall be integer expressions, and the width_expr shall be a positive constant integer expression. Each of these expressions shall be evaluated in a self-determined context. The lsb_base_expr and msb_base_expr can vary at run time. The first two examples select bits starting at the base and ascending the bit range. The number of bits selected is equal to the width expression. The second two examples select bits starting at the base and descending the bit range.
In VHDL terms this would be a slice with bounds determined from the high index and a width by subtraction.
PATTERN_WIDTH can be globally static (as in a generic constant) as well as locally static (a non-deferred constant). i_count can be variable.
Depending on the declared range of In for example:
constant DATAWIDTH: natural := 8;
signal In_in: std_logic_vector (31 downto 0);
The equivalent expression would be
if Pattern = In_in(i_count downto i_count - DATAWIDTH - 1) then
Note that if the slice length or i_count is less than DATAWIDTH - 1 you'll get a run time error. The - 1 is because In_in'RIGHT = 0.
Without providing the declarations for In (or Pattern) and DATAWIDTH a better answer can't be provided. It really wants to be re-written as VHDL friendly.
Note as Lars indicated in is reserved word (VHDL is not case sensitive here) and the name was changed.
I am stuck in the following problem-
I need to write a VHDL function that converts 5 bit vector to integer where integer value of binary number a4a3a2a1a0 can be computed as (((0 + a4)* + a3)* + a2 )* +a1)* +a0.
This is not any homework. But I am preparing for my exams.
Thanks!
If your binary number a4a3a2a1a0 is an std_logic_vector, you can use standard conversion functions:
use IEEE.NUMERIC_STD.ALL;
.
integer_result <= to_integer(unsigned(input_vector));
The NUMERIC_STD library must have been used for this to work.
In many cases it may be possible to use 'unsigned' as the type of the input vector, removing one conversion stage.
I am trying to get partial sums of 18*18 multiplication. I want to save these in a multidimensional array(18*36) where each index of array contains a partial sum.
i tried using an array of std_logic_vector. But I got no results. I even tried array of bit_vector and also also of bits.
Here is my VHDL code.
entity partial is
port(
A : in bit_vector(17 downto 0);
B : in bit_vector(17 downto 0);
C : out bit_vector(35 downto 0);
D : out bit
);
end partial;
architecture Behavioral of partial is
type partial_sums is array (17 downto 0, 35 downto 0) of bit;
signal sums : partial_sums;
begin
process (A,B)
begin
--sums <= (others=> (others=>'0'));
--for j in 0 to 17 loop
-- sums(j)<="000000000000000000000000000000000000";
--end loop;
for i in B'low to B'high loop
if ( B(i)='1') then
for p in A'low to A'high loop
sums(i,p) <= A(p);
end loop;
end if;
end loop;
D <= sums(0,0);
end process;
end Behavioral;
I am always getting 0 in D no matter what indices use in sums array.
Please help me.
You are assigning sums to D in a combinatorial process, but sums is not in the process sensitivity list.
Probably the best way to go here is to move the assignment of D outside of the process.
A word of warning: Xilinx ISE including verison 14 has problems with multidimensional arrays and vector assignments. You cannot use three-dimensional arrays and you cannot use unconstrained arrays of arrays. Also, using multidimensional arrays, assignment is somewhat flaky at best. When I used ISE last, it often would complain about legal assignments not having the desired width even when ModelSim would compile and simulate fine.
Your actual problem is likely that you only assign the lower 18 bits of each entry in sums, where the entry is actually 36 bits wide.
For better readability you should probably define
type partial_sums is array (natural range <>) of bit_vector(35 downto 0);
and then use direct bit_vector assignments without loops.
Your fixed values in D are likely due to either B having no bits set to '1' (where you should get U because you lack a default value) or because A's bits are always '0', where you should get all '0' in the lower 18 bits and all 'U' in the upper 18 bis.
EDIT: However, bit is resolved logic, so you will only see '0' or '1' in there. IMO you should use std_logic.
Actually, it works fine, loading appropriate test data into the partial product array.
You just aren't waking the process up again to collect the result on D.
Add "sums" to the sensitivity list of process "partial" to do so.
Or better, make it a clocked process (as you will have to, to get any sensible results when you get to synthesis).
See this Q/A on how signal assignments work.
Is process in VHDL reentrant?
constant MAX : unsigned(18 downto 0) := "100" & x"0000";
constant MIN : unsigned(18 downto 0) := "001" & x"0000";
What is this VHDL code setting max and min to? An explanation of fixed point representation would be helpful.
The & operator concatenates the two bit vectors "100" and x"0000" (e.g. "00" & "11" would be equivalent to "0011").
The X"012345689ABCDEF" syntax means that the following vector should be interpreted as a hex number (e.g. X"0" actually is "0000", X"F" would be "1111" or X"0F" would be "00001111"). This allows you to write a bit vector in a more compact way.
For the interpretation of a bit vector check e.g. http://en.wikipedia.org/wiki/Binary_numeral_system
For representation of hexdecimal numbers check e.g. http://en.wikipedia.org/wiki/Hexadecimal
Edit for clarification: I assume you are using the unsigned type from the numeric_std package. From the header of that package
This package defines numeric types and arithmetic functions
for use with synthesis tools. Two numeric types are defined:
-- > UNSIGNED: represents UNSIGNED number in vector form
-- > SIGNED: represents a SIGNED number in vector form
The base element type is type STD_LOGIC.
The leftmost bit is treated as the most significant bit.
Signed vectors are represented in two's complement form.
So your MAX is set to 2^18 and your MIN to 2^16.