VHDL shift_right number - vhdl

I want to divide a number by 512 meaning that I need to shift it by 9. For example in my code I want to take the number 26 in binary form to multiply by 100 and then divide it by 512. But instead of dividing by 512 all I need to do is to shift right 9 times the number 26*100. But when I do the shift_right command I get the following error:
Error (10511): VHDL Qualified Expression error at Multiplier_VHDL .vhd(34): SHIFT_RIGHT type specified in Qualified Expression must match std_logic_vector type that is implied for expression by context
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity Multiplier_VHDL is
GENERIC (
display_resolution : INTEGER := 23; -- counter to get to the lowest frequency
display_counter: INTEGER := 8); -- counter to get to 97KHz frequency
port (
Nibble1 : in std_logic_vector(display_counter downto 0) := "000011010"; -- 26 in binary form
Nibble2 : in std_logic_vector(display_counter downto 0);
Result: out std_logic_vector(17 downto 0));
end entity Multiplier_VHDL;
architecture Behavioral of Multiplier_VHDL is
signal number : unsigned(display_counter downto 0) := "001100100"; -- 100 in binary form
begin
Result <= std_logic_vector(unsigned(Nibble1) * unsigned(number));
Result <= (shift_right(unsigned(number), display_counter + 1));
end architecture Behavioral;

shift_right returns either unsigned or signed, depending on what you give it. So you're trying to write an unsigned to a std_logic_vector (Result is of type std_logic_vector).
Also, number is already of type unsigned so there's no need to cast it to unsigned again.
But I give you +1 point for using numeric_std rather than std_logic_arith.

Related

Adding two vectors of 5 bit numbers in vhdl

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.

std_logic_vector to integer conversion vhdl

