I have just started VHDL module in university and my lecturer isn't good a explaining things. How to I use/declare signed values in VHDL?
This is the basic code format I have been taught and I'm currently programming a 2bit subtractor. The information in other websites are quite confusing.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.std_logic_arith.all;
entity TwoBitSubtractor is port(
x,y :in integer range 0 to 3;
result :out integer range 0 to 3);
end TwoBitSubtractor;
architecture gates of TwoBitSubtractor is
begin
result<= x - y;
end gates;
You should use signed type for specifying signed values. Integer can also be used to declare values in a more human readable manner, but with that you are out of bit-level definitions, which is not desired in VHDL in my opinion. For example, you are ignoring the the amount of bits used for any signal with integer, which can be good for a high level language, but not too useful for VHDL.
library ieee;
use ieee.numeric_std.all;
entity TwoBitSubtractor is port(
x : in signed(2 downto 0);
y : in signed(2 downto 0);
result : out signed(2 downto 0));
end TwoBitSubtractor;
architecture gates of TwoBitSubtractor is
begin
result <= x - y;
end gates;
See the way they are declared within the entity port. More details on signed/unsigned, please check here
Also a working online simulation of TwoBitSubtractor with testbench, check here
Related
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.
I am designing a 2s complement code but it is showing that error can any one help me with that.
library ieee;
use ieee.std_logic_1164.all;
use IEEE.std_logic_arith.all;
entity comp is
port(a : in std_logic_vector(7 downto 0);
y : out std_logic_vector(7 downto 0));
end comp;
architecture dataflow of comp is
signal temp: std_logic;
begin
y<= not(a) + "00000001";
end dataflow;
Error: D:/modelsim_projects/2scmpliment.vhd(13): No feasible entries
for infix operator "+".
When using Synopsys packages, you need to add use of the std_logic_unsigned package after std_logic_1164, like:
use IEEE.std_logic_unsigned.all;
With this you can even use integer notation for addition like:
y <= not(a) + 1;
Alternative is to use the IEEE VHDL standard numeric_std package, with changes like:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
...
y <= std_logic_vector(unsigned(not(a)) + 1);
As the title say I need to write a vhdl code that take as input a 32 bit vector and a 6 bit vector. I need to output another 32 bit vector which is equal the input 32 bit vector but the nth bit of it is flipped. n= the number of the 6 bit vector. Here is my code but is incorrect.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
entity flipMSB is
Port ( Anotf : in STD_LOGIC_VECTOR (31 downto 0);
count : in STD_LOGIC_VECTOR (5 downto 0);
Af : out STD_LOGIC_VECTOR (31 downto 0));
end flipMSB;
architecture bhv of flipMSB is
signal sig: STD_LOGIC_VECTOR(31 downto 0);
signal n : integer;
begin
n<=CONV_INTEGER(count);
sig<=Anotf;
sig(n)<=not sig(n);
Af<=sig;
end bhv;
First, a 6 bit number goes up to 64, you only need 5 bits for your count signal!
Second:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
std_logic_arith and numeric_std have conflicting types. Since std_logic_arith and std_logic_unsigned are not part of the VHDL standard (and IEEE, despite the library name), I suggest you only use numeric_std. If you use VHDL-2008, you can use numeric_std_unsigned. You will need to replace n <= conv_integer(count) with n <= to_integer(unsigned(count))
Finally,
sig<=Anotf;
sig(n)<=not sig(n);
will have two output driver for the bit n, which is bad. If you put that logic into a process, it would be fine since the first assignation to sig(n) would be overridden (instead of driven twice):
process(Anotf, count)
variable n : natural;
begin
Af <= Anotf;
n := to_integer(unsigned(count));
Af(n) <= not Anotf(n);
end process;
Think of it this way, if two processes drive the same signal, this result in two drivers (and conflict!). A statement outside a process is implicitly in its own process. Also, in a process only the last statement assigning a signal will have an effect.
I'm designing a 1 bit ALU and using a structural approach. For some reason I keep getting a type mismatch error even though I'm only using std_logic_vectors for everything. I don't see what could be wrong?
Here's the code:
1 bit ALU:
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.std_logic_arith.ALL;
USE ieee.std_logic_unsigned.ALL;
USE ieee.numeric_std.all;
ENTITY alu1 is
PORT(
a : IN STD_LOGIC_VECTOR;
b : IN STD_LOGIC_VECTOR;
op : IN STD_LOGIC_VECTOR(2 DOWNTO 0);
result : OUT STD_LOGIC_VECTOR;
cout : OUT STD_LOGIC;
zero : OUT STD_LOGIC);
END alu1;
ARCHITECTURE structure OF alu1 IS
COMPONENT FourToOneMux
PORT(
andIn : IN STD_LOGIC_VECTOR;
orIn : IN STD_LOGIC_VECTOR;
addIn : IN STD_LOGIC_VECTOR;
bMuxIn : IN STD_LOGIC_VECTOR;
sel : IN STD_LOGIC_VECTOR;
muxOut : OUT STD_LOGIC_VECTOR);
END COMPONENT;
COMPONENT TwoToOneMux
PORT(
bIn : IN STD_LOGIC_VECTOR;
bInvertedIn : IN STD_LOGIC_VECTOR;
sel : IN STD_LOGIC_VECTOR;
muxOut : OUT STD_LOGIC_VECTOR);
END COMPONENT;
COMPONENT FullAdder
PORT(
a :IN STD_LOGIC_VECTOR;
b :IN STD_LOGIC_VECTOR;
cin :IN STD_LOGIC_VECTOR;
cout :OUT STD_LOGIC_VECTOR;
output :OUT STD_LOGIC_VECTOR);
END COMPONENT;
signal muxOneOut, muxTwoOut, andOut, orOut, addOut, FMuxOut, carryOut : STD_LOGIC_VECTOR := (others => '0');
BEGIN
M1: TwoToOneMux port map(b, NOT b, op(0), muxOneOut);
M2: TwoToOneMux port map(a, b, op(0), muxTwoOut);
andOut <= a AND muxOneOut;
orOut <= a OR muxOneOut;
A1: FullAdder port map(a, muxOneOut, cout, carryOut, addOut);
F1: FourToOneMux port map(andOut, orOut, addOut, muxTwoOut, op(1) & op(2), result);
END structure;
And the TwoToOneMux code:
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.std_logic_arith.ALL;
USE ieee.std_logic_unsigned.ALL;
USE ieee.numeric_std.all;
ENTITY TwoToOneMux is
PORT(
in1 : IN STD_LOGIC_VECTOR;
in2 : IN STD_LOGIC_VECTOR;
sel : IN STD_LOGIC_VECTOR;
output : OUT STD_LOGIC_VECTOR);
END TwoToOneMux;
ARCHITECTURE behavioral OF TwoToOneMux IS BEGIN
WITH sel select
output <= in1 when "0",
in2 when "1",
null when others;
END behavioral;
I'm a newcomer to VHDL and I'm feeling way over my head so any help is appreciated.
Firstly you haven't actually given us a clue what signal or entity the type mismatch applies to, so this will be a scatter-gun answer to problems with your code. But there IS one likely candidate, so bear with me...
For more information, there are a lot of bad sources out there, and some good ones. One of the best is Peter Ashenden's "Designer's Guide to VHDL".
Second, I'm curious where you "got" this USE list: please comment and let me know
USE ieee.std_logic_1164.ALL;
USE ieee.std_logic_arith.ALL;
USE ieee.std_logic_unsigned.ALL;
USE ieee.numeric_std.all;
There are a LOT of sources teaching this style or using it in example code, and I'd like to know which sources to steer beginners away from...
USE ieee.std_logic_1164.ALL;
USE ieee.numeric_std.all;
is all you want or need; the other libraries are non-standard, (forced into VHDL by a large company in their commercial interest, and going against the VHDL philosophy). They introduce multiple definitions of different types with the same names as ieee.numeric_std.signed and unsigned which help create confusion.
A quick tutorial in using the numeric_std type system:
- Use std_logic_vector where the value you are handling is untyped : e.g. a word that could be signed, unsigned, an instruction, a float or whatever else from context
- Use signed where the value is a signed integer
- Use unsigned where the value is an usigned integer
Correct choice of declarations will reduce the number of conversions between these types.
Third, ALL your STD_LOGIC_VECTOR ports and signals are unconstrained. There are places where unconstrained vectors are appropriate, but ... this is broken.
VHDL is strongly typed and does not infer types, but it gives you tools for limited forms of type introspection. Using this is easy and safe (because the compiler catches most errors!) but often considered fairly advanced because it can be frustrating to a beginner.
So
Signal A_BUS : std_logic_vector(31 downto 0);
Signal B_BUS : std_logic_vector(7 downto 0);
declare two different types of signal : both std_logic_vector but 32 and 8 bits respectively. Now given a component with ports
PORT(
a : IN STD_LOGIC_VECTOR;
b : IN STD_LOGIC_VECTOR );
it can be connected as
PORT MAP(
a => a_bus,
b => b_bus );
... see the problem? a and b are incompatible because they have different lengths. You can maybe get away with this in Python where dynamic typing can try to clean up the mess at runtime or maybe in C where type mismatches silently cause overflows to crash something else much later. But not in VHDL where you're designing hardware, and you actually want it to work.
The simplest (beginner) solution is to explicitly declare all your signal and port lengths
PORT(
a : IN STD_LOGIC_VECTOR(31 downto 0);
b : IN STD_LOGIC_VECTOR(31 downto 0));
and now the compiler will catch the error in the port map.
The downside of this is that it stops you using the same module in a polymorphic manner, e.g. in 8-bit, 16-bit and 32-bit CPUs. Often that doesn't matter, but where it does, more advanced techniques come in...
Look at one of your internal signal declarations :
signal muxOneOut : STD_LOGIC_VECTOR;
Imagine you want muxOneOut to have the same range as port A... You can do this by declaring:
signal muxOneOut : STD_LOGIC_VECTOR(A'range);
It now adjusts itself to whatever signal is externally connected to port A. If the mux selects ports A or B onto this signal, this works - assuming ports A and B are the same width. So let's check that assumption:
assert A'length = B'length report "Port width mismatch" severity FAILURE;
Now building the design will fail if the external signals are incorrectly sized.
And so on...
But we still haven't got to the likely culprit for your type mismatch. And it is this:
COMPONENT TwoToOneMux
PORT(
bIn : IN STD_LOGIC_VECTOR;
bInvertedIn : IN STD_LOGIC_VECTOR;
sel : IN STD_LOGIC_VECTOR;
muxOut : OUT STD_LOGIC_VECTOR);
END COMPONENT;
...
M2: TwoToOneMux port map(a, b, op(0), muxTwoOut);
(ditto M1). And it turns out that you ARE using more than one type : you are using both std_logic_vector, and std_logic.
"sel" is clearly a one bit signal, and the clearest way to express it is std_logic. However a one-bit std_logic_vector (as you are using here) is perfectly legal, just confusing as hell (though std_logic_vector makes more sense if you also use the same style for e.g. 4:1 and 8:1 muxes).
All you need to do to extract a 1-bit std_logic_vector version is to use the correct syntax : op(0 downto 0) extracts a vector which starts and ends at the same element, instead of op(0) which extracts a std_logic.
I'm learning VHDL and I'm having a problem with some code I'm trying to write to satisfy a bound-check exception.
Here is my basic summarized code:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.std_logic_arith.all;
use IEEE.NUMERIC_STD.ALL;
use ieee.std_logic_unsigned.all;
...
port(
Address: in std_logic_vector(15 downto 0);
...
constant SIZE : integer := 4096;
variable addr: integer range 0 to SIZE-1 := 0;
...
process ...
addr := conv_integer(Address) and (SIZE-1); --error here
The error message I get is
src/memory.vhd:37:35: no function declarations for operator "and"
Basically, my goal is to make a 16-bit address bus, reference memory with only 4096 bytes. Why do I get this odd error? Am I missing a library include or something?
First: Don't use std_logic_arith and numeric_std. And you don't need std_logic_arith
You can't do bitwise ANDs on integers, so you need to do something like:
addr := Address and to_unsigned(SIZE-1, Address'length);
But you'll probably want to guarantee SIZE is a power-of-2
what I tend to do is create a constant in bits and work up from there:
constant mem_bits : integer := 16;
constant SIZE : integer := 2**16;
then
addr := Address(mem_bits-1 downto 0);
I don't think and is defined for integers, although there might be a standard library that includes that functionality.
Why not keep your address as a std_logic_vector though? When it comes to addresses, you often want to be able to do easy decoding by looking directly at certain bits, so I think it makes rather good sense.
Just make addr a std_logic_vector(11 downto 0), and assign the lowest 12 bits of address to it - that will ignore the upper 4 bytes, and give you 4096 bytes of space (for an 8-bit databus).
And does not make sense for an integer. Integer is a number within a range, but it has no standard way of implementing itself, i.e. it has no predefined representation in binary.
you can use something like the syntax, below;
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
entity testand is
generic (nBITS:integer:=32);
port (
i:in integer;
a:in std_logic_vector(nBITS-1 downto 0);
o:out std_logic_vector(nBITS-1 downto 0));
end entity;
architecture beh of testand is
signal v:std_logic_vector(a'length-1 downto 0);
begin
v<=std_logic_vector(conv_unsigned(i,o'length));
o<=v and a;
end architecture;
In your specific case you could also use "mod SIZE" instead of "and (SIZE-1)".