ghdl / ghdl

VHDL 2008/93/87 simulator
GNU General Public License v2.0
2.35k stars 362 forks source link

Synth error 'multiple assignments for offsets' #1031

Open troubas opened 4 years ago

troubas commented 4 years ago

Description I believe that I never assign the same range multiple times. However when I try to synthesize (simulation is working as expected) i get the following errors:

barrel_shifter_rotator.vhd:53:12:error: multiple assignments for offsets 24:31
barrel_shifter_rotator.vhd:53:12:error: multiple assignments for offsets 24:39

Expected behaviour Working synthesis.

How to reproduce? Try to synthesize the following code:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.math_real.all;

-------------------------------------------------------------------------------

entity barrel_shifter_rotator is

  generic (
    -- word width
    NBITS : positive := 8);

  port (
    -- direction ('0': left, '1': right)
    dir    : in  std_logic;
    -- command (NOP, logic shift, arith. shift, rotate)
    cmd    : in  std_logic_vector(1 downto 0);
    -- data in, shift distance
    din, d : in  std_logic_vector(NBITS-1 downto 0);
    -- data out
    dout   : out std_logic_vector(NBITS-1 downto 0));

end entity barrel_shifter_rotator;

-------------------------------------------------------------------------------

architecture dfl of barrel_shifter_rotator is
    constant nshift : natural := natural(log2(real(NBITS)));

    -- custom vector for the shift stages
    type my_vec is array(0 to nshift) of std_logic_vector(NBITS-1 downto 0);
    signal vector : my_vec;
    -- vector of zeros
    constant ZEROS : std_logic_vector(NBITS-1 downto 0) := (others => '0');
    -- vector of ones (arithmetic shift)
    constant ONES  : std_logic_vector(NBITS-1 downto 0) := (others => '1');

begin  -- architecture dfl
    gen: for i in 0 to nshift-1 generate
        -- Op consists of a single operation
        op: process(dir, cmd, din, d, vector)
        begin
            vector(0) <= din;

            -- left shift
            if dir = '0' then
                -- arithmetic and logical shift is the same operation
                if cmd = "01" or cmd = "10" then
                    if d(i) = '1' then
                        vector(i+1) <= vector(i)(NBITS-1-2**i downto 0)
                                       & ZEROS(2**i-1 downto 0);
                    else
                        vector(i+1) <= vector(i);
                    end if;
                -- rotate left
                elsif cmd = "11" then
                    if d(i) = '1' then
                        vector(i+1) <= vector(i)(NBITS-1-2**i downto 0)
                                       & vector(i)(NBITS-1 downto NBITS-2**i);
                    else
                        vector(i+1) <= vector(i);
                    end if;
                else
                    vector(i+1) <= din;
                end if;
            -- right shift
            else
                -- logical
                if cmd = "01" then
                    if d(i) = '1' then
                        vector(i+1) <= ZEROS(2**i-1 downto 0)
                                       & vector(i)(NBITS-1 downto 2**i);
                    else
                        vector(i+1) <= vector(i);
                    end if;
                -- arithmetic
                elsif cmd = "10" then
                    if d(i) = '1' then
                        if vector(i)(NBITS-1) = '1' then
                            vector(i+1) <= ONES(2**i-1 downto 0)
                                           & vector(i)(NBITS-1 downto 2**i);
                        else
                            vector(i+1) <= ZEROS(2**i-1 downto 0)
                                           & vector(i)(NBITS-1 downto 2**i);
                        end if;
                    else
                        vector(i+1) <= vector(i);
                    end if;
                -- rotate right
                elsif cmd = "11" then
                    vector(i+1) <= vector(i)(2**i-1 downto 0)
                                   & vector(i)(NBITS-1 downto 2**i);
                else
                    vector(i+1) <= din;
                end if;
            end if;
        end process op;
    end generate gen;

    dout <= vector(nshift);
end architecture dfl;

Context Please, provide the following information:

Xiretza commented 4 years ago

There is indeed a multiple assignment, line 44 (assigning to vector(0)) needs to be moved outside the generate block, otherwise those elements are actually assigned from multiple processes. The error message leaves a lot to be desired though: for one, it uses the indices of the flattened array (vector(0) becomes vector(31 downto 24)), but for some reason it also reports a second error for indices 24 to 39: this doesn't make much sense, since the flattened vector is only 32 bits wide. Not sure what's going on there.

troubas commented 4 years ago

Ah of course! Thanks for the hint! Should I close the ticket ?

tgingold commented 4 years ago

Clearly the error message could be improved...