VHDL err: 10028: Can't resolve multiple constant drivers for net - vhdl

I have a code like this:
signal IndexA_1 : std_logic_vector(31 downto 0);
signal IndexA_2 : std_logic_vector(31 downto 0);
type Register_array_type is array (0 to 255) of
std_logic_vector(63 downto 0);
signal RegArray : Register_array_type;
IndexA_1 <= data_in1;
IndexA_2 <= data_in2;
RegArray(1) <= x"00000000_0000000b";
RegArray(2) <= x"00000000_0000000c";
RegArray(3) <= x"00000000_0000000d";
RegArray(4) <= x"00000000_0000000e";
RegArray(5) <= x"00000000_0000000f";
RegArray(to_integer(unsigned(IndexA_1(7 downto 0)))) <= Rx_data_1 ;
RegArray(to_integer(unsigned(IndexA_2(7 downto 0)))) <= Rx_data_2 ;
So for example I want to assign part of the RegArray to some fixed value and the other part of the array get the data from Rx_data_x. So in the code, I know that IndexA_1 will not have the index overlapped with the fixed ones (in the code it will never be 1,2,3,4,or 5). But I got an multiple drivers error (Because Quartus thinks IndexA_1&2 may overlap with 1,2,3,4,5). Any idea how to code for this can avoid the err?
Thanks!

Related

VHDL: Combining multiplication and slicing into one line

I have a hardware accelerated function that requires two instances of fixed point multiplication. My current solution (example below) requires two clock cycles per multiplication; one step of multiplication, followed by a second step where that value is sliced back to the original input word size. I would like this to take as few cycles as necessary for latency.
Here is my current solution:
signal a : std_logic_vector(7 downto 0);
signal b : std_logic_vector(7 downto 0);
signal y : std_logic_vector(7 downto 0);
signal product : std_logic_vector(15 downto 0);
MULTIPLY_PROCESS : process(clk)
begin
if(rising_edge(clk)) then
product <= std_logic_vector(unsigned(a) * unsigned(b));
y <= product(11 downto 4); --takes one additional clock cycle
end if; --for y to appear
end process;
It makes sense to me that this could be shrunk down to one clock cycle, as normal unsigned multiplication does this automatically by throwing out the top end of the oversized vector.
example:
signal a : std_logic_vector(7 downto 0);
signal b : std_logic_vector(7 downto 0);
signal y : std_logic_vector(7 downto 0);
MULTIPLY_PROCESS : process(clk)
begin
if(rising_edge(clk)) then
y <= std_logic_vector(unsigned(a) * unsigned(b)); --truncates automatically
end if;
end process;
This is code I thought would work, but throws a compiler error:
y <= std_logic_vector(unsigned(x) * unsigned(a))(11 downto 4)
Error: Prefix of slice name cannot be type conversion (STD_LOGIC_VECTOR) expression.
Is there some way to fixed-point multiply and truncate in a single line/step/clock cycle?
Credit to user1155120. Calling the multiplication through a function and then slicing the function before conversion does the trick.
y <= std_logic_vector("*"(unsigned(x), unsigned(a))(11 downto 4));

Width mismatch in assignment: VHDL

