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.
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 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
How can I calculate the module of a vector?
As a vector is not a pre-defined type in VHDL it makes sense to me that there is no function implementing the modue of a vector. If there is such I have not found it.
This is basically a problem of obtaining the square root of a number, as the module can be defined as:
sqrt(a^2+b^2+...+n^2)
Implementing the sum of all the members of the vector squared is not a challenge so I think the most necessary part is having a function to calculate the square root of a number.
As far as I'm concerned there isn't any official package implementing this function. How to implement a function to calculate the module of a vector?
Or if you prefer it, how to implement a square root?
This is one possible solution. I will provide you 3 codes.
-The first one provides the type definition used for the vector. Its not important but it is needed to make it work.
-The second one is the package in which the function is defined. It is commented so that you can easily adapt it to any kind of vector. It can probably be upgraded to make it adapt by itself using some parameters by this works fine.
-The third one is a testbench to try it out.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
package tipos is
constant bandas : positive := 4;
type vector32 is array (0 to bandas-1) of signed (31 downto 0);
end package tipos;
Be aware of calling properly the library with the vector definition. In my case it was compiled to work for the ModelSim simulation
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
library work; use work.tipos.all;
package propios is
--function declaration.
function module (a : vector32; bands: natural) return unsigned;
end propios; --end of package.
package body propios is --start of package body
--definition of function
--based on: https://en.m.wikipedia.org/wiki/Methods_of_computing_square_roots#Binary_numeral_system_.28base_2.29
function module (a : vector32; bands: natural) return unsigned is --To adapt it to a diferent number of bits in the input vector:
--substitute the 71 for the needed number. Number of bits in each element of the vector *2 + power of two that can represent the maximum
--number of bands, or fields. In this case, 32bit numbers, maximum number of bands, 256, so 2^8. 32*2+8=72.
variable sum : unsigned(71 downto 0):= (others => '0');
variable b : unsigned(71 downto 0):=(0=>'0', 70 => '1', others => '0');
variable a_unsig: unsigned(31 downto 0):=(others =>'0');--for this vector use the same length as the input vector, 32bit in my case.
variable result: unsigned (71 downto 0):= (others => '0');
begin
for i in 0 to bands-1 loop--Sum of all the elements squared
a_unsig:=unsigned(a(i));
sum:=sum + (a_unsig * a_unsig);
end loop;
--Square root of sum
while b>sum loop--Do any needed changes here. You only have to change the 71's
b:='0'&'0'& b(71 downto 2);
end loop;
while (b/=0) loop
if (sum>=result+b) then
sum:=sum - (result + b);
result:=('0'& result(71 downto 1))+b;
else
result:='0'& result(71 downto 1);
end if;
b:='0' & '0' & b(71 downto 2);
end loop;
return result(35 downto 0);--sqrt(2^72)=2^36. Use half of the bits you put in place of 71
end module;
end propios; --end of the package body
And here is the testbench. Again take care of calling the packages properly
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
use work.propios.all;
use work.tipos.all;
ENTITY test IS
END test;
Architecture simple of test is
signal a:vector32;
signal c: unsigned(35 downto 0);
signal b: natural:= 4;
begin
a(0)<="00000000110010011010011100000000";
a(1)<="00000000110010011010011100000000";
a(2)<="00000000110010011010011100000000";
a(3)<="00000000110010011010011100000000";
process
begin
wait for 200ps;
c<= module (a , b);
wait;
end process;
end simple;
following code is a simple instruction Memory in Mips CPU
LIBRARY ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
ENTITY instructionMemory IS
generic (delay :time :=10 ns);
PORT( a : INOUT STD_LOGIC_VECTOR ( 31 downto 0);
output: OUT STD_LOGIC_VECTOR( 31 downto 0)
);
END ENTITY;
ARCHITECTURE instructionMemory OF instructionMemory IS
type MemMatrix is array ( 0 to 7 ) of std_logic_vector(31 downto 0); -- instruction from memory
signal Mem:MemMatrix := (x"00000000",x"00000001",x"00000000",x"00000001",x"00000001",x"00000001",x"00000001",x"00000001");
BEGIN
output <= Mem(conv_integer(a(6 downto 2)));
END instructionMemory;
I assume Mem is Memory and initilized it with some value. I wanna read this data and assign it to output.
But it's gives me following error :
no feasible entries for subprogram conv_integer
I change error line to this :
Mem(a(6 downto 2));
But again it gives me another error:
cannot resolve slice name to type std.standard.integer
I have no idea how to solve this, Can any body help me ?
The following analyzes and elaborates:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity instructionmemory is
generic (delay :time :=10 ns);
port( a : inout std_logic_vector ( 31 downto 0);
output: out std_logic_vector( 31 downto 0)
);
end entity;
architecture instructionmemory of instructionmemory is
type memmatrix is array ( 0 to 7 ) of std_logic_vector(31 downto 0); -- instruction from memory
signal mem:memmatrix := (
x"00000000",x"00000001",x"00000000",x"00000001",
x"00000001",x"00000001",x"00000001",x"00000001"
);
begin
output <= mem(conv_integer(a(6 downto 2))); -- closing paren for mem();
end instructionmemory;
What's different about it is the addition of a matching closing paren in the concurrent signal assignment statement targeting output.
ghdl actually pointed to the character location of the problem with a less than helpful message.
instructionMemory.vhdl:20:47: ',' is expected instead of ';'
The assumption being without a closing paren an additional argument is expected. Your error message(s) likely indicates a YACC/Bison based parser without the ability to provide error messages on non-terminals.
Addendum
If you were to note Russell's comment there is an integer range mismatch between the conversion of 6 downto 0 and memmatrix (0 to 7). The conversion has a binary range of 2**5 while mem has a range of 0 to 7. Should a(6 downto 2) every be out of range 0 to 7 a run time error will occur. Use of an integer type would allow to modify or otherwise handle an a field out of range by checking the integer value against the bound of mem.
You could also increase memmatrix size to accomidate the full range of a(6 downto 2).
Your additional question on how to assign a different index to mem for assigning output requires a bit more context. Where do you want want to get the index from?
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)".