I faced with conversion problem/I read a lot of similar topics but my code still not working.Could you pls give me some hints. Quartus give me error:
Error (10476): VHDL error at true_dual_port_ram_single_clock.vhd(44): type of identifier "random_num_i" does not agree with its usage as "std_logic_vector" type
LIBRARY ieee;
USE ieee.std_logic_1164.all;
use IEEE.std_logic_signed.all;
use IEEE.std_logic_unsigned.all;
use IEEE.NUMERIC_STD.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
entity write_ram is
generic(width : integer := 32);
port(clock_i : IN STD_LOGIC;
we_w : IN STD_LOGIC;
wr_addr : IN INTEGER RANGE 0 to 31;
read_add : IN INTEGER RANGE 0 to 31;
q_out : out STD_LOGIC_VECTOR(2 DOWNTO 0)
);
end write_ram;
architecture rtl of write_ram is
--- Component decalarartion
component random is
port(clk : in std_logic;
random_num : out std_logic_vector(width - 1 downto 0) --output vector
);
end component;
component single_clock_ram is
port(clock : IN STD_LOGIC;
data : IN INTEGER RANGE 0 to 31;
write_address : IN INTEGER RANGE 0 to 31;
read_address : IN INTEGER RANGE 0 to 31;
we : IN STD_LOGIC;
q : OUT STD_LOGIC_VECTOR(2 DOWNTO 0)
);
end component;
for all : random use entity work.random(rtl);
for all : single_clock_ram use entity work.single_clock_ram(rtl);
Signal random_num_i : INTEGER RANGE 0 to 31; --interanal signals
begin
-- Component Instantiation
C1 : random Port map(
clk => clock_i,
--random_num <=to_integer(to_signed(random_num_i))
random_num => random_num_i
);
random_num <= to_integer(to_signed(random_num_i)); -- error
C2 : single_clock_ram
Port map(
clock => clock_i,
we => we_w,
read_address => read_add,
write_address => wr_addr,
data => random_num_i,
q => q_out
);
end rtl;
Your question isn't an MCVE with the configuration specifications for random and single_clock_ram present. You didn't supply the entity declarations and architecture bodies (rtl) for them.
With them commented out this analyzes:
library ieee;
use ieee.std_logic_1164.all;
-- use ieee.std_logic_signed.all; -- NOT USED
-- use ieee.std_logic_unsigned.all; -- NOT USED
use ieee.numeric_std.all;
-- use ieee.std_logic_arith.all; -- NOT USED
entity write_ram is
generic (width: integer := 32);
port (clock_i: in std_logic;
we_w: in std_logic;
wr_addr: in integer range 0 to 31;
read_add: in integer range 0 to 31;
q_out: out std_logic_vector(2 downto 0)
);
end entity write_ram;
architecture rtl of write_ram is
--- component declaration
component random is
port (clk: in std_logic;
random_num: out std_logic_vector(width - 1 downto 0) --output vector
);
end component;
component single_clock_ram is
port (clock: in std_logic;
data: in integer range 0 to 31;
write_address: in integer range 0 to 31;
read_address: in integer range 0 to 31;
we: in std_logic;
q: out std_logic_vector(2 downto 0)
);
end component;
-- for all: random use entity work.random(rtl);
-- for all: single_clock_ram use entity work.single_clock_ram(rtl);
signal random_num_i: integer range 0 to 31; -- internal signals
signal random_num: std_logic_vector(width - 1 downto 0); -- added
begin
-- component instantiation
c1: random port map (
clk => clock_i,
-- random_num <=to_integer(to_signed(random_num_i))
-- random_num => random_num_i -- DELETED
random_num => random_num -- ADDED
);
-- random_num <= to_integer(to_signed(random_num_i)); -- error DELETED
random_num_i <= to_integer(signed(random_num)); -- ADDED
c2: single_clock_ram
port map (
clock => clock_i,
we => we_w,
read_address => read_add,
write_address => wr_addr,
data => random_num_i,
q => q_out
);
end architecture rtl;
Note there's been a random_num std_logic_vector declared to hook up to the output of random, which is converted an integer random_num_i used as an input to single_clock_ram data. The output q from the single_clock_ram looks a bit suspicious, should that be an integer or a wider std_logic_vector?
First, delete the non-standard libraries.
use IEEE.std_logic_signed.all;
use IEEE.std_logic_unsigned.all;
use IEEE.STD_LOGIC_ARITH.ALL;
leaving only std_logic_1164 and numeric_std.
The others introduce a bunch of overlapping declarations which make it difficult to determine what is going on - and if there are several declarations for the same operator with the same argument and result types, the compiler makes them all invisible rather than picking an arbitrary one.
Then, decide what you are trying to do. This is currently ambiguous and contradictory.
(1)You have a generic (width : integer :=32); and a port declaration
random_num : out std_logic_vector (width-1 downto 0)
which suggest you are dealing with 32 bit words.
(2) You have a ranged integer : Signal random_num_i: INTEGER RANGE 0 to 31; which (a) should be a ranged NATURAL to make it even clearer that negative values are errors, and (b) suggests you are dealing with 5 bit words.
Which is it? What exactly are you trying to do?
And here, you are apparently trying to connect them together in a port map...
C1: random Port map (
clk => clock_i,
--random_num <=to_integer(to_signed(random_num_i))
random_num =>random_num_i
);
random_num <=to_integer(to_signed(random_num_i)); -- error
There are a number of things wrong here.
1) A simple port mapping like random_num =>random_num_i requires that both sides have the same type. This would work if both sides actually WERE the same type : for example, if you added a signal declaration
random_num_slv : std_logic_vector (width-1 downto 0);
then the port mapping random_num =>random_num_slv would work. Now you can convert to the required type random_num_i in a signal assignment.
random_num_i <= to_integer (unsigned(random_num_slv));
There are still problems with this : a 32-bit output is likely to overflow a 5-bit integer.
While adding an intermediate signal random_num_slv may look inefficient and redundant, it keeps the design clean and simple, which matters when dealing with tools that don't understand type conversions in ports.
Make sure you know how to use intermediate signals even if there's a cleaner approach. It can save you when all else fails.
(2) The commented out port mapping
random_num <=to_integer(to_signed(random_num_i))
would be the way to do it, except for three things ...
(a) <= is a signal assignment, you need => a n association operator
(b) you're converting an integer to an integer, and driving a std_logic_vector with it. That really won't work...
(c) the component port is an OUTPUT so you shouldn't be driving it in the first place.
What you probably meant was
to_integer(unsigned(random_num)) => random_num_i
and this would be the cleanest way to do it if your tools support conversions in port maps properly.
Notes:
again it has the overflow problem, a 32-bit vector won't fit a 5 bit integer.
You can convert from std_logic_vector to either signed or unsigned by casting unsigned rather than a conversion function to_signed as they are closely related types. Integers are not "closely related" to these, so need a conversion function to_integer.
As negative numbers aren't permitted by the declaration of random_num_i, use unsigned rather than signed.
(3) The existing signal assignment
random_num <=to_integer(to_signed(random_num_i)); -- error
again contains several errors. The biggest is that there is no random_num port visible outside the component declaration. Simply delete this line, you need to use one of the port mappings.
Further considerations:
(1) Some type conversions are inevitable. But if you are doing too many, that generally points to a design error, like the use of std_logic_vector everywhere, even for thengs like addresses which are inevitably unsigned integers so either unsigned ornatural would be a better choice. Keep the design as simple and readable as possible. I think your use of integer here is generally good but natural would be better (unless you need negative addresses!)
(2) If you're adding the flexibility of a generic like width, use it correctly and consistently - OR - check it's valid.
Here, as described above, your design ONLY works correctly without surprises IF this entity is instantiated with width => 5.
So, check the value and abort if this precondition is not met.
assert Width = 5 report "Width of " & natural'image(width) & " not supported!"
severity FAILURE;
OR make the design work for all reasonable values of the generic, for example by making other quantities dependent on it in valid ways. For example:
constant DEPTH : natural := 2**WIDTH - 1;
signal random_num_i : natural range 0 to DEPTH;
and so on...

