cross total of a std_logic_vector - vhdl

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.

Related

VHDL shift_right number

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.

Combining `others` expression with `signed` cast

Let var stand for a signed vector (library IEEE.NUMERIC_STD.ALL) of size m.
Let foo be another variable of type std_logic_vector(n-1 downto 0), where n is smaller than m.
I want to concatenate a '0' left of foo, then pad it with zeroes in its right until it size is m and then store the result in var.
I tried
rdsor <= signed('0' & divisor & others=>'0');
But Xilinx complains with the following message on synthesis:
Syntax error near "others".
How do I do what I want?
Assuming rdsor is equivalent to your theoretical var and divisor equivalent to foo you could use two assignments in a process statement:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity jsevillamol is
end entity;
architecture fum of jsevillamol is
constant M: natural := 42;
constant N: natural := 23;
signal rdsor: signed (M - 1 downto 0);
signal divisor: std_logic_vector (N - 1 downto 0);
begin
-- rdsor <= signed('0' & divisor & others=>'0');
process (divisor)
begin
rdsor <= (others => '0');
rdsor (rdsor'LEFT downto rdsor'LEFT - divisor'LENGTH)
<= signed('0' & divisor);
end process;
end architecture;
This works because each element of rdsor is a separate signal and there is only one value for any particular time in a projected output waveform. By not providing an after time_expression in the waveform element of the second assignment the elements of rdsor slice will be assigned the second assignments expression values. (The elements of the first assignment are supplanted by the second). This method of overwriting the projected output waveform is commonly used in providing default values prior to incomplete condition coverage with if statements.
This example analyzes, elaborates and simulates, while doing nothing interesting it demonstrates index ranges are constructed properly.
Notice it avoids the issue of concatenation versus aggregation brought up by Matthew Taylor's answer.
For a single signal assignment in a method not sensitive to tool VHDL revision:
architecture fie of jsevillamol is
constant M: natural := 42;
constant N: natural := 23;
signal rdsor: signed (M - 1 downto 0);
signal divisor: std_logic_vector (N - 1 downto 0);
subtype other is signed (rdsor'LEFT - divisor'LENGTH - 1 downto 0);
begin
-- rdsor <= signed('0' & divisor & others=>'0');
rdsor <= '0' & signed(divisor) & other'(others => '0');
end architecture;
This uses concatenation and subsumes the others into an aggregate. There's a subtype declaration for the trailing '0's portion to allow the aggregate expression to be the target of a qualified expression.
This architecture also analyzes, elaborates and simulates proving index arithmetic is correct.
You would need to use others as part of an aggregate not part of a concatenation. Here's a solution using an aggregate and attributes (which relies on you using VHDL 2008):
rdsor <= (rdsor'LEFT => '0', (rdsor'LEFT-1) downto (rdsor'LEFT-divisor'LENGTH) => signed(divisor), others => '0');
https://www.edaplayground.com/x/5Yuw

How to typecast integer to unsigned in VHDL