My code:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
library work;
use work.costanti.all;
entity Multiplier is
generic(nbA:integer:=nbA;
nbB:integer:=nbB);
port (
A: in STD_LOGIC_VECTOR(nbA-1 downto 0);
B: in STD_LOGIC_VECTOR(nbB-1 downto 0);
clk: in STD_LOGIC;
R: out STD_LOGIC_VECTOR(nbA+nbB-1 downto 0));
end Multiplier;
architecture Behavioral of Multiplier is
component AdderTree is
generic(nbit: integer:=nbA+nbB);
port (
IN1: in STD_LOGIC_VECTOR(nbit-1 downto 0);
IN2: in STD_LOGIC_VECTOR(nbit-1 downto 0);
IN3: in STD_LOGIC_VECTOR(nbit-1 downto 0);
IN4: in STD_LOGIC_VECTOR(nbit-1 downto 0);
IN5: in STD_LOGIC_VECTOR(nbit-1 downto 0);
IN6: in STD_LOGIC_VECTOR(nbit-1 downto 0);
IN7: in STD_LOGIC_VECTOR(nbit-1 downto 0);
IN8: in STD_LOGIC_VECTOR(nbit-1 downto 0);
IN9: in STD_LOGIC_VECTOR(nbit-1 downto 0);
S: out STD_LOGIC_VECTOR(nbit-1 downto 0)
);
end component;
signal V : STD_LOGIC_VECTOR(nbA-1 downto 0);
signal P : STD_LOGIC_VECTOR((nbA*nbB)-1 downto 0);
signal PP_0to6 : STD_LOGIC_VECTOR( (nbA)+(nbA+1)+(nbA+2)+(nbA+3)+(nbA+4)+(nbA+5)+(nbA+6)-1 downto 0); --(dim(pp0+PP1+PP2+PP3+PP4+PP5+PP6) downto 0 )
signal PP7 : STD_LOGIC_VECTOR(nbA+nbB-1 downto 0);
signal P7 : STD_LOGIC_VECTOR(nbA downto 0);
signal PPP : STD_LOGIC_VECTOR((nbA+nbB)*(nbB+1)-1 downto 0);
begin
for_g: for i in 0 to nbB-1 generate
V <= (others => B(i));
P((nbB)*(i)+(nbB-1) downto (nbB)*(i)) <= V and A;
end generate for_g;
P7 <= '0' & P((nbA*nbB)-1 downto (nbA*nbB)-1-(nbB-1));
PP_0to6(nbB-1 downto 0) <= P(nbB-1 downto 0); --PP0
for_g2: for i in 0 to nbB-3 generate
PP_0to6((nbB+1)*(i+1)+(i*(i+1)/2)+7 downto (nbB+1)*(i+1)+(i*(i+1)/2)) <= P(nbB*(i+1)+(nbB-1) downto nbB*(i+1)); --PP1 to PP6
PP_0to6((nbB+1)*(i+1)+(i*(i+1)/2)-1 downto (nbB+1)*(i)+((i-1)*(i)/2)+7+1) <= (others => '0');
end generate for_g2;
PP7(nbA+nbB-1 downto nbA-1) <= P7;
PP7(nbA-2 downto 0) <= (others => '0');
PPP_0to6: for i in 3 to nbB-2 generate
PPP(((i+1)*(nbA+nbB-1)+i)-(8-i) downto i*(nbA+nbB)) <= PP_0to6( (i+1)*(nbB-1)+((1/2)*((i*i)+(3*i))) downto i*(nbB)+(i-1)*i/2); --PP0 to PP6
PPP(((i+1)*(nbA+nbB-1)+i) downto ((i+1)*(nbA+nbB-1)+i)-(8-i)+1)<= (others => '0');
end generate PPP_0to6;
-- Fill last 32 bits of PPP
--Insert ADDER TREE
end Behavioral;
Portion of the error code: portion of code
PPP_0to6: for i in 0 to nbB-2 generate
PPP(((i+1)*(nbA+nbB-1)+i)-(8-i) downto i*(nbA+nbB)) <= PP_0to6( (i+1)*(nbB-1)+((1/2)*((i*i)+(3*i))) downto i*(nbB)+(i-1)*i/2); --PP0 to PP6
PPP(((i+1)*(nbA+nbB-1)+i) downto ((i+1)*(nbA+nbB-1)+i)-(8-i)+1)<= (others => '0');
end generate PPP_0to6;
Hi, I'm making a multiplier on vhdl, but on line 66 it reports me the following error:
if i=1: [Synth 8-690] width mismatch in assignment; target has 9 bits, source has 7 bits ["...Multiplier.vhd":66]
if i=2: [Synth 8-690] width mismatch in assignment; target has 10 bits, source has 5 bits ["...Multiplier.vhd":66]
if i=3: [Synth 8-690] width mismatch in assignment; target has 11 bits, source has 2 bits ["...Multiplier.vhd":66]
and so on..
I can't understand why, they seem to be the same size ..
my constant are:
nbA=8
nbB=8
and the signal P, PP_0to6 and PPP:
signal P : STD_LOGIC_VECTOR((nbA*nbB)-1 downto 0);
signal PP_0to6 : STD_LOGIC_VECTOR( (nbA)+(nbA+1)+(nbA+2)+(nbA+3)+(nbA+4)+(nbA+5)+(nbA+6)-1 downto 0);
signal PPP : STD_LOGIC_VECTOR((nbA+nbB)*(nbB+1)-1 downto 0);
N.B. I make sure to shift to the rigth by adding zeros as in the figure:
schema
The error is here:
PPP(((i+1)*(nbA+nbB-1)+i)-(8-i) downto i*(nbA+nbB)) <= PP_0to6( (i+1)*(nbB-1)+((1/2)*((i*i)+(3*i))) downto i*(nbB)+(i-1)*i/2);
but if I tried to replace the value of i:
i=0: PPP(7 downto 0) <= PP_0to6(7 downto 0);
i=1: PPP(24 downto 16)<=PP_0to6(16 downto 8)
i=2: PPP(41 downto 32)<=PP_0to6(26 downto 17)
i=3: PPP(58 downto 48)<=PP_0to6(37 downto 27)
...
...
the dimensions look the same.
I guess strictly speaking this answer doesn't really answer your question, since I'm not trying to figure out where your error is. But I'm convinced that if you change your coding style you won't encounter such difficult to debug errors any more.
As mentioned in my comments, your code will become must clearer and easier to debug if you split the signal up properly. I.e. don't create one giant signal for everything.
VHDL has arrays and records, use them, they won't make your circuit any larger, but the code will be much easier to reason about.
It's been a while since I actually wrote VHDL, so the syntax below might contain typo's, but hopefully the idea behind the code is clear:
constant c_AllZeros : std_logic_vector(c_MaxZeros - 1 downto 0) := (others => '0');
...
type t_P is std_logic_vector(c_SomeLength - 1 downto 0);
subtype t_P_Array is array (natural range <>) of t_P;
...
signal P : t_P_Array(0 to c_NumInputs - 1);
...
PPP_0to6: for i in PPP'range generate
PP(i) <= P(i) & c_AllZeros(index downto 0);
PPP(i) <= c_AllZeros(c_MaxZeros - index downto 0) & PP(i);
end generate PPP_0to6;
As you might notice, I also got rid of the explicit indices for the for-loop in the generate. There's still a magic number when indexing the all_zeroes signal to generate PPP. If I was writing this code, I'd replace that with some (calculated) constant with a meaningful name. This will make the code both more readable and trivial to change later on.
Note that there's other ways to do this. E.g. you could first set all bits of all PP signals to 0 and then assign a slice of them the P value.

