1 |
2 |
poppy |
------------------------------------------------------------------------------------
|
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 |
5 |
poppy |
-- it under the terms of the GNU Lesser General Public License as published by --
|
12 |
|
|
-- the Free Software Foundation; either version 2.1 of the License, or --
|
13 |
2 |
poppy |
-- (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 |
5 |
poppy |
-- GNU Lesser General Public License for more details. --
|
19 |
2 |
poppy |
-- --
|
20 |
5 |
poppy |
-- You should have received a copy of the GNU Lesser General Public License --
|
21 |
2 |
poppy |
-- 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 alu 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 |
|
|
|
67 |
|
|
res : out bus32; -- The result is 32 bit long
|
68 |
|
|
overflow : out bus1 -- Overflow of the result
|
69 |
|
|
);
|
70 |
|
|
end alu;
|
71 |
|
|
|
72 |
|
|
|
73 |
|
|
architecture rtl of alu is
|
74 |
|
|
|
75 |
|
|
-- Signals to pre-process the operands
|
76 |
|
|
signal efct_op1, efct_op2 : bus33; -- Effective operands of the adder (33 bits)
|
77 |
|
|
signal comp_op2 : bus1; -- Select the opposite of operand 2
|
78 |
|
|
signal igno_op2 : bus1; -- Ignore op 2 (put zeros)
|
79 |
|
|
signal sign_op1 : bus1; -- High bit of op 1
|
80 |
|
|
signal sign_op2 : bus1; -- High bit of op 2
|
81 |
|
|
signal signe : bus1; -- Signed operation (bit sign extension)
|
82 |
|
|
signal shift_val : natural range 0 to 31; -- Value of the shift
|
83 |
|
|
|
84 |
|
|
-- Signals for internal results
|
85 |
|
|
signal res_shl, res_shr : bus32; -- Results of left and right shifter
|
86 |
|
|
signal res_lui : bus32; -- Result of Load Upper Immediate
|
87 |
|
|
signal res_add : bus33; -- Result of the adder
|
88 |
|
|
signal carry : bus33; -- Carry for the adder
|
89 |
|
|
signal nul : bus1; -- Check if the adder result is zero
|
90 |
|
|
signal hilo : bus64; -- Internal registers to store the multiplication operation
|
91 |
|
|
signal tmp_hilo : bus64; -- Internal registers to store the multiplication operation (synchronised)
|
92 |
|
|
|
93 |
|
|
begin
|
94 |
|
|
|
95 |
|
|
-- Process if the operation is signed compliant
|
96 |
|
|
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)
|
97 |
|
|
else
|
98 |
|
|
'0';
|
99 |
|
|
|
100 |
|
|
sign_op1 <= signe and op1(31);
|
101 |
|
|
sign_op2 <= signe and op2(31);
|
102 |
|
|
|
103 |
|
|
-- Selection of the value of the second operand : op2 or -op2 (ie not op2 + 1)
|
104 |
|
|
comp_op2 <= '1' when -- The opposite of op2 is used
|
105 |
|
|
(ctrl=OP_SUB or ctrl=OP_SUBU) -- Opposite of the operand 2 to obtain a substraction
|
106 |
|
|
or (ctrl=OP_SLT or ctrl=OP_SLTU) -- Process the difference to check the lesser than operation for the operands
|
107 |
|
|
or (ctrl=OP_EQU or ctrl=OP_NEQU) -- Process the difference to check the equality of the operands
|
108 |
|
|
else
|
109 |
|
|
'0'; -- by default, op2 is used
|
110 |
|
|
|
111 |
|
|
igno_op2 <= '1' when -- Op 2 will be zero (when comp_op2='0')
|
112 |
|
|
(ctrl=OP_SPOS or ctrl=OP_LNEG) -- Process if the op1 is nul with op1+0
|
113 |
|
|
else
|
114 |
|
|
'0';
|
115 |
|
|
|
116 |
|
|
-- Effective signals for the adder
|
117 |
|
|
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)
|
118 |
|
|
(others => '0') when (igno_op2='1') else -- Op2 is zero
|
119 |
|
|
(sign_op2 & op2); -- by default we use op2 (33 bits long)
|
120 |
|
|
|
121 |
|
|
efct_op1 <= sign_op1 & op1;
|
122 |
|
|
|
123 |
|
|
-- Execution of the addition
|
124 |
|
|
carry <= X"00000000" & comp_op2; -- Carry to one when -op2 is needed
|
125 |
|
|
res_add <= std_logic_vector(unsigned(efct_op1) + unsigned(efct_op2) + unsigned(carry));
|
126 |
|
|
|
127 |
|
|
nul <= '1' when (res_add(31 downto 0)=X"00000000") else '0'; -- Check the nullity of the result
|
128 |
|
|
|
129 |
|
|
-- Value of the shift for the programmable shifter
|
130 |
|
|
shift_val <= to_integer(unsigned(op1(4 downto 0)));
|
131 |
|
|
|
132 |
|
|
res_shl <= bus32(shift_left(unsigned(op2), shift_val));
|
133 |
|
|
res_shr <= not bus32(shift_right(unsigned(not op2) , shift_val)) when (ctrl=OP_SRA and op2(31)='1') else
|
134 |
|
|
bus32(shift_right(unsigned(op2), shift_val));
|
135 |
|
|
res_lui <= op2(15 downto 0) & X"0000";
|
136 |
|
|
|
137 |
|
|
-- Affectation of the hilo register if necessary
|
138 |
|
|
tmp_hilo <= std_logic_vector(signed(op1)*signed(op2)) when (ctrl=OP_MULT) else
|
139 |
|
|
std_logic_vector(unsigned(op1)*unsigned(op2)) when (ctrl=OP_MULTU) else
|
140 |
|
|
op1 & hilo(31 downto 0) when (ctrl=OP_MTHI) else
|
141 |
|
|
hilo(63 downto 32) & op1 when (ctrl=OP_MTLO) else
|
142 |
|
|
(others => '0');
|
143 |
|
|
|
144 |
|
|
-- Check the overflows
|
145 |
|
|
overflow <= '1' when ((ctrl=OP_ADD and op1(31)=efct_op2(31) and op1(31)/=res_add(31))
|
146 |
|
|
or (ctrl=OP_SUB and op1(31)/=op2(31) and op1(31)/=res_add(31))) else
|
147 |
|
|
'0'; -- Only ADD and SUB can overflow
|
148 |
|
|
|
149 |
|
|
-- Result affectation
|
150 |
|
|
res <=
|
151 |
|
|
-- Arithmetical operations
|
152 |
|
|
res_add(31 downto 0) when (ctrl=OP_ADD or ctrl=OP_ADDU or ctrl=OP_SUB or ctrl=OP_SUBU) else
|
153 |
|
|
-- Logical operations
|
154 |
|
|
op1 and op2 when (ctrl=OP_AND) else
|
155 |
|
|
op1 or op2 when (ctrl=OP_OR) else
|
156 |
|
|
op1 nor op2 when (ctrl=OP_NOR) else
|
157 |
|
|
op1 xor op2 when (ctrl=OP_XOR) else
|
158 |
|
|
-- Different tests : the result is one when the test is succesful
|
159 |
|
|
(0 => res_add(32), others=>'0') when (ctrl=OP_SLTU or ctrl=OP_SLT) else
|
160 |
|
|
(0 => nul, others=>'0') when (ctrl=OP_EQU) else
|
161 |
|
|
(0 => not nul, others=>'0') when (ctrl=OP_NEQU) else
|
162 |
|
|
(0 => op1(31), others=>'0') when (ctrl=OP_SNEG) else
|
163 |
|
|
(0 => not (op1(31) or nul), others=>'0') when (ctrl=OP_SPOS) else
|
164 |
|
|
(0 => (op1(31) or nul), others=>'0') when (ctrl=OP_LNEG) else
|
165 |
|
|
(0 => not op1(31), others=>'0') when (ctrl=OP_LPOS) else
|
166 |
|
|
-- Shifts
|
167 |
|
|
res_shl when (ctrl=OP_SLL) else
|
168 |
|
|
res_shr when (ctrl=OP_SRL or ctrl=OP_SRA) else
|
169 |
|
|
res_lui when (ctrl=OP_LUI) else
|
170 |
|
|
-- Internal registers
|
171 |
|
|
hilo(63 downto 32) when (ctrl=OP_MFHI) else
|
172 |
|
|
hilo(31 downto 0) when (ctrl=OP_MFLO or ctrl=OP_MULT or ctrl=OP_MULTU) else
|
173 |
|
|
op1 when (ctrl=OP_MTHI or ctrl=OP_MTLO) else
|
174 |
|
|
op2 when (ctrl=OP_OP2) else
|
175 |
|
|
-- Always true
|
176 |
|
|
X"00000001" when (ctrl=OP_OUI) else
|
177 |
|
|
-- Unknown operation or nul result desired
|
178 |
|
|
(others => '0');
|
179 |
|
|
|
180 |
|
|
-- Save the hilo register
|
181 |
|
|
process (clock)
|
182 |
|
|
begin
|
183 |
|
|
if clock = '1' and clock'event then
|
184 |
|
|
if reset = '1' then
|
185 |
|
|
hilo <= (others => '0');
|
186 |
|
|
elsif (ctrl = OP_MULT) or (ctrl = OP_MULTU) or (ctrl = OP_MTLO) or (ctrl = OP_MTHI) then
|
187 |
|
|
hilo <= tmp_hilo;
|
188 |
|
|
end if;
|
189 |
|
|
end if;
|
190 |
|
|
end process;
|
191 |
|
|
end rtl;
|