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.
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, ...
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.
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.
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?
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;
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!