how to make std_logic_vector consist of std_logic_vectorin vhdl

I have such signal:
sw : std_logic_vector(7 downto 0);
and now I want to make another one, which will have it as upper bits, 1 the rest:
std_logic_vector(31 downto 0) := (7 downto 0 => sw, others => '1');
but it won't compile. any help please? I don't want to do it bit by bit.
I'm not entirely sure where should go this smaller signal, but you probably want to do this:
signal sw: std_logic_vector(7 downto 0);
signal big: std_logic_vector(31 downto 0);
big <= sw & x"FFFFFF";
This will assign sw vector to 8 most significant bits of big vector, and '1' to rest of bits. Write in comments, if you want to do something else.
What you are trying to do is assign a signal -which is variable- to another signal during initialization. What do you expect to happen?
I.e. at the moment you define a signal, you can only initialize it. If you want to assign something to the signal, you have to write a declaration.
definition -> initialization
declaration -> assignment
So in this case you can define big a larger range, and fix the constant bits in initialization
signal big : std_logic_vector(31 downto 0) => (others => '1');
And when you want to assign sw to any part of big, do that after the begin.
big(31 downto 24) <= sw;
or
big(7 downto 0) <= sw;
etc. The bits you initialized as '1' will be overwritten by the assignment.

Use of conv_integer in VHDL