cross total of a std_logic_vector

My purpose of this code is a cross total of a std_logic_vector.
I have the following code:
generic(
lowPass_len : integer := 4;
...
signal inputbuffer : std_logic_vector(lowPass_len-1 downto 0);
signal sum: integer range 0 to lowPass_len;
signal lowpass_alarm_tog : std_logic;
...
inputbuffer <= inputbuffer(lowPass_len-1 downto 1) & alarm_tog_d2_meta;
for i in (lowPass_len-1) downto 1 loop
sum <= to_integer(unsigned(inputbuffer(i-1)) + unsigned(inputbuffer(i)));
end loop;
because inputbuffer is a std_logic_vector, I wanted to cast it to unsigned to make the addition. then convert it to integer, as sum has this kind of type.
ghdl gives me the following mistake for two times in this line
conversion not allowed between not closely related types
The expression inputbuffer(i-1) just returns a single bit of type std_logic. This cannot be directly casted to unsigned because the latter is an array of std_logic.
You have to extend the single bit to a vector of the required length first. The length depends on the highest number which could be encountered in the addition.

VHDL: issues with adding and subtracting

What issues could I run into with this code? I was thinking that there could be an issue if the result from the addition is bigger than what 15 bits can represent (32767), or if I get a negative number in the subtraction.
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
use ieee.numeric_std.all;
entity test is
port( input: in std_logic_vector(14 downto 0);
sel : out boolean;
output: out std_logic_vector(14 downto 0));
end test;
architecture test of test is
constant first : integer := 1050;
constant second : integer := 33611;
begin
output <= input - first;
output <= input + second;
sel <= input < first;
end test;
The primary issue you have is that the design intent is not communicated so it is impossible to distinguish correct from incorrect results - in that sense, whatever it does must be right!
I differ from David's opinion in one respect : where he says "std_logic_vector is an unsigned representation" I suggest that std_logic_vector is neither signed nor unsigned; it is just a bag of bits. If it happens to follow unsigned rules, that's an accident of the set of libraries you have included.
Instead, I would delete the non-standard libraries:
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
and use exclusively the standard libraries:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
Then - if the input and output ports are meant to represent unsigned numbers, the best thing to do is say so...
port( input : in unsigned(14 downto 0);
sel : out boolean;
output : out unsigned(14 downto 0));
(If you are not allowed to change the port types, you can use unsigned signals internally, and type convert between them and the ports.)
Now as regards the expressions, they may overflow (and in the case of "second" obviously will!).
In simulation, these overflows OUGHT to be reported as arithmetic errors. (Note : at least one simulator runs with overflow checks off as the default setting! Just dumb...)
As the designer, you decide what the correct semantics for overflows are:
They represent bugs. Simulate with overflow checks enabled, detect and fix the bugs.
They are permitted, and e.g. negative numbers represent large positive numbers. Express this in the code, e.g. as output <= (input - first) mod 2**output'length; Now anyone reading the code understands that overflow is allowed, and simply wraps.
Overflow should saturate to the positive or negative limit. Signal this by writing output <= saturate(input - first); I'll leave writing the Saturate function as an exercise...
The adding operators "+" and "-" are performed bit wise - std_logic_vector is an array type with a base element type of std_ulogic which represents 'bits' as a multi level value system that includes meta values. Their result is bounded by the longer of the two operands. (They don't overflow).
See the source for package std_logic_unsigned:
function "+"(L: STD_LOGIC_VECTOR; R: STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is
-- pragma label_applies_to plus
constant length: INTEGER := maximum(L'length, R'length);
variable result : STD_LOGIC_VECTOR (length-1 downto 0);
begin
result := UNSIGNED(L) + UNSIGNED(R);-- pragma label plus
return std_logic_vector(result);
end;
Which uses the unsigned add from std_logic_arith:
function "+"(L: UNSIGNED; R: UNSIGNED) return UNSIGNED is
-- pragma label_applies_to plus
-- synopsys subpgm_id 236
constant length: INTEGER := max(L'length, R'length);
begin
return unsigned_plus(CONV_UNSIGNED(L, length),
CONV_UNSIGNED(R, length)); -- pragma label plus
end;
An this uses unsigned_plus also found in std_logic_arith:
function unsigned_plus(A, B: UNSIGNED) return UNSIGNED is
variable carry: STD_ULOGIC;
variable BV, sum: UNSIGNED (A'left downto 0);
-- pragma map_to_operator ADD_UNS_OP
-- pragma type_function LEFT_UNSIGNED_ARG
-- pragma return_port_name Z
begin
if (A(A'left) = 'X' or B(B'left) = 'X') then
sum := (others => 'X');
return(sum);
end if;
carry := '0';
BV := B;
for i in 0 to A'left loop
sum(i) := A(i) xor BV(i) xor carry;
carry := (A(i) and BV(i)) or
(A(i) and carry) or
(carry and BV(i));
end loop;
return sum;
end;
std_logic_vector is an unsigned representation, there is no concept of negative numbers, it's a bag of bits. If you want to signify signed operations you should be using package numeric_std, and either type convert or use operands for your relational and adding operators that are type signed.
That being said you'll get the same answers using std_logic_vector with Synopsys's std_logic_unsigned package or unsigned with the IEEE numeric_std package.
(And your last two use clauses aren't needed by the code you show).
And the reason you don't need a use clause making packages numeric_std or std_logic_arith visible is because you aren't using signed or unsigned types and package std_logic_unsigned has it's own use clause for std_logic_arith and otherwise has declarations for everything you're using in your design specification ("+", "-" and "<").

Cannot resolve slice name as type std.standard.integer

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?

Resources