1 |
2 |
mcafruni |
--------------------------------------------------------------------------
|
2 |
|
|
-- --
|
3 |
|
|
-- --
|
4 |
|
|
-- miniMIPS Superscalar Processor : Arithmetical and logical unit --
|
5 |
|
|
-- based on miniMIPS Processor --
|
6 |
|
|
-- --
|
7 |
|
|
-- --
|
8 |
|
|
-- Author : Miguel Cafruni --
|
9 |
|
|
-- miguel_cafruni@hotmail.com --
|
10 |
|
|
-- December 2018 --
|
11 |
|
|
--------------------------------------------------------------------------
|
12 |
|
|
|
13 |
|
|
library IEEE;
|
14 |
|
|
use IEEE.std_logic_1164.all;
|
15 |
|
|
use IEEE.numeric_std.all;
|
16 |
|
|
|
17 |
|
|
library work;
|
18 |
|
|
use work.pack_mips.all;
|
19 |
|
|
|
20 |
|
|
entity alu is
|
21 |
|
|
port
|
22 |
|
|
(
|
23 |
|
|
clock : in bus1;
|
24 |
|
|
reset : in bus1;
|
25 |
|
|
op1 : in bus32; -- Operand 1
|
26 |
|
|
op2 : in bus32; -- Operand 2
|
27 |
|
|
ctrl : in alu_ctrl_type; -- Opearator control
|
28 |
|
|
hilo_p2 : in bus64;
|
29 |
|
|
hilo_p1p2 : out bus64;
|
30 |
|
|
res : out bus32; -- The result is 32 bit long
|
31 |
|
|
overflow : out bus1 -- Overflow of the result
|
32 |
|
|
);
|
33 |
|
|
end alu;
|
34 |
|
|
|
35 |
|
|
|
36 |
|
|
architecture rtl of alu is
|
37 |
|
|
|
38 |
|
|
-- Signals to pre-process the operands
|
39 |
|
|
signal efct_op1, efct_op2 : bus33; -- Effective operands of the adder (33 bits)
|
40 |
|
|
signal comp_op2 : bus1; -- Select the opposite of operand 2
|
41 |
|
|
signal igno_op2 : bus1; -- Ignore op 2 (put zeros)
|
42 |
|
|
signal sign_op1 : bus1; -- High bit of op 1
|
43 |
|
|
signal sign_op2 : bus1; -- High bit of op 2
|
44 |
|
|
signal signe : bus1; -- Signed operation (bit sign extension)
|
45 |
|
|
signal shift_val : natural range 0 to 31; -- Value of the shift
|
46 |
|
|
|
47 |
|
|
-- Signals for internal results
|
48 |
|
|
signal res_shl, res_shr : bus32; -- Results of left and right shifter
|
49 |
|
|
signal res_lui : bus32; -- Result of Load Upper Immediate
|
50 |
|
|
signal res_add : bus33; -- Result of the adder
|
51 |
|
|
signal res_mul : std_logic_vector(31 downto 0); -- Resultado da multiplicacao 25.05.18
|
52 |
|
|
signal carry : bus33; -- Carry for the adder
|
53 |
|
|
signal nul : bus1; -- Check if the adder result is zero
|
54 |
|
|
signal hilo : bus64; -- Internal registers to store the multiplication operation
|
55 |
|
|
signal tmp_hilo : bus64; -- Internal registers to store the multiplication operation (synchronised)
|
56 |
|
|
signal hilop2 : bus64; -- Internal registers to store the multiplication operation
|
57 |
|
|
signal i_mult : bus1;
|
58 |
|
|
|
59 |
|
|
begin
|
60 |
|
|
|
61 |
|
|
-- Process if the operation is signed compliant
|
62 |
|
|
signe <= '1' when (ctrl=OP_ADD or ctrl=OP_SUB or ctrl=OP_SLT or ctrl=OP_SNEG or ctrl=OP_SPOS or ctrl=OP_LNEG or ctrl=OP_LPOS)
|
63 |
|
|
else
|
64 |
|
|
'0';
|
65 |
|
|
|
66 |
|
|
sign_op1 <= signe and op1(31);
|
67 |
|
|
sign_op2 <= signe and op2(31);
|
68 |
|
|
|
69 |
|
|
-- Selection of the value of the second operand : op2 or -op2 (ie not op2 + 1)
|
70 |
|
|
comp_op2 <= '1' when -- The opposite of op2 is used
|
71 |
|
|
(ctrl=OP_SUB or ctrl=OP_SUBU) -- Opposite of the operand 2 to obtain a substraction
|
72 |
|
|
or (ctrl=OP_SLT or ctrl=OP_SLTU) -- Process the difference to check the lesser than operation for the operands
|
73 |
|
|
or (ctrl=OP_EQU or ctrl=OP_NEQU) -- Process the difference to check the equality of the operands
|
74 |
|
|
else
|
75 |
|
|
'0'; -- by default, op2 is used
|
76 |
|
|
|
77 |
|
|
igno_op2 <= '1' when -- Op 2 will be zero (when comp_op2='0')
|
78 |
|
|
(ctrl=OP_SPOS or ctrl=OP_LNEG) -- Process if the op1 is nul with op1+0
|
79 |
|
|
else
|
80 |
|
|
'0';
|
81 |
|
|
|
82 |
|
|
-- Effective signals for the adder
|
83 |
|
|
efct_op2 <= not (sign_op2 & op2) when (comp_op2='1') else -- We take the opposite of op2 to get -op2 (we will add 1 with the carry)
|
84 |
|
|
(others => '0') when (igno_op2='1') else -- Op2 is zero
|
85 |
|
|
(sign_op2 & op2); -- by default we use op2 (33 bits long)
|
86 |
|
|
|
87 |
|
|
efct_op1 <= sign_op1 & op1;
|
88 |
|
|
|
89 |
|
|
-- Execution of the addition
|
90 |
|
|
carry <= X"00000000" & comp_op2; -- Carry to one when -op2 is needed
|
91 |
|
|
res_add <= std_logic_vector(unsigned(efct_op1) + unsigned(efct_op2) + unsigned(carry)); -- Usado na instrucao BNE
|
92 |
|
|
res_mul <= std_logic_vector(signed(efct_op1(15 downto 0))*signed(efct_op2(15 downto 0))); -- new, operandos de 16 bits por hora!!!!
|
93 |
|
|
nul <= '1' when (res_add(31 downto 0)=X"00000000") else '0'; -- Check the nullity of the result
|
94 |
|
|
|
95 |
|
|
-- Value of the shift for the programmable shifter
|
96 |
|
|
shift_val <= to_integer(unsigned(op1(4 downto 0)));
|
97 |
|
|
|
98 |
|
|
res_shl <= bus32(shift_left(unsigned(op2), shift_val));
|
99 |
|
|
res_shr <= not bus32(shift_right(unsigned(not op2) , shift_val)) when (ctrl=OP_SRA and op2(31)='1') else
|
100 |
|
|
bus32(shift_right(unsigned(op2), shift_val));
|
101 |
|
|
res_lui <= op2(15 downto 0) & X"0000";
|
102 |
|
|
|
103 |
|
|
-- Affectation of the hilo register if necessary
|
104 |
|
|
tmp_hilo <= std_logic_vector(signed(op1)*signed(op2)) when (ctrl=OP_MULT) else
|
105 |
|
|
std_logic_vector(unsigned(op1)*unsigned(op2)) when (ctrl=OP_MULTU) else
|
106 |
|
|
op1 & hilo(31 downto 0) when (ctrl=OP_MTHI) else
|
107 |
|
|
hilo(63 downto 32) & op1 when (ctrl=OP_MTLO) else
|
108 |
|
|
(others => '0');
|
109 |
|
|
|
110 |
|
|
hilo_p1p2 <= tmp_hilo; -- saida do resultado completo assincrona 20-12-2018
|
111 |
|
|
|
112 |
|
|
-- Check the overflows
|
113 |
|
|
overflow <= '1' when ((ctrl=OP_ADD and op1(31)=efct_op2(31) and op1(31)/=res_add(31))
|
114 |
|
|
or (ctrl=OP_SUB and op1(31)/=op2(31) and op1(31)/=res_add(31))) else
|
115 |
|
|
'0'; -- Only ADD and SUB can overflow
|
116 |
|
|
|
117 |
|
|
-- Result affectation
|
118 |
|
|
res <=
|
119 |
|
|
-- Arithmetical operations
|
120 |
|
|
res_add(31 downto 0) when (ctrl=OP_ADD or ctrl=OP_ADDU or ctrl=OP_SUB or ctrl=OP_SUBU) else
|
121 |
|
|
res_mul(31 downto 0) when (ctrl=OP_MULT2) else -- Acrescentada por Miguel Cafruni. Operandos de modulos que facam com que o resultado correto do produto caiba nos 32 bits menos significativos
|
122 |
|
|
-- Logical operations
|
123 |
|
|
op1 and op2 when (ctrl=OP_AND) else
|
124 |
|
|
op1 or op2 when (ctrl=OP_OR) else
|
125 |
|
|
op1 nor op2 when (ctrl=OP_NOR) else
|
126 |
|
|
op1 xor op2 when (ctrl=OP_XOR) else
|
127 |
|
|
-- Different tests : the result is one when the test is succesful
|
128 |
|
|
(0 => res_add(32), others=>'0') when (ctrl=OP_SLTU or ctrl=OP_SLT) else
|
129 |
|
|
(0 => nul, others=>'0') when (ctrl=OP_EQU) else
|
130 |
|
|
(0 => not nul, others=>'0') when (ctrl=OP_NEQU) else
|
131 |
|
|
(0 => op1(31), others=>'0') when (ctrl=OP_SNEG) else
|
132 |
|
|
(0 => not (op1(31) or nul), others=>'0') when (ctrl=OP_SPOS) else
|
133 |
|
|
(0 => (op1(31) or nul), others=>'0') when (ctrl=OP_LNEG) else
|
134 |
|
|
(0 => not op1(31), others=>'0') when (ctrl=OP_LPOS) else
|
135 |
|
|
-- Shifts
|
136 |
|
|
res_shl when (ctrl=OP_SLL) else
|
137 |
|
|
res_shr when (ctrl=OP_SRL or ctrl=OP_SRA) else
|
138 |
|
|
res_lui when (ctrl=OP_LUI) else
|
139 |
|
|
-- Internal registers
|
140 |
|
|
hilo(63 downto 32) when (ctrl=OP_MFHI and i_mult='1') else
|
141 |
|
|
hilo(31 downto 0) when ((ctrl=OP_MFLO or ctrl=OP_MULT or ctrl=OP_MULTU) and i_mult='1') else
|
142 |
|
|
hilop2(63 downto 32) when (ctrl=OP_MFHI and i_mult='0') else
|
143 |
|
|
hilop2(31 downto 0) when (ctrl=OP_MFLO and i_mult='0') else
|
144 |
|
|
op1 when (ctrl=OP_MTHI or ctrl=OP_MTLO) else
|
145 |
|
|
op2 when (ctrl=OP_OP2) else -- dado para a instrucao SW salvar na RAM
|
146 |
|
|
-- Always true
|
147 |
|
|
X"00000001" when (ctrl=OP_OUI) else
|
148 |
|
|
-- Unknown operation or nul result desired
|
149 |
|
|
(others => '0');
|
150 |
|
|
|
151 |
|
|
-- Save the hilo register
|
152 |
|
|
process (clock)
|
153 |
|
|
begin
|
154 |
|
|
if rising_edge(clock) then
|
155 |
|
|
if reset = '1' then
|
156 |
|
|
hilo <= (others => '0');
|
157 |
|
|
i_mult <= '0';
|
158 |
|
|
elsif (ctrl = OP_MULT) or (ctrl = OP_MULTU) or (ctrl = OP_MTLO) or (ctrl = OP_MTHI) then
|
159 |
|
|
hilo <= tmp_hilo;
|
160 |
|
|
i_mult <= '1';
|
161 |
|
|
else
|
162 |
|
|
i_mult <= '0';
|
163 |
|
|
end if;
|
164 |
|
|
end if;
|
165 |
|
|
end process;
|
166 |
|
|
|
167 |
|
|
process (hilo_p2)
|
168 |
|
|
begin
|
169 |
|
|
hilop2 <= hilo_p2; -- salva entrada assincrona do resultado da multiplicacao feita no pipe 2
|
170 |
|
|
end process;
|
171 |
|
|
|
172 |
|
|
end rtl;
|