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.
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'm new to VHDL and am having a bit of an issue with the synthesis tool crashing when I have certain stuff in my code (developing in Xilinx ISE).
Below is the gist of what is making the program crash.
signal enteredDigit1 : std_logic_vector(3 downto 0);
begin
u3: entity work.module port map (x,y, enteredDigit1)
process(asyncClock, enteredDigit1) begin
ssegDigit <= enteredDigit1
end process
If I do the ssegDigit <= enteredDigit1 outside that process, its fine. However due to me needing to write an asynchronous bit of code, I figured it would be easier to keep track of states and such in a process.
Any ideas why it would just crash? I get no indication from the program console.
EDIT: It seems to be crashing because I'm assigning ssegDigit a new value. If I instead give enteredDigit1 to a variable in the process it compiles
Without seeing the error message and/or the declaration for ssegDigit it may be impossible to provide a definitive answer.
This analyzes:
library ieee;
use ieee.std_logic_1164.all;
entity module is
port (
signal x: in std_logic_vector (3 downto 0);
signal y: in std_logic_vector (3 downto 0);
signal enteredDigit1: out std_logic_vector (3 downto 0)
);
end entity;
architecture foo of module is
begin
end architecture;
library ieee;
use ieee.std_logic_1164.all;
entity ssegDigit_tb is
end entity;
architecture foo of ssegDigit_tb is
signal asyncClock: std_logic;
signal x: std_logic_vector(3 downto 0);
signal y: std_logic_vector(3 downto 0);
signal ssegDigit: std_logic_vector(3 downto 0);
signal enteredDigit1 : std_logic_vector(3 downto 0);
begin
u3: entity work.module port map (x,y, enteredDigit1);
process(asyncClock, enteredDigit1)
begin
ssegDigit <= enteredDigit1;
end process;
end architecture;
Notice that ssegDigit has the same index range of enteredDigit1, and I corrected the declaration for enteredDigit1 which was:
signal enteredDigit1 : std_logic_vector(3 down 0);
Where the VHDL reserved word downto was not complete and should be:
signal enteredDigit1 : std_logic_vector(3 downto 0);
Without knowing your exact methodology for causing the ISE tool to crash there's an outside possibility that it's parser isn't robust enough.
In general a simulator's analyzer is going to be more robust than one found in a synthesis tool. Synthesizers are written anticipating a valid VHDL design specification, which also points to the utility of validating your design before synthesis.
If neither the declaration for ssegDigit having a matching element for each element in enteredDigit1 nor fixing the reserved word downto in declaration for enteredDigit1 is your problem, by definition you haven't provided enough information. Also notice the semicolon following the assignment statement in the process and after end process.
Let us know, and elaborate the question if needed.
Noted you corrected the downto in your example but not the missing semicolons.
After your comment:
... The sseg digits are declared as you expected, and port mapped to the same range. I was thinking maybe its a case of the synthesizer flipping out because the signal enteredDigit1 is being modified in a few places. Any idea why it would work outside the process? synchronous issues?
It appears that ssegDigit is declared as a signal and connected to a port. This points to the futility of playing twenty questions in comments, where each time around a bit more information is revealed (we'd eventually get a message suggesting moving dialogs to a wiki chat if nothing else).
Perhaps you could show port declarations including mode, signal declarations for the involved elements and any assignment statements for the signals particularly enteredDigit1.
It might also be useful for you to demonstrate the indications leading you to conclude the synthesis tool 'crashing'.
See How do I ask a good question? , Help others reproduce the problem, "Include just enough code to allow others to reproduce the problem. For help with this, read How to create a Minimal, Complete, Valid Example" (How to create a Minimal, Complete, and Verifiable example).
The code below is a simple vhdl structural architecture, however, the
concurrent assignment to the signal, comb1, is upsetting the simulation
with the outputs (tb_lfsr_out) and comb1 becoming undefined. Please, please help,
thank you, Louise.
library IEEE;
use IEEE.STD_LOGIC_1164.all;
entity testbench is
end testbench;
architecture behavioural of testbench is
CONSTANT clock_frequency : REAL := 1.0e9;
CONSTANT clock_period : REAL := (1.0/clock_frequency)/2.0;
signal tb_master_clk, comb1: STD_LOGIC := '0';
signal tb_lfsr_out : std_logic_vector(2 DOWNTO 0) := "111";
component dff
port
(
q: out STD_LOGIC;
d, clk: in STD_LOGIC
);
end component;
begin
-- Clock/Start Conversion Generator
tb_master_clk <= (NOT tb_master_clk) AFTER (1 SEC * clock_period);
comb1 <= tb_lfsr_out(0) xor tb_lfsr_out(2);
dff6: dff port map (tb_lfsr_out(2), tb_lfsr_out(1), tb_master_clk);
dff7: dff port map (tb_lfsr_out(1), tb_lfsr_out(0), tb_master_clk);
dff8: dff port map (tb_lfsr_out(0), comb1, tb_master_clk);
end behavioural;
It's just a little more complex than Radix Ciano(1) says. All tb_lfsr_out elements are showing 'U' from Now = 0 ns. The reason why is that all of the D flip flops aren't initialized.
All tb_lfsr_out elements are showing 'U' from Now = 0 ns. The reason why is that all of the D flip flops aren't initialized.
If you reset all the flip flops the result will always be '0' without a '1' to cause a flip in the XOR gate.
Preset the D flip flops (which can come for free in an FPGA implementation):
This was done by simply adding a default value:
q: out std_logic := '1';
(1) Yes it's a minor change, and to all appearances someone changed their user name and if asked I would have changed Radix to Ciano. Making changes simply to cross a threshold is ridiculous.
The entire purpose of this answer was to avoid stepping on the other answerer's rights of authorship and now he's done the very thing. The issue with his answer being that the complimentary property of XOR prevented the LFSR from working when all inputs were '0's or any inputs were metavalues.
And while you're at it no one noticed the error in the waveform now corrected, apparently too self absorbed in playing games with answer edits. (The signals after the label dff8 were actually from dff7).
There's a message here which is in the form of a question. What's the purpose in answering questions on stackoverflow? See Why I no longer contribute to StackOverflow . And note Mr. Richter's reputation has continued to eek upward, including for the example post on goto he cites as likely to induce severe ire. (And the message there is have patience all you petty editors, sooner or later you're 'reputation' will reach self sustaining levels unless the system is altered to prevent it).
Also note the question's author has to date and after an impassioned plea closing his question not show acceptance of nor use for any answer.
In the mean time quit spoiling why I answer questions on VHDL by changing the words I write, although I have to admit the edit voting history was entertaining.
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;