width mismatch in assignment error for barrel shifter

Guest #6219459
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.
Attached files:
Guest #6219589
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, ...
Guest #6220186
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.
Guest #6220937
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?
Guest #6221195
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;
Attached files:
Guest #6222187
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!

Reply

Note: the original post is older than 6 months. Please don't ask any new questions in this thread, but start a new one.

Formatting
  • [c]C-Code[/c]
  • [vhdl]VHDL-Code[/vhdl]
  • [code]code in other languages, ASCII drawings[/code]
  • [math]formula (LaTeX syntax)[/math]
  • [[Title]] – link to an article
  • Link to another post: right-click its post ID (#8078628), copy the address, paste it into the text

More about formatting

Post long source code as an attachment, not in the text.

Already registered? Log in

Not shown to anyone. We send you a link; your post appears once you confirm it there.

By submitting you create a free account and accept the terms of use.