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:
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.
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:
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; |
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
Log in with Google account
No account? Register here.