EmbDev.net

Forum: FPGA, VHDL & Verilog width mismatch in assignment error for barrel shifter


von Jason (Guest)


Attached files:

Rate this post
useful
not useful
I am learning FPGA prototyping by VHDL examples by myself. Currently I 
encountered an error when I ran synthesis on the attached vhdl file.

The error shows shows "width mismatch in assignment; target has 8 bits, 
source has 16 bits on line 57". Line 57 is listed as follows:
b <= a(shiftAmt-1 downto 0) & a(2**WIDTH - 1 downto shiftAmt);

shiftAmt was defined on line 47 as:
signal shiftAmt : integer := to_integer(unsigned(amt));

Can anyone tell me what causes the error and how I can fix it? Thanks.

von FPGAzumSpass (Guest)


Rate this post
useful
not useful
You are assigning amt to shiftAmt only at signal declaration, but amt is 
coming from a port, so that will not work.

Instead define the signal as:
signal shiftAmt : integer;

and add this assignment to the architecture:
shiftAmt <= to_integer(unsigned(amt));


I haven't tried synthesis with it, but at least modelsim works with it.

In any case, you should consider using the build in shifting functions 
like sll, srl, shift_right, ror, ...

von Jason (Guest)


Attached files:

Rate this post
useful
not useful
Thank you so much for your swift reply. I am beginner for both VHDL and 
FPGA. The barrel shifter is a project in the textbook. I tried your way, 
but the width mismatch error still exists. I attached the modified file. 
Is it possible a Vivado error instead of VHDL error? Thanks.

von FPGAzumSpass (Guest)


Rate this post
useful
not useful
You are right, as the assignment is not constant, synthesis may not 
recognize that it needs to build a multiplexer there. Quartus does also 
not like it, so it's not just Vivado.

Here is a possible solution using a process:
1
process (a, shiftAmt)
2
begin
3
  b <= (others => '0'); -- to prevent latches from bein built
4
  for i in 0 to 2**WIDTH - 1 loop
5
    if (shiftAmt = i) then
6
      b <= a(i-1 downto 0) & a(2**WIDTH - 1 downto i);
7
    end if;
8
  end loop;
9
end process;

This implements the multiplexer required by choosing based on the 
shiftwidth.


Another possibility would be something like that:
1
gshift: for i in 0 to 2**WIDTH - 1 generate
2
begin
3
   b(i) <= a(2**WIDTH - 1 - shiftAmt) when ((shiftAmt + i) > (2**WIDTH - 1)) 
4
   else a(shiftAmt + i);
5
end generate;

Which does exactly the same by assigning the correct source bit to the 
target bit.
Not sure if the correct bit is picked, was just a short test if it 
builds.


I still would just write like that:
1
b  <= std_logic_vector(unsigned(a) ror shiftAmt);


As it's easiest to read and hard to build an error into it.

All 3 variantes require exact same amount of ressources.

von Jason (Guest)


Rate this post
useful
not useful
Thanks again. I tried all three solutions. Both solution 1 and 3 works 
well. But I had trouble to run the simulation for solution 2. It seems 
the simulation error is also related with shiftAmt in the index of an 
array. I applied the method in your solution 1 to modify the solution 2 
and the error was gone. I listed the codes as follows:

-- solution 2:
shiftAmt<= to_integer(unsigned(amt));
process(a, shiftAmt)
begin
    b <= (others => '0'); -- to prevent latches from bein built
    for i in 0 to 2**WIDTH-1 loop
        if (shiftAmt = i) then
            for j in 0 to 2**WIDTH - 1 loop
               if j < ( 2**WIDTH - shiftAmt) then
                b(j) <= a(shiftAmt + j);
               else
                b(j) <=a(j - 2**Width + shiftAmt);
               end if;
            end loop;
        end if;
    end loop;
end process;


Now I am still confused when the error will happen. It seems no variable 
is allowed in the index of an array. But index i is also a variable, 
right?

von FPGAzumSpass (Guest)


Attached files:

Rate this post
useful
not useful
Sorry to not made this clear:

Solution 2 is to be used outside of a process.
Solution 3 can be used inside and outside of a process.


Solution 2:
1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
use IEEE.numeric_std.all;
4
5
entity barrel_shifter is
6
   generic (WIDTH: integer := 3);
7
   Port (
8
    a : in std_logic_vector(2**WIDTH - 1 downto 0);
9
    amt : in std_logic_vector (WIDTH-1 downto 0) := (others => '0');
10
    b : out std_logic_vector( 2**WIDTH - 1 downto 0)
11
    --b: out integer
12
    );
13
end barrel_shifter;
14
15
architecture Behavioral of barrel_shifter is
16
17
    signal shiftAmt : integer := 0;
18
   
19
begin
20
21
   shiftAmt <= to_integer(unsigned(amt));
22
23
   gshift: for i in 0 to 2**WIDTH - 1 generate
24
   begin
25
      b(i) <= a(2**WIDTH - 2 - i + shiftAmt) when ((shiftAmt + i) > (2**WIDTH - 1)) 
26
      else a(shiftAmt + i);
27
   end generate;
28
                    
29
end Behavioral;

It's still working in sythesis (sorry, only tried quartus as i don't 
have Vivado installed) and modelsim with this simple testbench:
1
library IEEE;
2
use IEEE.std_logic_1164.all;  
3
use IEEE.numeric_std.all;     
4
5
entity tb is
6
end tb;
7
8
architecture Behavioral of tb is
9
begin
10
11
   dut: entity work.barrel_shifter 
12
   port map
13
   (
14
      a   => "00000111",    
15
      amt => "010",
16
      b   => open
17
   );
18
                    
19
end Behavioral;

von Jason (Guest)


Rate this post
useful
not useful
My fault. The simulation error happened because I didn't initialize 
shiftAmt to 0. Now it works well in Vivado too.

Thank you so much for your help. I am so lucky to find such a great 
mentor like you in the forum!

Please log in before posting. Registration is free and takes only a minute.
Existing account
Do you have a Google/GoogleMail account? No registration required!
Log in with Google account
No account? Register here.