2

I am making a component which takes in input of 32 bits and a control input of 7 bits. What this component does is that it looks at last 2 bits of S and for

  • S = 00, it does logical shift left on inp
  • S = 01, it does logical shift right on inp
  • S = 10, it does arithmetic shift right on inp
  • S = 11, it does rotate right on inp

The amount/number of the shifts is decided by first 5 bits of S. For example if S=0001001,then input has to be logically shifted right by 2 places. Below is my code. The problem is coming in 'sra' where following error shows up:

found '0' definitions of operator "sra", cannot determine exact overloaded matching definition for "sra" My code is:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
use IEEE.NUMERIC_STD.ALL;

-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity barrelshifter is
port(
clk : in std_logic;
    inp : in unsigned (31 downto 0):= (others => '0'); 
    s : in unsigned (6 downto 0);
    outp : out unsigned (31 downto 0)
    );
end barrelshifter;

architecture Behavioral of barrelshifter is
  signal samt : unsigned (4 downto 0);
  signal stype : unsigned (1 downto 0);
  signal inp1 : unsigned (31 downto 0);
begin
  samt <= s(6 downto 2);
  stype <= s(1 downto 0);
  inp1 <= inp;

  process(clk)
  begin 
    if  stype = "00"  then 
      outp <= inp sll to_integer(samt);  
    end if;   
    if  stype = "01"  then
      outp <= inp srl to_integer(samt);
    end if; 
    if  stype = "10"  then
      outp <= inp sra to_integer(samt);
    end if; 
    if  stype = "11"  then
      outp <= inp ror to_integer(samt);
    end if; 
  end process;
end Behavioral;
Paebbels
  • 15,573
  • 13
  • 70
  • 139
Ankit Shubham
  • 2,989
  • 2
  • 36
  • 61

2 Answers2

4

First off, I recommend you use shift_left(), shift_right(), rotate_left(), and rotate_right() functions instead. There are known problems and portability issues with the shift operators between VHDL '87 and VHDL '08 (see here).

The "sra" operator is not defined for all types in numeric_std. You have to do some casting to get what you want. But better to use the shift_left and shift_right functions and be explicit.

Note also that the meaning of sra is the same as srl for an unsigned input. Why even define an sra operation in this case? Perhaps you wanted signed inputs?

If your inputs are signed, can choose between srl and sra by doing:

outp <= signed(shift_right(unsigned(inp), to_integer(samt))); -- srl
outp <= shift_right(inp, to_integer(samt)); --sra

(Edit: You are also missing your rising_edge() check in your process that does the shift.)

(Edit 2: You are probably better off using a case statement for selecting your shift operation. The if chain you have, while mutually exclusive, is not a typical coding style. Either use if/elsif/else or a case.)

PlayDough
  • 1,116
  • 8
  • 16
  • Thanks for pointing out that sra is the same as srl for an unsigned input. But for the moment if I view unsigned as signed,then what casting can I try? – Ankit Shubham Mar 15 '16 at 21:59
  • Both `signed` and `unsigned` are related as arrays of `std_logic` (same as `std_logic_vector`), hence they can be cast to each other. So, let's say you have `signed` inputs. I edited by answer above to show an example. – PlayDough Mar 15 '16 at 22:10
4

Your code can be used 'as is' in VHDL.

sra isn't defined in IEEE package numeric_std prior to -2008. Your code will analyze without error with a -2008 compliant VHDL implementation

Otherwise for prior version compliant implementations:

outp <= unsigned (to_stdlogicvector(to_bitvector(std_logic_vector(inp)) sra to_integer(samt)));

Because sra is predefined for type bit_vector and samt is type unsigned (with an equivalent binary value that has a natural range).

You're also missing a synthesis eligible RTL description of sequential logic - the unlabelled process having clk in it's sensitivity list.

Changing that and showing the above fix in a pre -2008 compliant VHDL implementation:

library ieee;
use ieee.std_logic_1164.all;

use ieee.numeric_std.all;

entity barrelshifter is
    port (
        clk:  in  std_logic;
        inp:  in  unsigned (31 downto 0):= (others => '0'); 
        s:    in  unsigned (6 downto 0);
        outp: out unsigned (31 downto 0)
    );
end entity barrelshifter;

architecture behavioral of barrelshifter is
    signal samt:   unsigned (4 downto 0);
    signal stype:  unsigned (1 downto 0);
    signal inp1:   unsigned (31 downto 0);
begin
    samt <= s(6 downto 2);
    stype <= s(1 downto 0);
    inp1 <= inp; 

UNLABELLED:    
    process(clk)
    begin 
        if rising_edge(clk) then
            if stype = "00" then 
                outp <= inp sll to_integer(samt);  
            end if;   
            if stype = "01" then
                outp <= inp srl to_integer(samt);
            end if; 
            if stype = "10" then
                outp <= unsigned (to_stdlogicvector(to_bitvector(std_logic_vector(inp)) sra to_integer(samt)));
            end if; 
            if stype = "11" then
                outp <= inp ror to_integer(samt);
            end if;
        end if; 
    end process;
end architecture behavioral;

Because the if statements with conditions depending on stype are mutually exclusive you could replace the inner if statements with a case statement or a single if statement with elsif alternative conditions. This would allow conditions after the first matching value of stype.

That would look like this:

architecture with_elsif of barrelshifter is
    signal samt:   unsigned (4 downto 0);
    signal stype:  unsigned (1 downto 0);
    signal inp1:   unsigned (31 downto 0);
begin
    samt <= s(6 downto 2);
    stype <= s(1 downto 0);
    inp1 <= inp; 

UNLABELLED:    
    process(clk)
    begin 
        if rising_edge(clk) then
            if stype = "00" then 
                outp <= inp sll to_integer(samt);  
            -- end if;
            elsif stype = "01" then
                outp <= inp srl to_integer(samt);
            -- end if;
            elsif stype = "10" then
                outp <= unsigned (to_stdlogicvector(to_bitvector(std_logic_vector(inp)) sra to_integer(samt)));
                -- end if; 
            elsif stype = "11" then
                outp <= inp ror to_integer(samt);
            end if;
        end if; 
    end process;
end architecture with_elsif;

or this:

architecture with_case of barrelshifter is
    signal samt:   unsigned (4 downto 0);
    signal stype:  unsigned (1 downto 0);
    signal inp1:   unsigned (31 downto 0);
begin
    samt <= s(6 downto 2);
    stype <= s(1 downto 0);
    inp1 <= inp; 

UNLABELLED:    
    process(clk)
    begin 
        if rising_edge(clk) then
            case stype is
                when "00" => 
                    outp <= inp sll to_integer(samt);  
                when "01" =>
                    outp <= inp srl to_integer(samt);
                when "10" => 
                    outp <= unsigned (to_stdlogicvector(to_bitvector(std_logic_vector(inp)) sra to_integer(samt)));
                when "11" =>
                    outp <= inp ror to_integer(samt);
                when others =>
            end case;
        end if; 
    end process;
end architecture with_case;

All these code samples analyze. The three architectures haven't been simulated and you're encouraged to do so to insure the operators do what you expect.

In general you should be using the shift_right, shift_left, rotate right and rotate left functions defined in package numeric_std as PlayDough notes.