I am trying to divide two integers as following:
variable m0Low : integer := 0;
variable m1Low : integer := 0;
m1Low := divide(m1Low,m0Low);
With the function :
function divide (a : UNSIGNED; b : UNSIGNED) return UNSIGNED is
variable a1 : unsigned(a'length-1 downto 0):=a;
variable b1 : unsigned(b'length-1 downto 0):=b;
variable p1 : unsigned(b'length downto 0):= (others => '0');
variable i : integer:=0;
begin
for i in 0 to b'length-1 loop
p1(b'length-1 downto 1) := p1(b'length-2 downto 0);
p1(0) := a1(a'length-1);
a1(a'length-1 downto 1) := a1(a'length-2 downto 0);
p1 := p1-b1;
if(p1(b'length-1) ='1') then
a1(0) :='0';
p1 := p1+b1;
else
a1(0) :='1';
end if;
end loop;
return a1;
end divide;
However, I get the following error:
Divide can not have such operands in this context.
I am trying to cast the variables to unsigned m1Low := divide(unsigned(m1Low),unsigned(m0Low));
But I get the following error:
The expression can not be converted to type unsigned.
Any idea what I can do?
Thanks
Haris
To convert integer to unsigned or signed data type over,
use IEEE.NUMERIC_STD.all;
you must use,
to_unsigned(I,U’length);
to_signed(I,S’length)
where I is the integer value and U'length is the unsigned vector length ( the number of bit ).
I didn't verify your code and how it's actually working but my correction on your code is just,
m1Low := to_integer(divide(to_unsigned(m1Low, N),to_unsigned(m0Low, N)));
you should specify N where its the length of your vector depend on your design. I used to_integer() because your function is returning unsigned value to integer variable.
Hope this simple notes help you.
If you want to pass integers as unsigned vectors, you need to convert them, not typecast them.
First you want the numeric_std library:
use ieee.numeric_std.all;
Then you can use to_unsigned to convert the integers to unsigned vectors. For that function you need to know the length of the unsigned vector you are converting to so use the 'length attribute:
destination_vector := to_unsigned(source_integer, destination_vector'length);
You can convert back from unsigned to integer (which doesn't need to be told the length of the input, as information about function inputs is directly available to the function) like this:
destination_integer := to_integer(source_vector);

I want to check if std_logic_vector contains negative integer

How can I check with if (...) then ... end if; construction if std_logic_vector variable holds the bits of a negative number? If it is negative, I have to assign it a zero value.
I have :
signal sum : std_logic_vector (15 downto 0);
sum<= (...);
if (...) then
sum<=x"00";
end if;
Thank you!
You cannot add two STD_LOGIC_VECTORs, because the language does not know anything about the arithmetic that it should perform. This is because, to the synthesis tool, every signal/port/variable that's declared as STD_LOGIC_VECTOR is nothing more than an array of STD_LOGIC, the multi-valued logic type. Arithmetic on such a type does not make sense.
If you want to use arithmetic on types whose interface is similar to the one exposed by STD_LOGIC_VECTOR, you should use SIGNED (for signed arithmetic) and UNSIGNED (for unsigned arithmetic) types defined in IEEE.NUMERIC_STD. In order to convert between these types, just cast them using the type names explicitly, like this :
std_logic_vector_variable := STD_LOGIC_VECTOR(unsigned_variable);
unsigned_variable := UNSIGNED(std_logic_vector_variable);
So, summing it all up - the signal sum should be declared as SIGNED, since you're obviously going to perform arithmetic on it. Then, you can freely use the comparison and arithmetic operations that you need. The resulting code should look more or less like this :
use IEEE.NUMERIC_STD.ALL;
-- entity and architecture declarations...
signal sum : SIGNED (15 downto 0);
-- inside some process...
if (sum <= 0) then sum <= 0; end if;
The quick and simple hack is to check if the most-significant-bit is 1, indicating a negative number:
result <= (others=>'0') when sum(sum'left)='1' else sum;
Or you can coerce the std_logic_vector into an appropriate type and see if it is negative:
result <= (others=>'0') when signed(sum) < 0 else sum;
Or inside of a process use an if statement instead of a selected signal assignment:
if signed(sum) < 0 then
result <= (others=>'0');
else
result <= sum;
end if;
signal sum : std_logic_vector (15 downto 0);
sum<= x"E8";
if (sum(15)='1') then
sum<=x"00";
end if;
Just check the MSB..
If MSB is 1, that means the number is negative else positive.

How to multiply by 2 a 32 bit signed std_logic_vector in VHDL

We have a type which is an array of 32 bit "std_logic_vector" of size 3, which is defined in the following way:
subtype scalar is std_logic_vector(31 downto 0);
type vector_nd is array (natural range <>) of scalar;
subtype vector_3d is vector_nd(2 downto 0);
We have a signal of type "vector_3d" which we want to multiply by 2 and put the result in a signal of type "scalar":
signal v_normal_out_sig := vector_3d;
signal mult1_in1_sig := scalar;
--...
mult1_in1_sig <= 2*signed(v_normal_out_sig(0)) when cau_state = st_cycle18;
When we compile it we get the error:
No feasible entries for infix operator "*".
What is the right way to implement what we want? We are using the following libraries:
ieee.std_logic_1164.all
ieee.std_logic_arith.all
ieee.std_logic_unsigned.all
What we did eventually is the fallowing:
mult1_in1_sig <= v_normal_out_sig(0)(31) & v_normal_out_sig(0)(29 downto 0) & '0' when cau_state = st_cycle18;
And test gave the right results for both positive and negative numbers.

Resources