I have two numbers A and B, both of different sizes and i need to multiply them using VHDL. I don't know the exact logic to multiply them.
If you are trying to multiply two std_logic_vector, then * will fails,
since std_logic_vector is just an array of std_logic elements, but does not
have an inherit numerical representation.
So take a look a the
ieee.numeric_std VHDL
package. This defines unsigned and signed types that assume a typical
numerical representation of an array, along with operators on these types,
including *. Using this package you can do:
use ieee.numeric_std.all;
...
c <= std_logic_vector(unsigned(a) * unsigned(b));
Note that for * the c'length is a'length + b'length.
Btw. welcome to Stack Overflow, and please spend some time in Stack Overflow
Help Center, so you can get better answers in
the future, and avoid being voted down or get the answer closed.
Related
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 5 years ago.
Improve this question
Most, if not all, VHDL textbooks casually list the arithmetic operators and amongst them even more so casually the Shift Left Arithmetic (SLA) as shift left that fills with rightmost element. Although even wikipedia disagrees with this definition, I have never seen anyone to even blink an eye to this definition, it's just taken in with a face value, "yup, makes sense".
However, the apparent complete uselessness of filling with the rightmost value in binary arithmetics made me to wonder - has anyone found a really good use for SLA in real life?
(I'm not against the existence of SLA, nor want to eradicate it from VHDL. This is just a bit of fun for the Easter holidays...)
This site mentions:
At one point, there were actual shift operators built into VHDL. These were: srl, sll, sra, sla. However these shift operators never worked correctly and were removed from the language. This website goes into great detail about the history of these VHDL shift operators and discusses why they have been replaced by shift_right() and shift_left() functions.
However the link is broken.
The wikipedia page you link shows something very important
The VHDL arithmetic left shift operator [sla] is unusual. Instead of filling the LSB of the result with zero, it copies the original LSB into the new LSB. While this is an exact mirror image of the arithmetic right shift, it is not the conventional definition of the operator, and is not equivalent to multiplication by a power of 2. In the VHDL 2008 standard this strange behavior was left unchanged (for backward compatibility) for argument types that do not have forced numeric interpretation (e.g., BIT_VECTOR) but 'SLA' for unsigned and signed argument types behaves in the expected way (i.e., rightmost positions are filled with zeros). VHDL's shift left logical (SLL) function does implement the aforementioned 'standard' arithmetic shift.
I.e. now we have the peculiar situation that sla behaves differently for different data types. That sounds like a very stupid thing to me.
However, this is expected... in my experience IEEE standardization committees mostly consist of a lot of older men, some who where there when the committee started (<'87). The rest are representatives of companies, that also don't like change. If sla etc. would be removed, this would mean a lot of old code would have to be rewritten.
Then after months of discussion they decide to keep the old folks happy by keeping the old behavior for old data types, and changing the behavior for new data types....
edit
To make it more awkward, it seems sla is not defined for the std_logic_vector and unsigned types and such... But it comes back for the ufixed type and such. So I've managed to write some (vhdl-2008) code demonstrating the difference in behavior:
entity test_e is
end entity;
library ieee;
architecture test_a of test_e is
constant value1 : bit_vector(3 downto 0) := "0001";
constant value2 : bit_vector(3 downto 0) := value1 sla 2;
use ieee.fixed_pkg.all;
constant value3 : ufixed(3 downto 0) := to_ufixed(1,3,0);
constant value4 : ufixed(3 downto 0) := value3 sla 2;
begin
end architecture;
When simulating, value2 will hold "0111" and value4 will hold "0100".
Of course, when you need to multiple to 2^n, you just need to SLA to n bit.
I use it in current project, to reduce used resources of FPGA, before division I use SRA, in result I get smaller number than was, use division and then use SRL to get right scale of the value.
It looks like, C=A/B, with reducing C*N=(A/N)/B.
You get some error in C, but reduce used resources.
I use the following package only in my VHDL file:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
In the code, I compare a std_logic_vector signal : A with a constant value, e.g
...if A<="00001011" then
yet the code was checked correctly by Xilinx ISE. My understanding is that STD_LOGIC_1164 package does not include an implementation of inequalities having as an operand std_logic_vector so why the above code statement was accepted and will the above comparison treat A as signed or unsigned number?
-- Copying my comp.lang.vhdl reply to this post. Sorry some duplicates, but some does not.
All enumerated types and arrays of enumerated types implicitly define the regular ordering relational operators (>, >=, <, <=). Unfortunately it is not numerically ordered, so the results may not be as expected. Instead it is dictionary ordered.
First you have to look at the element type, which is std_logic whose base type is std_ulogic. For an enumerated type, such as std_ulogic, left values are less than right values, hence, for std_ulogic (and std_logic):
'U' < 'X' < '0' < '1' < 'Z' < 'W' < 'L' < 'H' < '-'
For equal length arrays whose element base type is std_ulogic (such as std_logic_vector or std_ulogic_vector) whose values are only 0 or 1, things work out fine:
"1010" > "0101"
Note that dictionary comparisons always compare the left element first. Hence, for string, something that starts with 'S' is always less than something that starts with 'T' independent of length. This is great for sorting strings into a dictionary and is the only practical default - if we are going to provide such as thing.
OTOH, this is not so great if you are thinking things are numeric. For example, if the arrays are not equal length, then the following is true because the leading '1'on the left parameter is > the leading '0' of the right parameter.
"100" > "0111"
Hence, with only "use ieee.std_logic_1164.all", you have potential exposure to bad coding practices that mistakenly think of std_logic_vector as numeric (such as unsigned).
Many will argue, never use std_logic_vector for math and ">" is math. I generally agree.
So what do I do? How do I protect my design and design team from this. First you have to decide a policy and how to implement it.
1) Forbid use of regular ordering relational operators (>, >=, <, <=) with std_logic_vector and enforce it with a lint tool. However this means you have to buy and require the use of a lint tool.
2) Forbid use of regular ordering relational operators (>, >=, <, <=) with std_logic_vector and enforce it by using the both of the following package references. Note that this generates errors by referencing two definitions for each of the operators, and hence, when used the expression becomes ambiguous. Note this may be problematic since numeric_std_unsigned was introduced in 1076-2008 and it may not yet be supported by your synthesis tools.
library ieee ;
use ieee.numeric_std_unsigned.all ;
use ieee.std_logic_unsigned.all ;
3) Relax the rules some. Our biggest concern is design correctness. Allow std_logic_vector to be interpreted as an unsigned value and either reference numeric_std_unsigned (preferred, but it is VHDL-2008 and may not be implemented by your synthesis tool yet - but if it is not be sure to submit a bug report) or std_logic_unsigned (not preferred - this is an old shareware package that is not an IEEE standard and perhaps does not belong in the IEEE library - OTOH, it is well supported and it plays nice with other packages - such as numeric_std).
The nice result of this is that it also allows comparisons that include integers:
if A <= 11 then
Note, some suggest that the overloading of ">" and friends in numeric_std_unsigned/std_logic_unsigned is illegal. This was a very conservative interpretation of 1076 prior to VHDL-2008. It was fixed for all revisions of VHDL with an ISAC resolution prior to VHDL-2008 that determined that explicitly defined operators always overload implicitly defined operators without creating any ambiguity. I note that even the VHDL FAQ is out of date on this issue.
4) Be formal, but practical. Never use std_logic_vector. Only use numeric types, such as unsigned and signed from package ieee.numeric_std. Types signed and unsigned also support comparisons with integers.
There are probably a few strategies I left out.
Note that VHDL-2008 introduces matching operators which also address this issue by not defining them for types that do not have a numeric interpretation. These operators are: ?=, ?/=, ?>, ?>=, ?<, ?<=
"<=" is called a relational operator in VHDL.
It's predefined. See IEEE Std 1076-2008, 9.2.3 Relational operators the table. It's a predefined operator for any scalar or single dimensional discrete array type.
std_logic_vector qualifies as a single dimensional discrete array type, it's element types discrete, in this case being enumerated types (std_logic/std_ulogic). See 5.2 Scalar types, 5.2.1 General, wherein the first paragraph demonstrates an enumerated type is discrete.
And for a simpler answer it's part of the language.
Short answer: you need to use an extra package: ieee.numeric_std
I must assume that you have defined A as a std_logic_vector(7 downto 0).
This data type represents an array of bits. There is no numeric value associated with it. Hence, the comparison between A and your bit string literal does not make sense.
If you want to compare the numeric values represented by A, you need to use unsigned(7 downto 0) or signed(7 downto 0), preferably from the package ieee.numeric_std. This is the accepted good practice to attribute numeric values to arrays of bits.
Technically, you could work around this and define your own "<=" function, but you would just be duplicating code from the VHDL standard IEEE library.
To expand on David's answer slightly: it's predefined for discrete arrays such that, basically, array elements are compared left to right (according to IEEE 1076-2008, 9.2.3), and each scalar array element is compared using its inherent order which, in the case of an enumeration like std_logic, is defined by its position (according to 5.2.2.1). '1' is "greater than" '0' only because its position in the std_ulogic declaration is higher (and 'Z' is "greater than" '1' for the same reason).
It should be clear from this that it's not treating the vectors as signed or unsigned. It happens to look like it's treating the vectors as unsigned if they're equal length and only contain '0' and '1', but you still shouldn't do it.
I am working in 8 bit pixel values..for ease of coding i want to use conv_integer to convert this 8 bit std_logic_vector.is it cause any synthesise problem?is it reduce the speed of hardware...
No, integers synthesise just fine. Don't use conv_integer though - that's from an old non-standard library.
You want to use ieee.numeric_std; and then to_integer(unsigned(some_vector));
If you still want to access the bits, and treat the vector as a number, then use the signed or unsigned type - they define vectors of bits (which can still have -, Z etc.) which behave as numbers, so you can write unsigned_vector <= unsigned_vector + 1.
You will lose a lot of the functionality that comes with the standard logic vector such as having the value 'Z' or 'X'. If you need access to the bits leave it as std_logic_vector, or cast it to numeric_std. If you don't and you need to do some fancy arithmetic maybe it's better to have as an int. At the end of the day its all bits. Its normally best to keep to a vector type (std_logic_vector, unsigned, signed etc) at the top level so you can map each bit to a specific pin, but otherwise, you can use whatever types you want. Don't forget you are designing hardware now, not software, and there is a difference.
Is there any way to use pre-defined types from STD_LOGIC_1164 or STD_NUMERIC to represent an integer ranging from 0 to 2^32-1 ? (considering the default integer type ranges from -2^31-1 to 2^31-1)
I need to implement 32-bit counter and was looking for some way to save code using integer type instead of std_logic_vector.. Any design pattern for this ?
Or, better asked: Whats the best way to declare a 32-bit (unsigned) integer supporting the operations >/<, =, +-/ ?
Tahnks in advance
Edit1: One option I found was to declare a signal as std_logic_vector(31 downto 0), and to perform conversions when doing comparisons or +- operations.. ex: counter <= counter + std_logic_vector(unsigned(value) + 1).. Still haven't found a way to do division though (in case,for example, 1/4 of the value of counter is needed)
Using the Integer types, you cannot (at least, not portably; there may be some VHDL tools that go beyond the minimum and offer a 64-bit integer)
Using IEEE.numeric_std, you can declare an Unsigned with a full 32-bit range (or 53-bit if you wish) and it should do everything you want.need, unless I misunderstand what you are asking.
use ieee.numeric_std.all;
and then use the unsigned data type - this operates as a bit vector with mathematical operations defined for it. You can choose how many bits you'd like. For example:
signal mynum : unsigned(234 downto 0)
I'm creating a full adder with a variable number of bits. I've got a component that is a half-adder which takes in three inputs (the two bits to add, and a carry in bit) and gives 2 outputs (one bit output and a carry out bit).
I need to tie the carry out of one half-adder to the carry in of another. And I need to do this a variable number of times (if I'm adding 4 digit numbers, I'll need 4 half adders. If I'm doing 32 bit numbers, I'll need 32 half adders).
I was going to tie the carry outs of one half-adder to the carry in of another using signals, but I don't know how to create a variable number of signals.
I can instantiate a variable number of half-adders using a for-loop in a process, but since signals are defined outside of processes, I can't use a for loop for it. I don't know how I should tie the half-adders together.
The easiest way to write an adder in VHDL is not to worry about full adders and half adders, but just type:
a <= b + c;
where a,b and c are signed or unsigned
95% of the time, the synthesis tools will do a better job than you would.
I think you want variable-width signals not variable numbers of signals
Your signals need to be std_logic_vector(31 downto 0) for example - and then you wire up the bits of those signals to your half-adders appropriately.
Of course, as those signals are numbers, then don't use std_logic_vector use signed or unsigned (and the ieee.numeric_std lib).
And (as Philippe rightly points out) unless this is a learning exercise, just use the + operator.