1 |
21 |
mcafruni |
------------------------------------------------------------------------------------
|
2 |
|
|
-- --
|
3 |
|
|
-- Copyright (c) 2004, Hangouet Samuel --
|
4 |
|
|
-- , Jan Sebastien --
|
5 |
|
|
-- , Mouton Louis-Marie --
|
6 |
|
|
-- , Schneider Olivier all rights reserved --
|
7 |
|
|
-- --
|
8 |
|
|
-- This file is part of miniMIPS. --
|
9 |
|
|
-- --
|
10 |
|
|
-- miniMIPS is free software; you can redistribute it and/or modify --
|
11 |
|
|
-- it under the terms of the GNU General Public License as published by --
|
12 |
|
|
-- the Free Software Foundation; either version 2 of the License, or --
|
13 |
|
|
-- (at your option) any later version. --
|
14 |
|
|
-- --
|
15 |
|
|
-- miniMIPS is distributed in the hope that it will be useful, --
|
16 |
|
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of --
|
17 |
|
|
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --
|
18 |
|
|
-- GNU General Public License for more details. --
|
19 |
|
|
-- --
|
20 |
|
|
-- You should have received a copy of the GNU General Public License --
|
21 |
|
|
-- along with miniMIPS; if not, write to the Free Software --
|
22 |
|
|
-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA --
|
23 |
|
|
-- --
|
24 |
|
|
------------------------------------------------------------------------------------
|
25 |
|
|
|
26 |
|
|
|
27 |
|
|
-- If you encountered any problem, please contact :
|
28 |
|
|
--
|
29 |
|
|
-- lmouton@enserg.fr
|
30 |
|
|
-- oschneid@enserg.fr
|
31 |
|
|
-- shangoue@enserg.fr
|
32 |
|
|
--
|
33 |
|
|
|
34 |
|
|
|
35 |
|
|
|
36 |
|
|
--------------------------------------------------------------------------
|
37 |
|
|
-- --
|
38 |
|
|
-- --
|
39 |
|
|
-- miniMIPS Processor : Arithmetical and logical unit --
|
40 |
|
|
-- --
|
41 |
|
|
-- --
|
42 |
|
|
-- --
|
43 |
|
|
-- Authors : Hangouet Samuel --
|
44 |
|
|
-- Jan Sébastien --
|
45 |
|
|
-- Mouton Louis-Marie --
|
46 |
|
|
-- Schneider Olivier --
|
47 |
|
|
-- --
|
48 |
|
|
-- june 2003 --
|
49 |
|
|
--------------------------------------------------------------------------
|
50 |
|
|
|
51 |
|
|
library IEEE;
|
52 |
|
|
use IEEE.std_logic_1164.all;
|
53 |
|
|
use IEEE.numeric_std.all;
|
54 |
|
|
|
55 |
|
|
library work;
|
56 |
|
|
use work.pack_mips.all;
|
57 |
|
|
|
58 |
|
|
entity alu2 is
|
59 |
|
|
port
|
60 |
|
|
(
|
61 |
|
|
clock : in bus1;
|
62 |
|
|
reset : in bus1;
|
63 |
|
|
op1 : in bus32; -- Operand 1
|
64 |
|
|
op2 : in bus32; -- Operand 2
|
65 |
|
|
ctrl : in alu_ctrl_type; -- Opearator control
|
66 |
|
|
hilo_p1 : in bus64;
|
67 |
|
|
hilo_p2p1 : out bus64;
|
68 |
|
|
res : out bus32; -- The result is 32 bit long
|
69 |
|
|
overflow : out bus1 -- Overflow of the result
|
70 |
|
|
);
|
71 |
|
|
end alu2;
|
72 |
|
|
|
73 |
|
|
|
74 |
|
|
architecture rtl of alu2 is
|
75 |
|
|
|
76 |
|
|
-- Signals to pre-process the operands
|
77 |
|
|
signal efct_op1, efct_op2 : bus33; -- Effective operands of the adder (33 bits)
|
78 |
|
|
signal comp_op2 : bus1; -- Select the opposite of operand 2
|
79 |
|
|
signal igno_op2 : bus1; -- Ignore op 2 (put zeros)
|
80 |
|
|
signal sign_op1 : bus1; -- High bit of op 1
|
81 |
|
|
signal sign_op2 : bus1; -- High bit of op 2
|
82 |
|
|
signal signe : bus1; -- Signed operation (bit sign extension)
|
83 |
|
|
signal shift_val : natural range 0 to 31; -- Value of the shift
|
84 |
|
|
|
85 |
|
|
-- Signals for internal results
|
86 |
|
|
signal res_shl, res_shr : bus32; -- Results of left and right shifter
|
87 |
|
|
signal res_lui : bus32; -- Result of Load Upper Immediate
|
88 |
|
|
signal res_add : bus33; -- Result of the adder
|
89 |
|
|
signal res_mul : std_logic_vector(31 downto 0); -- Resultado da multiplicacao 25.05.18
|
90 |
|
|
signal carry : bus33; -- Carry for the adder
|
91 |
|
|
signal nul : bus1; -- Check if the adder result is zero
|
92 |
|
|
signal hilo : bus64; -- Internal registers to store the multiplication operation
|
93 |
|
|
signal tmp_hilo : bus64; -- Internal registers to store the multiplication operation (synchronised)
|
94 |
|
|
signal hilop1 : bus64;
|
95 |
|
|
signal i_mult : bus1;
|
96 |
|
|
|
97 |
|
|
begin
|
98 |
|
|
|
99 |
|
|
-- Process if the operation is signed compliant
|
100 |
|
|
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)
|
101 |
|
|
else
|
102 |
|
|
'0';
|
103 |
|
|
|
104 |
|
|
sign_op1 <= signe and op1(31);
|
105 |
|
|
sign_op2 <= signe and op2(31);
|
106 |
|
|
|
107 |
|
|
-- Selection of the value of the second operand : op2 or -op2 (ie not op2 + 1)
|
108 |
|
|
comp_op2 <= '1' when -- The opposite of op2 is used
|
109 |
|
|
(ctrl=OP_SUB or ctrl=OP_SUBU) -- Opposite of the operand 2 to obtain a substraction
|
110 |
|
|
or (ctrl=OP_SLT or ctrl=OP_SLTU) -- Process the difference to check the lesser than operation for the operands
|
111 |
|
|
or (ctrl=OP_EQU or ctrl=OP_NEQU) -- Process the difference to check the equality of the operands
|
112 |
|
|
else
|
113 |
|
|
'0'; -- by default, op2 is used
|
114 |
|
|
|
115 |
|
|
igno_op2 <= '1' when -- Op 2 will be zero (when comp_op2='0')
|
116 |
|
|
(ctrl=OP_SPOS or ctrl=OP_LNEG) -- Process if the op1 is nul with op1+0
|
117 |
|
|
else
|
118 |
|
|
'0';
|
119 |
|
|
|
120 |
|
|
-- Effective signals for the adder
|
121 |
|
|
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)
|
122 |
|
|
(others => '0') when (igno_op2='1') else -- Op2 is zero
|
123 |
|
|
(sign_op2 & op2); -- by default we use op2 (33 bits long)
|
124 |
|
|
|
125 |
|
|
efct_op1 <= sign_op1 & op1;
|
126 |
|
|
|
127 |
|
|
-- Execution of the addition
|
128 |
|
|
carry <= X"00000000" & comp_op2; -- Carry to one when -op2 is needed
|
129 |
|
|
res_add <= std_logic_vector(unsigned(efct_op1) + unsigned(efct_op2) + unsigned(carry));
|
130 |
|
|
res_mul <= std_logic_vector(signed(efct_op1(15 downto 0))*signed(efct_op2(15 downto 0)));
|
131 |
|
|
nul <= '1' when (res_add(31 downto 0)=X"00000000") else '0'; -- Check the nullity of the result (se os registradores contiverem o mesmo valor o resultado é 1)
|
132 |
|
|
|
133 |
|
|
-- Value of the shift for the programmable shifter
|
134 |
|
|
shift_val <= to_integer(unsigned(op1(4 downto 0)));
|
135 |
|
|
|
136 |
|
|
res_shl <= bus32(shift_left(unsigned(op2), shift_val));
|
137 |
|
|
res_shr <= not bus32(shift_right(unsigned(not op2) , shift_val)) when (ctrl=OP_SRA and op2(31)='1') else
|
138 |
|
|
bus32(shift_right(unsigned(op2), shift_val));
|
139 |
|
|
res_lui <= op2(15 downto 0) & X"0000";
|
140 |
|
|
|
141 |
|
|
-- Affectation of the hilo register if necessary
|
142 |
|
|
tmp_hilo <= std_logic_vector(signed(op1)*signed(op2)) when (ctrl=OP_MULT) else
|
143 |
|
|
std_logic_vector(unsigned(op1)*unsigned(op2)) when (ctrl=OP_MULTU) else
|
144 |
|
|
op1 & hilo(31 downto 0) when (ctrl=OP_MTHI) else
|
145 |
|
|
hilo(63 downto 32) & op1 when (ctrl=OP_MTLO) else
|
146 |
|
|
(others => '0');
|
147 |
|
|
|
148 |
|
|
hilo_p2p1 <= tmp_hilo;
|
149 |
|
|
|
150 |
|
|
-- Check the overflows
|
151 |
|
|
overflow <= '1' when ((ctrl=OP_ADD and op1(31)=efct_op2(31) and op1(31)/=res_add(31))
|
152 |
|
|
or (ctrl=OP_SUB and op1(31)/=op2(31) and op1(31)/=res_add(31))) else
|
153 |
|
|
'0'; -- Only ADD and SUB can overflow
|
154 |
|
|
|
155 |
|
|
-- Result affectation
|
156 |
|
|
res <=
|
157 |
|
|
-- Arithmetical operations
|
158 |
|
|
res_add(31 downto 0) when (ctrl=OP_ADD or ctrl=OP_ADDU or ctrl=OP_SUB or ctrl=OP_SUBU) else
|
159 |
|
|
res_mul(31 downto 0) when (ctrl=OP_MULT2) else
|
160 |
|
|
-- Logical operations
|
161 |
|
|
op1 and op2 when (ctrl=OP_AND) else
|
162 |
|
|
op1 or op2 when (ctrl=OP_OR) else
|
163 |
|
|
op1 nor op2 when (ctrl=OP_NOR) else
|
164 |
|
|
op1 xor op2 when (ctrl=OP_XOR) else
|
165 |
|
|
-- Different tests : the result is one when the test is succesful
|
166 |
|
|
(0 => res_add(32), others=>'0') when (ctrl=OP_SLTU or ctrl=OP_SLT) else
|
167 |
|
|
(0 => nul, others=>'0') when (ctrl=OP_EQU) else
|
168 |
|
|
(0 => not nul, others=>'0') when (ctrl=OP_NEQU) else -- inverte o sinal nul, se nao sao iguais os valores dos registradores, entao o branch sera tomado
|
169 |
|
|
(0 => op1(31), others=>'0') when (ctrl=OP_SNEG) else
|
170 |
|
|
(0 => not (op1(31) or nul), others=>'0') when (ctrl=OP_SPOS) else
|
171 |
|
|
(0 => (op1(31) or nul), others=>'0') when (ctrl=OP_LNEG) else
|
172 |
|
|
(0 => not op1(31), others=>'0') when (ctrl=OP_LPOS) else
|
173 |
|
|
-- Shifts
|
174 |
|
|
res_shl when (ctrl=OP_SLL) else
|
175 |
|
|
res_shr when (ctrl=OP_SRL or ctrl=OP_SRA) else
|
176 |
|
|
res_lui when (ctrl=OP_LUI) else
|
177 |
|
|
-- Internal registers
|
178 |
|
|
hilo(63 downto 32) when (ctrl=OP_MFHI and i_mult='1') else
|
179 |
|
|
hilo(31 downto 0) when ((ctrl=OP_MFLO or ctrl=OP_MULT or ctrl=OP_MULTU) and i_mult='1') else
|
180 |
|
|
hilop1(63 downto 32) when (ctrl=OP_MFHI and i_mult='0') else
|
181 |
|
|
hilop1(31 downto 0) when (ctrl=OP_MFLO and i_mult='0') else -- veio do pipe 1 20-12-2018 or ctrl=OP_MULT or ctrl=OP_MULTU
|
182 |
|
|
op1 when (ctrl=OP_MTHI or ctrl=OP_MTLO) else
|
183 |
|
|
op2 when (ctrl=OP_OP2) else
|
184 |
|
|
-- Always true
|
185 |
|
|
X"00000001" when (ctrl=OP_OUI) else -- J (jump)
|
186 |
|
|
-- Unknown operation or nul result desired
|
187 |
|
|
(others => '0');
|
188 |
|
|
|
189 |
|
|
-- Save the hilo register
|
190 |
|
|
process (clock)
|
191 |
|
|
begin
|
192 |
|
|
if rising_edge(clock) then
|
193 |
|
|
if reset = '1' then
|
194 |
|
|
hilo <= (others => '0');
|
195 |
|
|
i_mult <= '0';
|
196 |
|
|
elsif (ctrl = OP_MULT) or (ctrl = OP_MULTU) or (ctrl = OP_MTLO) or (ctrl = OP_MTHI) then
|
197 |
|
|
hilo <= tmp_hilo;
|
198 |
|
|
i_mult <= '1';
|
199 |
|
|
else
|
200 |
|
|
i_mult <= '0';
|
201 |
|
|
end if;
|
202 |
|
|
end if;
|
203 |
|
|
end process;
|
204 |
|
|
|
205 |
|
|
process (hilo_p1)
|
206 |
|
|
begin
|
207 |
|
|
hilop1 <= hilo_p1; -- salva entrada assincrona do resultado da multiplicacao feita no pipe 1 20-12-2018
|
208 |
|
|
end process;
|
209 |
|
|
|
210 |
|
|
end rtl;
|