I wanna have a simple module that adds two std_logic_vectors. However, when using the code
below with the + operator it does not synthesize.
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
entity add_module is
port(
pr_in1 : in std_logic_vector(31 downto 0);
pr_in2 : in std_logic_vector(31 downto 0);
pr_out : out std_logic_vector(31 downto 0)
);
end add_module;
architecture Behavior of add_module is
begin
pr_out <= pr_in1 + pr_in2;
end architecture Behavior;
The error message I get from XST
Line 17. + can not have such operands in this context.
Do I miss a library? If possible, I do not wanna convert the inputs into natural numbers.
Many thanks
How do you want the compiler to know if your std_logic_vectors are signed or unsigned ? Adder implementation is not the same in these two cases, so you need to explicitly tell the compiler what you want it to do ;-)
Note: VHDL syntax highlighting in StackOverflow is crappy. Copy/paste this code in your preferred VHDL editor to read it more easily.
library IEEE;
use IEEE.std_logic_1164.all;
-- use IEEE.std_logic_arith.all; -- don't use this
use IEEE.numeric_std.all; -- use that, it's a better coding guideline
-- Also, never ever use IEEE.std_unsigned.all or IEEE.std_signed.all, these
-- are the worst libraries ever. They automatically cast all your vectors
-- to signed or unsigned. Talk about maintainability and strong typed language...
entity add_module is
port(
pr_in1 : in std_logic_vector(31 downto 0);
pr_in2 : in std_logic_vector(31 downto 0);
pr_out : out std_logic_vector(31 downto 0)
);
end add_module;
architecture Behavior of add_module is
begin
-- Here, you first need to cast your input vectors to signed or unsigned
-- (according to your needs). Then, you will be allowed to add them.
-- The result will be a signed or unsigned vector, so you won't be able
-- to assign it directly to your output vector. You first need to cast
-- the result to std_logic_vector.
-- This is the safest and best way to do a computation in VHDL.
pr_out <= std_logic_vector(unsigned(pr_in1) + unsigned(pr_in2));
end architecture Behavior;
Don't use std_logic_arith - I've written about this (at some length :).
Do use numeric_std - and do use the right type on your entity ports. If you are doing arithmetic, use numerical types (either integers, or (un)signed vectors, as appropriate). They'll synthesise perfectly well.
std_logic_vectors are good for
when you don't care about numerical values (a set of control bits, some random data bits)
when you don't know about the type of the input (say an adder which can operate on both signed and unsigned numbers based on a control flag).
Good advice from #Aurelien to use numeric_std.
Bear in mind that adding two 32 bit values can result in a 33 bit value and decide how you want to handle the overflow.
You cannot do an arithmetic operation with just std_logic_vector. Either you have to convert the std_logic_vector to signed/unsigned (depending on your code requirements) (see 1 below) or else convert them to integers (see 2 below)
pr_out = std_logic_vector(unsigned(pr_in1) + "01")
pr_out = std_logic_vector(integer(pr_in1) + 99)
These are just examples. You can change them based on your requirements.
The easy way to solve this error is:
Add library of unsign,
After that your code starts to work.
Use
ieee.std_logic_unsigned.all;
pr_out <= pr_in1 + pr_in2;
Related
I am practising some basic vhdl programs.Now i came across arithmetic operations.I used bit_vector and multiplied the input signals directly but it errors "No feasible entries for infix operator".The program is below:
entity multiplier is
port(a,b : in bit_vector(3 downto 0);
c: out bit_vector(7 downto 0));
end multiplier;
architecture ar of multiplier is
begin
c<=(a*b);
end ar;
But i came across this program which works fine with std_logic_vector
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity Multiplier_VHDL is
port(
Nibble1, Nibble2: in std_logic_vector(3 downto 0);
Result: out std_logic_vector(7 downto 0)
);
end entity Multiplier_VHDL;
architecture Behavioral of Multiplier_VHDL is
begin
Result <= std_logic_vector(unsigned(Nibble1) * unsigned(Nibble2));
end ;
My questions are:
1.cant we simply add 2 signal bits c<=a+b as we do in verilog?
2.should a signal be signed/unsigned to perform arithmetic operations?
3.like c which is signed by default,what about vhdl/verilog?
4.are signed & unsigned present in use ieee.std_logic_arith.all and use IEEE.NUMERIC_STD.ALL same?
1. Cant we simply add 2 signal bits c <= a + b as we do in verilog?
VHDL is a strongly typed language, which means it is strict when it comes to assigning things of different types to each other. Verilog might let you multiply a simple bit vector; you know what the types of the operands are and the format of the result, and that's fine for your design process. In VHDL, it's not good enough that you as the designer know what formats the numbers are in, the compiler wants to know this as well. In your example, the compiler doesn't know if your vectors represent an unsigned number, signed, fixed point, etc. By casting them to unsigned, you are explicitly telling it what the number format is. An even better solution would be to have these as type unsigned throughout, to avoid the type casts.
Another advantage of VHDL strongly typed is that this can help to catch bugs caused by errors in number format storage at the compilation stage instead of under simulation or on an FPGA device. In general it saves time to catch bugs earlier in the design cycle. If you search online for "strongly typed" you will find more discussion on this topic.
2. Should a signal be signed/unsigned to perform arithmetic operations?
As above, if you want to stick to standard libraries, then yes it is a good idea to give your signals a meaningful type. Think about the guy trying to understand your code in 10 years time (it might even be you), if it's clear what the number formats are, their life will be made easier.
3. Like c which is signed by default, what about vhdl/verilog?
c in your example code is not signed by default in VHDL, it has whatever type you declared it as. If you are multiplying using unsigned, the result would also be unsigned, so this would be the type that I would use for the result. If the type of the result signal does not match the return type of the operation, this will be a compiler error.
4. Are signed & unsigned present in use ieee.std_logic_arith.all and use IEEE.NUMERIC_STD.ALL same?
No, it is not recommended to use std_logic_arith, as this library is not part of the VHDL standard. If you familiarise yourself with the number formats in numeric_std, you should not need to use any other libraries for integer arithmetic.
The usual vector type to use in VHDL is std_logic_vector from the package ieee.std_logic_1164, instead of bit_vector.
However, this vector type is just a collection of std_logic elements, without defined arithmetic operations. So the standard VHDL package that can be used to get arithmetic operations is numeric_std.
Using these for VHDL-2002 compatible code for unsigned arithmetic, it will look:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity multiplier is
port(a, b : in std_logic_vector(3 downto 0);
c : out std_logic_vector(7 downto 0));
end multiplier;
architecture ar of multiplier is
begin
c <= std_logic_vector(unsigned(a) * unsigned(b));
end ar;
However, you could choose to define a, ´b´, and ´c´ as unsigned to simplify the code like:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity multiplier is
port(a, b : in unsigned(3 downto 0);
c : out unsigned(7 downto 0));
end multiplier;
architecture ar of multiplier is
begin
c <= a * b;
end ar;
There are also signed types defined in the numeric_std package.
In VHDL-2008, a numeric_std_unsigned package is provided, which provides arithmetic operations for the std_logic_vector type, thus the code can be like:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std_unsigned.all;
entity multiplier is
port(a, b : in std_logic_vector(3 downto 0);
c : out std_logic_vector(7 downto 0));
end multiplier;
architecture ar of multiplier is
begin
c <= a * b;
end ar;
To answer the 4 questions:
Arithmetic operations must be defined for the operands, and this can be done either through use of conversion to unsigned type in numeric_std package, or through use of operators in numeric_std_unsigned package.
For VHDL-2002 yes, and for VHDL-2008 the numeric_std_unsigned package can be used.
See above.
The std_logic_arith package is a Synopsys package, so use numeric_std and numeric_std_unsigned instead.
My project is design of 32bit MAC(Multiply and Accumlate) unit using reversible logic. For the project , i have designed 32bit mulitplier and 64 bit adder using reversible logic. Now, in the next step i want to design a 64 bit accumlator which takes the value from the adder and stores it and adds with the previous value present in it. I am not getting any idea how to design Accumlator.
Please help in completion of my project.
A basic VHDL accumulator can be implemented in only a few lines of code. How you decide to implement it, and any additional features necessary are going to depend on your specific requirements.
For example:
Are the inputs signed or unsigned?
What is the type of the inputs?
Does the accumulator saturate, or will it roll over?
Here is a sample unsigned accumulator to give you an idea of what you need to implement (based on this source):
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity accumulator is
port (
DIN: in std_logic_vector(3 downto 0);
CLK: in std_logic;
RST: in std_logic;
DOUT: out std_logic_vector(3 downto 0)
);
end entity accumulator;
architecture behave of accumulator is
signal acc_value : std_logic_vector(3 downto 0);
begin
process(CLK)
begin
if rising_edge(CLK) then
if RST='1' then
acc_value <= (others => '0'); -- reset accumulated value to 0
else
acc_value <= std_logic_vector( unsigned(acc_value) + unsigned(DIN) );
end if;
end if;
end process;
-- Assign output
DOUT <= acc_value;
end behave;
To describe what this design does in words: Every clock cycle on the rising edge, the data input DIN is interpreted as an unsigned value, and added to the currently accumulated value acc_value. If the RST input is asserted, instead of accumulating the DIN input, the accumulated value is cleared back to 0. The value of the accumulator is always presented on the output of the block, DOUT.
Based on what you are interfacing with, you might want to consider the following changes/modifications:
Perhaps DIN should be signed or unsigned types instead of std_logic_vector. I actually recommend this, but it depends on how you are representing your values in other places of your design.
DOUT could also be a signed or unsigned value instead of std_logic_vector - it depends your requirements.
In this case, acc_value, the accumulated value register, will rollover if the values accumulated get too high. Maybe you want to generate an error condition when this happens, or perform a check to ensure that you saturate at the maximum value of acc_value instead.
acc_value need not be the same width as DIN -- it could be twice as wide (or whatever your requirements are). The wider it is, the more you can accumulate before the rollover condition occurs.
I am trying to come up with a way to estimate the gate count if I were to implement a purely combinational 64-bit division.
I can't get my synthesis tool to generate a combinational 64-bit/64-bit integer division.
a 64bit/64bit divider fully combinational is leading to a huge design. this will use a lot of resources and lead to poor speed achievements. I'd suggest to implement the division with several register stages instead of fully combinational.
however, if you'd like to try, the following code would be synthesisable (as "/" operation is given by numeric_std library). check with a synthesis tool the recources needed for it (for synthesis the use of std_logic_vector in entities is suggested):
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.ALL;
entity divideComb is
Port ( a : in STD_LOGIC_VECTOR (63 downto 0);
b : in STD_LOGIC_VECTOR (63 downto 0);
c : out STD_LOGIC_VECTOR (63 downto 0));
end divideComb;
architecture Behavioral of divideComb is
begin
c<=std_logic_vector(signed(a)/signed(b));
end Behavioral;
the above code leads to the following synthesis results with Xilinx ISE 13.4:
inferred 131 Adder/Subtractor(s)
inferred 65 Comparator(s)
inferred 4036 Multiplexer(s)
when using Spartan 6 architecture, this leads to 6982 Slice LUTs (and 0 FlipFlops, of course!)
I am working on a project but whatever I do I can’t understand what this code does. Since I am not familiar with VHDL, it’s really hard for me to understand the purpose of this code.
library iee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use work.my_package.all;
Entity multiplier is
generic (size: integer :=4);
Port (a,b : in unsigned( size-1 downto 0);
y : out unsigned( size-1 downto 0));
End multiplier ;
ARCHITECTURE behavior of multiplier is
Begin
y<= mult(a,b);
End behavior;
You have an entity which describes the interface of your design. In this case inputs a and b as well as output y. These are all 4-bit values.
The architecture contains the implementation of what you're trying to do (the body if you will). In this case it's simply a multiplication of a and b, which is assigned to y. And (should you be confused) no, the <= does not stand for "smaller than or equal to" but it's an assignment.
It takes two 4 bit inputs and produces a 4 bit product on the output. This is a little weird as the input size is equal to the output so if you multiply together 2 big numbers you get an overflow.
just look for the ARCHITECTURE section and you can see that you do multiplying of two integers a and b which are defined in the Entity section.
the ARCHITECTURE section always describes how you system behaves!
I'm trying to add '1' to an N-Length STD_LOGIC_VECTOR in VHDL
This is the very first time I'm using VHDL so I'm not at all sure how to add this 1 without bulding a Full-Adder which seems kinda of redundent
We are not allowed to use any more liberaries then then one in the code.
LIBRARY IEEE ;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY cnt IS
GENERIC (n: natural :=3);
PORT( clk: IN std_logic; -- clock
rst: IN std_logic; -- reset
cntNum: IN std_logic_vector(n-1 DOWNTO 0); -- # of counting cycles
cntOut: OUT std_logic_vector(n-1 DOWNTO 0) -- count result
);
END cnt;
architecture CntBhvArc OF cnt IS
signal counta : std_logic_vector(n-1 DOWNTO 0);
begin
process (clk, rst)
begin
if rst='1' then
counta<="0";
elsif (clk'event) and (clk='0') then
counta<= counta+'1';
end if;
cntOut<=counta;
end process;
END CntBhvArc
Also... can anyone point to a VHDL totrial for someone who has very little experince in programing?
Thanks
You should not use library IEEE.STD_LOGIC_UNSIGNED.ALL
This library is deprecated (see VHDL FAQ); use ieee.numeric_std.all instead.
To answer your last point - don't think of it as programming. HDL stands for "hardware description language". You're describing hardware, always keep it in mind when writing your code :)
I've also written at length about not using STD_LOGIC_UNSIGNED, but using NUMERIC_STD instead. If this is homework and you're being taught to use STD_LOGIC_UNSIGNED, then I despair of the educational establishments. It's been years since that made sense.
VHDL is strongly-typed, so if count is representing a number (and with a name like that, it better had be :), use either a signed or unsigned vector, or an integer. Integers don't wrap around in simulation unless you make them (if you add 1 to them when they are at their max value, the simulator will terminate). The vector types do. Sometimes you want one behaviour, sometimes the other.
Finally, I just noted this:
elsif (clk'event) and (clk='0') then
which is better written as:
elsif falling_edge(clk) then
again, this has been so for about a decade or two. Were you intending to use the falling edge - rising edge is more usual.
You need to cast the std_logic_vector to an unsigned value so you can add one, then cast it back so you can assign it to your output.
This looks like a homework assignment, so I'll leave you to figure out exactly how to do the implementation.