I am in the process of trying to write some code that will simply just shift a 32 bit vector left or right, with a 5 bit input that will be used for the shift amount (shamt). The issue I am having is trying to convert an std_logic_vector to an integer. My code is this:
library ieee;
use ieee.STD_LOGIC_1164.all;
use ieee.STD_LOGIC_ARITH.all;
entity shiftlogical is
port(x : in std_logic_vector(31 downto 0);
shamt : in std_logic_vector( 4 downto 0);
y : out std_logic_vector(31 downto 0));
end shiftlogical;
architecture beh of shiftlogical is
signal shift : integer;
signal temp : std_logic_vector(31 downto 0);
begin
shift <= conv_integer(unsigned(shamt));
temp <= x(shift downto 0);
y <= temp;
end beh;
The code is not complete I know, but to test some ideas I am trying to pass "00010" (2) into shamt, but shift comes out to be -2147483648. But I cannot figure out why it is doing this, nor can I find any resources online that shows anything different than what I am doing. I greatly appreciate any help.
-2147483648 (-2**31) is the default initial value for integers, being the leftmost, most negative value in its range. It suggests that the signal assignment to shift has not executed. Most likely because it is a continuous assignment and there hasn't been an event on shamt to cause it to update.
std_logic_arith is not an IEEE standard library. You should use to_integer() from ieee.numeric_std instead. It is also beneficial to keep numeric ports as unsigned or signed so that your intent is clear and to minimize type conversions. Also, you cannot directly assign the variable length slice of x to temp since their lengths do not match. You should use resize() (from numeric_std) to extend the length back to 32-bits or rethink your approach.
I fixed the obvious typo in the entity name, started the simulation (ModelSim) and forced the signal shamt to "00010". Then just after trying to run for 1 ps, ModelSim complains about:
Fatal: (vsim-3420) Array lengths do not match. Left is 32 (31 downto 0). Right is 0 (-2147483648 downto 0 (null array)).
Time: 0 ps Iteration: 0 Process: /shiftlogical/line__16 File: shiftlogical.vhdl
Fatal error in Architecture beh at shiftlogical.vhdl line 16
That is because all your concurrent statements are executed in parallel. The new signal values are scheduled for the next delta cycle within the simulation. Thus, the line
temp <= x(shift downto 0);
is executed with the old value of shift which is the initial value of this signal. The initial value of an integer is -2**31 as also Kevin pointed out.
Of course you can initialize the signal shift, but the only value which will not result in an error will be 31 because in this asignment the signal on the left and the expression on the right must match in array (std_logic_vector) size. The signal shamt must be forced to "11111" as well, so that shift keeps 31.
You cannot easily fix this, because for a left shift you must add zeros at the right (LSB) and for a right shift zeros or the sign at the left (MSB).
#Martin Zabel what I had really tested there was to see if shift would hold an integer value which it did until I tried to pass it in for temp <= x(shift downto 0); What I realized was that the signal needed to really be a variable to work as intended and as follows my code consists of:
library ieee;
use ieee.STD_LOGIC_1164.all;
use ieee.STD_LOGIC_ARITH.all;
entity shiftlogical is
port(x: in std_logic_vector(31 downto 0);
shamt: in std_logic_vector(4 downto 0);
dir: in std_logic;
y: out std_logic_vector(31 downto 0));
end shiftlogical;
architecture beh of shiftlogical is
begin
process(dir)
variable shift : integer;
begin
shift := conv_integer(unsigned(shamt));
if(dir = '0') then --Left shift
y(31 downto shift) <= x(31-shift downto 0);
y(shift downto 0) <= (others => '0');
elsif(dir = '1') then --Right shift
y(31-shift downto 0) <= x(31 downto shift);
y(31 downto 31-shift) <= (others => '0');
else --Always left shift
y(31 downto shift) <= x(31-shift downto 0);
y(shift downto 0) <= (others => '0');
end if;
end process;
end beh;

VHDL multiple std_logic_vector to one large std_logic_vector

I have four std_logic_vectors (15 downto 0) and want to stack them into a std_logic_vector (63 downt 0) so fare I have found one way of doing it but is it the correct way or is there a more optimal and correct way to do it?
signal slv16_1,slv16_2,slv16_3,slv16_4 : std_logic_vector(15 downto 0);
signal slv64 : std_logic_vector(63 downto 0);
slv64(15 downto 0) <= slv16_1;
slv64(31 downto 16) <= slv16_2;
slv64(47 downto 32) <= slv16_3;
slv64(63 downto 48) <= slv16_4;
An easy way to accomplish this is to use the concatenation operator &. It achieves the same thing you did above, but with less code required.
slv64 <= slv16_4 & slv16_3 & slv16_2 & slv16_1;
Since the source vectors have unique names, I don't see a way to automate this. What you might be able to try is to never use the 16-bit vectors, and instead use slices of the larger 64 bit vector. So instead of an assignment like this:
slv16_1 <= "0101110000111010";
Use
slv64(15 downto 0) <= "0101110000111010";
Or instead of an entity instantiation where you connect slv16_2 like this:
output_port => slv16_2,
Use
output_port => slv64(31 downto 16),
I would really need to see more of your code to understand what might work best, but my basic answer is 'use the larger vector in the first place'.
If you can't do this for some reason, an alternative would be to declare your 16-bit vectors as an array of arrays:
type slv16_array_type is array (integer range <>) of std_logic_vector(15 downto 0);
signal slv16_array : slv16_array_type(3 downto 0);
You could then assign to the elements like this:
slv16_array(0) <= "0101";
You could combine the elements of this type with a generate loop:
slv16_combine : for i in 0 to 3 generate
slv64((16*(i+1))-1 downto 16*i) <= slv16_array(i);
end generate;
VHDL guide says that this one should work:
slv64 <= (slv16_4, slv16_3, slv16_2, slv16_1);

Resources