-- `Deep Thought', a softcore CPU implemented on a FPGA -- -- Copyright (C) 2010 Markus Hofstaetter -- Copyright (C) 2010 Martin Perner -- Copyright (C) 2010 Stefan Rebernig -- Copyright (C) 2010 Manfred Schwarz -- Copyright (C) 2010 Bernhard Urban -- -- This program is free software: you can redistribute it and/or modify -- it under the terms of the GNU General Public License as published by -- the Free Software Foundation, either version 3 of the License, or -- (at your option) any later version. -- -- This program is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License -- along with this program. If not, see . library IEEE; use IEEE.std_logic_1164.all; use IEEE.numeric_std.all; use work.common_pkg.all; use work.extension_pkg.all; --use work.core_extension.all; package alu_pkg is --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; alu_jump : std_logic; brpr : std_logic; reg_op : std_logic; mem_op : std_logic; mem_en : std_logic; hw_op : std_logic; byte_op : std_logic; sign_xt : std_logic; end record alu_result_rec; constant SHIFT_WIDTH : integer := 5; --log2c(gp_register_t'length); constant COND_ZERO : condition_t := "0001"; constant COND_NZERO : condition_t := "0000"; constant COND_NOFLO : condition_t := "0010"; constant COND_OFLO : condition_t := "0011"; constant COND_NCARRY : condition_t := "0100"; constant COND_CARRY : condition_t := "0101"; constant COND_NSIGN : condition_t := "0110"; constant COND_SIGN : condition_t := "0111"; constant COND_ABOVE : condition_t := "1000"; constant COND_BEQ: condition_t := "1001"; constant COND_GEQ : condition_t := "1010"; constant COND_LT : condition_t := "1011"; constant COND_GT : condition_t := "1100"; constant COND_LEQ : condition_t := "1101"; constant COND_ALWAYS : condition_t := "1110"; constant COND_NEVER : condition_t := "1111"; 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, addc : 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; component alu is --some modules won't need all inputs port( --System inputs clk : in std_logic; reset : in std_logic; --operation inputs cond : in condition_t; op_group : in op_info_t; left_operand : in gp_register_t; right_operand : in gp_register_t; displacement : in gp_register_t; prog_cnt : in instr_addr_t; brpr : in std_logic; op_detail : in op_opt_t; alu_state : in alu_result_rec; pval : in gp_register_t; pval_nxt : in gp_register_t; alu_result : out alu_result_rec; addr : out word_t; --memaddr data : out gp_register_t; --mem data --ureg pinc : out std_logic; pwr_en : out std_logic; paddr : out paddr_t ); end component alu; 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;