copyleft: gplv3 added and set repo to public
[calu.git] / cpu / src / alu_pkg.vhd
1 --   `Deep Thought', a softcore CPU implemented on a FPGA
2 --
3 --  Copyright (C) 2010 Markus Hofstaetter <markus.manrow@gmx.at>
4 --  Copyright (C) 2010 Martin Perner <e0725782@student.tuwien.ac.at>
5 --  Copyright (C) 2010 Stefan Rebernig <stefan.rebernig@gmail.com>
6 --  Copyright (C) 2010 Manfred Schwarz <e0725898@student.tuwien.ac.at>
7 --  Copyright (C) 2010 Bernhard Urban <lewurm@gmail.com>
8 --
9 --  This program is free software: you can redistribute it and/or modify
10 --  it under the terms of the GNU General Public License as published by
11 --  the Free Software Foundation, either version 3 of the License, or
12 --  (at your option) any later version.
13 --
14 --  This program is distributed in the hope that it will be useful,
15 --  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 --  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 --  GNU General Public License for more details.
18 --
19 --  You should have received a copy of the GNU General Public License
20 --  along with this program.  If not, see <http://www.gnu.org/licenses/>.
21
22 library IEEE;
23
24 use IEEE.std_logic_1164.all;
25 use IEEE.numeric_std.all;
26
27 use work.common_pkg.all;
28 use work.extension_pkg.all;
29 --use work.core_extension.all;
30
31
32 package alu_pkg is
33         
34         --type alu_interal_rec is record
35         --      
36         --end record alu_internal_rec;
37         
38         type alu_result_rec is record
39                 result : gp_register_t;
40                 result_addr : gp_addr_t;
41                 
42                 status : status_rec;
43
44                 alu_jump : std_logic;
45                 brpr : std_logic;
46                 reg_op : std_logic;
47                 mem_op  : std_logic;
48                 
49                 mem_en : std_logic;
50                 
51                 hw_op   : std_logic;
52                 byte_op : std_logic;
53                 sign_xt : std_logic;
54                 
55         end record alu_result_rec;
56         
57         constant SHIFT_WIDTH : integer := 5; --log2c(gp_register_t'length);
58         
59         constant COND_ZERO : condition_t := "0001";
60         constant COND_NZERO : condition_t := "0000";
61         constant COND_NOFLO : condition_t := "0010";
62         constant COND_OFLO : condition_t := "0011";
63         constant COND_NCARRY : condition_t := "0100";
64         constant COND_CARRY : condition_t := "0101";
65         constant COND_NSIGN : condition_t := "0110";
66         constant COND_SIGN : condition_t := "0111";
67         
68         constant COND_ABOVE : condition_t := "1000";
69         constant COND_BEQ: condition_t := "1001";
70         constant COND_GEQ : condition_t := "1010";
71         constant COND_LT : condition_t := "1011";
72         constant COND_GT : condition_t := "1100";
73         
74         constant COND_LEQ : condition_t := "1101";
75         constant COND_ALWAYS : condition_t := "1110";
76         constant COND_NEVER : condition_t := "1111";
77         
78         function add_oflo(l_neg, r_neg, res_neg : std_logic) return std_logic;
79         -- function addsub_op(left_operand, right_operand : gp_register_t; sub, addc : std_logic; alu_result : alu_result_rec) return alu_result_rec;
80         
81         -- function and_op(left_operand, right_operand : gp_register_t; alu_result : alu_result_rec) return alu_result_rec;
82         -- function or_op(left_operand, right_operand : gp_register_t; alu_result : alu_result_rec) return alu_result_rec;
83         -- function xor_op(left_operand, right_operand : gp_register_t; alu_result : alu_result_rec) return alu_result_rec;
84         
85         -- function shift_op(left_operand, right_operand : gp_register_t; arith,sleft,carry : std_logic ;alu_result : alu_result_rec) return alu_result_rec;
86         
87         component alu is
88         --some modules won't need all inputs
89         port(
90         --System inputs
91         
92                         clk : in std_logic;
93                         reset : in std_logic;
94         --operation inputs
95                         cond : in condition_t;
96                         op_group : in op_info_t;
97                         left_operand : in gp_register_t;
98                         right_operand : in gp_register_t;
99                         
100             displacement : in gp_register_t;
101                         prog_cnt    : in instr_addr_t;
102                         brpr        : in std_logic;
103                         
104                         op_detail : in op_opt_t;
105                         
106                         alu_state  : in alu_result_rec;
107                         pval            : in gp_register_t;
108                         pval_nxt   : in gp_register_t;
109                         
110                         alu_result : out alu_result_rec;
111             addr : out word_t; --memaddr
112             data : out gp_register_t; --mem data --ureg
113                         
114                         pinc : out std_logic;
115                         pwr_en : out std_logic;
116                         paddr : out paddr_t
117                 );
118         end component alu;
119         
120 end package alu_pkg;
121
122 package body alu_pkg is
123
124         function add_oflo(l_neg, r_neg , res_neg: std_logic) return std_logic is
125         begin
126                 return (l_neg AND r_neg AND not(res_neg)) OR 
127                                 (not(l_neg) AND not(r_neg) AND res_neg);
128         end function add_oflo;
129         
130         -- function addsub_op(left_operand, right_operand : gp_register_t; sub, addc : std_logic; alu_result : alu_result_rec) return alu_result_rec is
131                 -- variable alu_result_out : alu_result_rec;
132                 -- variable complement          : gp_register_t;
133                 -- variable carry_res           : unsigned(gp_register_t'length downto 0);
134                 -- variable tmp_right_operand : unsigned(gp_register_t'length downto 0);
135                 -- variable oflo1, oflo2, l_neg, r_neg : std_logic;
136                 -- variable addcarry            : unsigned(carry_res'range);
137         -- begin
138                 -- alu_result_out := alu_result;
139                 
140                 -- addcarry := (others =>'0');
141                 -- addcarry(0) := unsigned(alu_result.status.carry and addc);
142                 
143                 -- complement := inc(not(right_operand));
144                 -- l_neg := left_operand(gp_register_t'high);
145                 
146                 -- carry_res := unsigned('0' & left_operand)+addcarry;
147                 -- oflo1 := add_oflo(l_neg,'0',std_logic_vector(carry_res)(gp_register_t'high));
148                 
149                 -- if sub = '1' then
150                         -- tmp_right_operand := unsigned('0' & complement);
151                 -- else
152                         -- tmp_right_operand := unsigned('0' & right_operand);
153                 -- end if;
154                 
155                 -- l_neg := std_logic_vector(carry_res)(gp_register_t'high);
156                 -- r_neg := std_logic_vector(tmp_right_operand)(gp_register_t'high);
157                 
158                 -- carry_res := carry_res + tmp_right_operand;
159                 -- oflo2 := add_oflo(l_neg,r_neg,std_logic_vector(carry_res)(gp_register_t'high));
160                 
161
162                 -- alu_result_out.result := std_logic_vector(carry_res)(gp_register_t'range);
163                 -- alu_result_out.status.carry := std_logic_vector(carry_res)(carry_res'high);
164                 
165                 
166                 -- alu_result_out.status.carry := oflo1 or oflo2;
167                 
168                 -- --sign will be set globally.
169                 -- --zero will be set globally.
170                 
171                 -- return alu_result_out;
172         -- end function addsub_op;
173         
174         -- function and_op(left_operand, right_operand : gp_register_t; alu_result : alu_result_rec) return alu_result_rec is
175                 -- variable alu_result_out : alu_result_rec;
176         -- begin
177                 -- alu_result_out := alu_result;
178                 -- alu_result_out.result := left_operand and right_operand;
179         -- end function and_op;
180         
181         -- function or_op(left_operand, right_operand : gp_register_t; alu_result : alu_result_rec) return alu_result_rec is
182                 -- variable alu_result_out : alu_result_rec;
183         -- begin
184                 -- alu_result_out := alu_result;
185                 -- alu_result_out.result := left_operand or right_operand;
186         -- end function or_op;
187         
188         -- function xor_op(left_operand, right_operand : gp_register_t; alu_result : alu_result_rec) return alu_result_rec is
189                 -- variable alu_result_out : alu_result_rec;
190         -- begin
191                 -- alu_result_out := alu_result;
192                 -- alu_result_out.result := left_operand xor right_operand;
193         -- end function xor_op;
194         
195         -- function shift_op(left_operand, right_operand : gp_register_t; arith,rs,carry : std_logic ;alu_result : alu_result_rec) return alu_result_rec is
196                 -- variable alu_result_out : alu_result_rec;
197                 -- variable tmp_shift : bit_vector(gp_register_t'length+1 downto 0);
198                 -- variable tmp_sb : std_logic;
199         -- begin
200                 -- alu_result_out := alu_result;
201                 
202                 -- if rs = '1' then
203                         -- tmp_sb := (carry and alu_result.status.carry and not(arith)) or (arith and left_operand(gp_register_t'high));
204                         -- tmp_shift := bit_vector(tmp_sb & left_operand & alu_result.status.carry);
205                         -- tmp_shift := tmp_shift sra to_integer(unsigned(right_operand)(SHIFT_WIDTH-1 downto 0));
206                         
207                         -- alu_result_out.status.carry := std_logic_vector(tmp_shift)(0);
208                 -- else
209                         -- tmp_sb := (carry and alu_result.status.carry and not(arith));
210                         -- tmp_shift :=  bit_vector(alu_result.status.carry & left_operand & tmp_sb);
211                         -- tmp_shift :=  tmp_shift sla to_integer(unsigned(right_operand)(SHIFT_WIDTH-1 downto 0));
212                         
213                         -- alu_result_out.status.carry := std_logic_vector(tmp_shift)(tmp_shift'high);
214                 -- end if;
215                 
216                 -- alu_result_out.result := std_logic_vector(tmp_shift)(gp_register_t'length downto 1);
217                 
218         -- end function shift_op;
219
220 end package body alu_pkg;