library IEEE; use IEEE.std_logic_1164.all; use IEEE.numeric_std.all; use work.common_pkg.all; --use work.core_extension.all; package alu_pkg is type status_rec is record zero : std_logic; oflo : std_logic; sign : std_logic; carry : std_logic; end record; subtype status_t is byte_t; type alu_interal_rec is record end record alu_internal_rec; type alu_result_rec is record result : gp_register_t; result_addr : gp_addr_t; status : status_rec; stackpointer : gp_register_t; alu_jmp : std_logic; brpr_bit : std_logic; reg_op : std_logic; mem_op : std_logic; hw_op : std_logic; byte_op : std_logic; sign_xt : std_logic; end record alu_result_rec; constant SHIFT_WIDTH : integer := log2c(gp_register_t'length); function add_oflo(l_neg, r_neg, res_neg : std_logic) return std_logic; function addsub_op(left_operand, right_operand : gp_register_t; sub : std_logic; alu_result : alu_result_rec) return alu_result_rec; function and_op(left_operand, right_operand : gp_register_t; alu_result : alu_result_rec) return alu_result_rec; function or_op(left_operand, right_operand : gp_register_t; alu_result : alu_result_rec) return alu_result_rec; function xor_op(left_operand, right_operand : gp_register_t; alu_result : alu_result_rec) return alu_result_rec; function shift_op(left_operand, right_operand : gp_register_t; arith,sleft,carry : std_logic ;alu_result : alu_result_rec) return alu_result_rec; end package alu_pkg; package body alu_pkg is function add_oflo(l_neg, r_neg , res_neg: std_logic) return std_logic is begin return (l_neg AND r_neg AND not(res_neg)) OR (not(l_neg) AND not(r_neg) AND res_neg); end function add_oflo; function addsub_op(left_operand, right_operand : gp_register_t; sub, addc : std_logic; alu_result : alu_result_rec) return alu_result_rec is variable alu_result_out : alu_result_rec; variable complement : gp_register_t; variable carry_res : unsigned(gp_register_t'length downto 0); variable tmp_right_operand : unsigned(gp_register_t'length downto 0); variable oflo1, oflo2, l_neg, r_neg : std_logic; variable addcarry : unsigned(carry_res'range); begin alu_result_out := alu_result; addcarry := (others =>'0'); addcarry(0) := unsigned(alu_result.status.carry and addc); complement := inc(not(right_operand)); l_neg := left_operand(gp_register_t'high); carry_res := unsigned('0' & left_operand)+addcarry; oflo1 := add_oflo(l_neg,'0',std_logic_vector(carry_res)(gp_register_t'high)); if sub = '1' then tmp_right_operand := unsigned('0' & complement); else tmp_right_operand := unsigned('0' & right_operand); end if; l_neg := std_logic_vector(carry_res)(gp_register_t'high); r_neg := std_logic_vector(tmp_right_operand)(gp_register_t'high); carry_res := carry_res + tmp_right_operand; oflo2 := add_oflo(l_neg,r_neg,std_logic_vector(carry_res)(gp_register_t'high)); alu_result_out.result := std_logic_vector(carry_res)(gp_register_t'range); alu_result_out.status.carry := std_logic_vector(carry_res)(carry_res'high); alu_result_out.status.carry := oflo1 or oflo2; --sign will be set globally. --zero will be set globally. return alu_result_out; end function addsub_op; function and_op(left_operand, right_operand : gp_register_t; alu_result : alu_result_rec) return alu_result_rec is variable alu_result_out : alu_result_rec; begin alu_result_out := alu_result; alu_result_out.result := left_operand and right_operand; end function and_op; function or_op(left_operand, right_operand : gp_register_t; alu_result : alu_result_rec) return alu_result_rec is variable alu_result_out : alu_result_rec; begin alu_result_out := alu_result; alu_result_out.result := left_operand or right_operand; end function or_op; function xor_op(left_operand, right_operand : gp_register_t; alu_result : alu_result_rec) return alu_result_rec is variable alu_result_out : alu_result_rec; begin alu_result_out := alu_result; alu_result_out.result := left_operand xor right_operand; end function xor_op; 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 variable alu_result_out : alu_result_rec; variable tmp_shift : bit_vector(gp_register_t'length+1 downto 0); variable tmp_sb : std_logic; begin alu_result_out := alu_result; if rs = '1' then tmp_sb := (carry and alu_result.status.carry and not(arith)) or (arith and left_operand(gp_register_t'high)); tmp_shift := bit_vector(tmp_sb & left_operand & alu_result.status.carry); tmp_shift := tmp_shift sra to_integer(unsigned(right_operand)(SHIFT_WIDTH-1 downto 0)); alu_result_out.status.carry := std_logic_vector(tmp_shift)(0); else tmp_sb := (carry and alu_result.status.carry and not(arith)); tmp_shift := bit_vector(alu_result.status.carry & left_operand & tmp_sb); tmp_shift := tmp_shift sla to_integer(unsigned(right_operand)(SHIFT_WIDTH-1 downto 0)); alu_result_out.status.carry := std_logic_vector(tmp_shift)(tmp_shift'high); end if; alu_result_out.result := std_logic_vector(tmp_shift)(gp_register_t'length downto 1); end function shift_op; end package body alu_pkg;