2

so, I'm developing an ALU for MIPS architecture and I'm trying to make a shift left and a shift right so that the ALU can shift any amount of bits.

the Idea I had is to convert the shift value to an integer and select the piece of the entry that'll be on the result(the integer is stored in X) but Quartus doesn't accept a variable value, only constants.

What could I do to make this? (Cases are on lines "WHEN "1000" =>..." and "WHEN "1001" =>...")

Thanks.

PROCESS ( ALU_ctl, Ainput, Binput, X )
BEGIN
                -- Select ALU operation
    --ALU_output_mux <= X"00000000"; --padrao   
CASE ALU_ctl IS
    WHEN "1000" =>  ALU_output_mux(31 DOWNTO X) <= (Ainput( 31-X DOWNTO 0 ));
    WHEN "1001" =>  ALU_output_mux(31-X DOWNTO 0) <= (Ainput( 31 DOWNTO X ));
    WHEN OTHERS =>  ALU_output_mux  <= X"00000000";
END CASE;
END PROCESS;
Brian Carlton
  • 7,545
  • 5
  • 38
  • 47
Adriano
  • 389
  • 3
  • 11
  • Its been about 3 years since I worked with VHDL and even then it was on a Vortex 3 board. Don't you have to define wires, inputs and outputs or is my memory failing me? I assume Quartus is your IDE in my case I used something entirely different. – Security Hound Jun 22 '11 at 13:12

3 Answers3

3

If Quartus doesn't like it you have two choices:

  1. Write it some way that Quartus does like - you're trying to infer a barrel shifter, so you could write one out longhand and then instantiate that. Potentially expensive in time
  2. Get a different synthesizer that will accept it. Potentially expensive in money.
Martin Thompson
  • 16,395
  • 1
  • 38
  • 56
0

I have had issues with this in Quartus as well, although your code also has some implicit latches (you are not assigning all bits of the output in your two shift cases).

The work-around I use is to define an intermediate array with all the possible results, then select one of those results using your selector. In your case, something like the following:

subtype DWORD_T         is std_logic_vector( 31 downto 0);
type    DWORD_A         is array (natural range <>) of DWORD_T;
signal  shift_L         : DWORD_A(31 downto 0);
signal  shift_R         : DWORD_A(31 downto 0);
signal  zero            : DWORD_T;

...

zero <= (others=>'0');

process (Ainput)
begin    
    for index in Ainput'range loop
        shift_L(index) <= Ainput(31 - index downto 0) & zero(index - 1 downto 0);
        shift_R(index) <= zero(index - 1 downto 0) & Ainput(31 downto index);
    end loop;
end process;

ALR_output_mux <= shift_L(to_integer(X)) when ALU_ctl="1000", 
                  shift_R(to_integer(X)) when ALU_ctl="1001",
                  (others=>'0') when others;
Charles Steinkuehler
  • 3,335
  • 18
  • 12
0

You could work around this by using generate or for to create each shift/rotate level, or you can use the standard functions ({shift,rotate}_{left,right}) for shifting and rotating.

Yann Vernier
  • 15,414
  • 2
  • 28
  • 26