EmbDev.net

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


von Jason (Guest)


Attached files:

Rate this post
0 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
0 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
0 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
0 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:
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
      b <= a(i-1 downto 0) & a(2**WIDTH - 1 downto i);
    end if;
  end loop;
end process;

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


Another possibility would be something like that:
gshift: for i in 0 to 2**WIDTH - 1 generate
begin
   b(i) <= a(2**WIDTH - 1 - shiftAmt) when ((shiftAmt + i) > (2**WIDTH - 1)) 
   else a(shiftAmt + i);
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:
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
0 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
0 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:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.all;

entity barrel_shifter is
   generic (WIDTH: integer := 3);
   Port (
    a : in std_logic_vector(2**WIDTH - 1 downto 0);
    amt : in std_logic_vector (WIDTH-1 downto 0) := (others => '0');
    b : out std_logic_vector( 2**WIDTH - 1 downto 0)
    --b: out integer
    );
end barrel_shifter;

architecture Behavioral of barrel_shifter is

    signal shiftAmt : integer := 0;
   
begin

   shiftAmt <= to_integer(unsigned(amt));

   gshift: for i in 0 to 2**WIDTH - 1 generate
   begin
      b(i) <= a(2**WIDTH - 2 - i + shiftAmt) when ((shiftAmt + i) > (2**WIDTH - 1)) 
      else a(shiftAmt + i);
   end generate;
                    
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:
library IEEE;
use IEEE.std_logic_1164.all;  
use IEEE.numeric_std.all;     

entity tb is
end tb;

architecture Behavioral of tb is
begin

   dut: entity work.barrel_shifter 
   port map
   (
      a   => "00000111",    
      amt => "010",
      b   => open
   );
                    
end Behavioral;

von Jason (Guest)


Rate this post
0 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

Entering an e-mail address is optional. If you want to receive reply notifications by e-mail, please log in.

Rules — please read before posting

  • Post long source code as attachment, not in the text
  • Posting advertisements is forbidden.

Formatting options

  • [c]C code[/c]
  • [avrasm]AVR assembler code[/avrasm]
  • [vhdl]VHDL code[/vhdl]
  • [code]code in other languages, ASCII drawings[/code]
  • [math]formula (LaTeX syntax)[/math]




Bild automatisch verkleinern, falls nötig
Note: the original post is older than 6 months. Please don't ask any new questions in this thread, but start a new one.