a125674232e8713096de62472ab656a1d0912944
[calu.git] / cpu / src / alu_pkg.vhd
1 library IEEE;\r
2 \r
3 use IEEE.std_logic_1164.all;\r
4 use IEEE.numeric_std.all;\r
5 \r
6 use work.common_pkg.all;\r
7 --use work.core_extension.all;\r
8 \r
9 \r
10 package alu_pkg is\r
11         \r
12         type status_rec is record\r
13                 zero : std_logic;\r
14                 oflo : std_logic;\r
15                 sign : std_logic;\r
16                 carry : std_logic;\r
17         end record;\r
18         \r
19         subtype status_t is byte_t;\r
20         type alu_interal_rec is record\r
21                 \r
22         end record alu_internal_rec;\r
23         \r
24         type alu_result_rec is record\r
25                 result : gp_register_t;\r
26                 result_addr : gp_addr_t;\r
27                 \r
28                 status : status_rec;\r
29                 stackpointer : gp_register_t;\r
30 \r
31                 alu_jmp : std_logic;\r
32                 brpr_bit : std_logic;\r
33                 reg_op : std_logic;\r
34                 mem_op  : std_logic;\r
35                 \r
36                 hw_op   : std_logic;\r
37                 byte_op : std_logic;\r
38                 sign_xt : std_logic;\r
39                 \r
40         end record alu_result_rec;\r
41         \r
42         constant SHIFT_WIDTH : integer := log2c(gp_register_t'length);\r
43         \r
44         function add_oflo(l_neg, r_neg, res_neg : std_logic) return std_logic;\r
45         function addsub_op(left_operand, right_operand : gp_register_t; sub : std_logic; alu_result : alu_result_rec) return alu_result_rec;\r
46         \r
47         function and_op(left_operand, right_operand : gp_register_t; alu_result : alu_result_rec) return alu_result_rec;\r
48         function or_op(left_operand, right_operand : gp_register_t; alu_result : alu_result_rec) return alu_result_rec;\r
49         function xor_op(left_operand, right_operand : gp_register_t; alu_result : alu_result_rec) return alu_result_rec;\r
50         \r
51         function shift_op(left_operand, right_operand : gp_register_t; arith,sleft,carry : std_logic ;alu_result : alu_result_rec) return alu_result_rec;\r
52         \r
53         \r
54 end package alu_pkg;\r
55 \r
56 package body alu_pkg is\r
57 \r
58         function add_oflo(l_neg, r_neg , res_neg: std_logic) return std_logic is\r
59         begin\r
60                 return (l_neg AND r_neg AND not(res_neg)) OR \r
61                                 (not(l_neg) AND not(r_neg) AND res_neg);\r
62         end function add_oflo;\r
63         \r
64         function addsub_op(left_operand, right_operand : gp_register_t; sub, addc : std_logic; alu_result : alu_result_rec) return alu_result_rec is\r
65                 variable alu_result_out : alu_result_rec;\r
66                 variable complement             : gp_register_t;\r
67                 variable carry_res              : unsigned(gp_register_t'length downto 0);\r
68                 variable tmp_right_operand : unsigned(gp_register_t'length downto 0);\r
69                 variable oflo1, oflo2, l_neg, r_neg : std_logic;\r
70                 variable addcarry               : unsigned(carry_res'range);\r
71         begin\r
72                 alu_result_out := alu_result;\r
73                 \r
74                 addcarry := (others =>'0');\r
75                 addcarry(0) := unsigned(alu_result.status.carry and addc);\r
76                 \r
77                 complement := inc(not(right_operand));\r
78                 l_neg := left_operand(gp_register_t'high);\r
79                 \r
80                 carry_res := unsigned('0' & left_operand)+addcarry;\r
81                 oflo1 := add_oflo(l_neg,'0',std_logic_vector(carry_res)(gp_register_t'high));\r
82                 \r
83                 if sub = '1' then\r
84                         tmp_right_operand := unsigned('0' & complement);\r
85                 else\r
86                         tmp_right_operand := unsigned('0' & right_operand);\r
87                 end if;\r
88                 \r
89                 l_neg := std_logic_vector(carry_res)(gp_register_t'high);\r
90                 r_neg := std_logic_vector(tmp_right_operand)(gp_register_t'high);\r
91                 \r
92                 carry_res := carry_res + tmp_right_operand;\r
93                 oflo2 := add_oflo(l_neg,r_neg,std_logic_vector(carry_res)(gp_register_t'high));\r
94                 \r
95 \r
96                 alu_result_out.result := std_logic_vector(carry_res)(gp_register_t'range);\r
97                 alu_result_out.status.carry := std_logic_vector(carry_res)(carry_res'high);\r
98                 \r
99                 \r
100                 alu_result_out.status.carry := oflo1 or oflo2;\r
101                 \r
102                 --sign will be set globally.\r
103                 --zero will be set globally.\r
104                 \r
105                 return alu_result_out;\r
106         end function addsub_op;\r
107         \r
108         function and_op(left_operand, right_operand : gp_register_t; alu_result : alu_result_rec) return alu_result_rec is\r
109                 variable alu_result_out : alu_result_rec;\r
110         begin\r
111                 alu_result_out := alu_result;\r
112                 alu_result_out.result := left_operand and right_operand;\r
113         end function and_op;\r
114         \r
115         function or_op(left_operand, right_operand : gp_register_t; alu_result : alu_result_rec) return alu_result_rec is\r
116                 variable alu_result_out : alu_result_rec;\r
117         begin\r
118                 alu_result_out := alu_result;\r
119                 alu_result_out.result := left_operand or right_operand;\r
120         end function or_op;\r
121         \r
122         function xor_op(left_operand, right_operand : gp_register_t; alu_result : alu_result_rec) return alu_result_rec is\r
123                 variable alu_result_out : alu_result_rec;\r
124         begin\r
125                 alu_result_out := alu_result;\r
126                 alu_result_out.result := left_operand xor right_operand;\r
127         end function xor_op;\r
128         \r
129         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\r
130                 variable alu_result_out : alu_result_rec;\r
131                 variable tmp_shift : bit_vector(gp_register_t'length+1 downto 0);\r
132                 variable tmp_sb : std_logic;\r
133         begin\r
134                 alu_result_out := alu_result;\r
135                 \r
136                 if rs = '1' then\r
137                         tmp_sb := (carry and alu_result.status.carry and not(arith)) or (arith and left_operand(gp_register_t'high));\r
138                         tmp_shift := bit_vector(tmp_sb & left_operand & alu_result.status.carry);\r
139                         tmp_shift := tmp_shift sra to_integer(unsigned(right_operand)(SHIFT_WIDTH-1 downto 0));\r
140                         \r
141                         alu_result_out.status.carry := std_logic_vector(tmp_shift)(0);\r
142                 else\r
143                         tmp_sb := (carry and alu_result.status.carry and not(arith));\r
144                         tmp_shift :=  bit_vector(alu_result.status.carry & left_operand & tmp_sb);\r
145                         tmp_shift :=  tmp_shift sla to_integer(unsigned(right_operand)(SHIFT_WIDTH-1 downto 0));\r
146                         \r
147                         alu_result_out.status.carry := std_logic_vector(tmp_shift)(tmp_shift'high);\r
148                 end if;\r
149                 \r
150                 alu_result_out.result := std_logic_vector(tmp_shift)(gp_register_t'length downto 1);\r
151                 \r
152         end function shift_op;\r
153 \r
154 end package body alu_pkg;\r