From 11cff5384e0bd1514c946cf6e0e7396a03dd2879 Mon Sep 17 00:00:00 2001 From: Markus Hofstaetter Date: Sun, 14 Nov 2010 01:29:01 +0100 Subject: [PATCH] Added arithmetic and logical vhdl functions --- cpu/src/alu_b.vhd | 38 ++++++++++ cpu/src/alu_pkg.vhd | 154 +++++++++++++++++++++++++++++++++++++++++ cpu/src/common_pkg.vhd | 36 +++++++++- 3 files changed, 226 insertions(+), 2 deletions(-) create mode 100755 cpu/src/alu_b.vhd create mode 100755 cpu/src/alu_pkg.vhd diff --git a/cpu/src/alu_b.vhd b/cpu/src/alu_b.vhd new file mode 100755 index 0000000..533ed7f --- /dev/null +++ b/cpu/src/alu_b.vhd @@ -0,0 +1,38 @@ +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; + +use work.core_pkg.all; +use work.alu_pkg.all; + +architecture behaviour of alu is + +begin + +syn: process(sys_clk, reset) + +begin + + if (reset = RESET_VALUE) then + + elsif rising_edge(sys_clk) then + + end if; + +end process syn; + + +nxt_calc: process(sys_clk, reset) + +begin + + + case new_op is + when ADD_SUB => + + when others => null; + end case; + +end process nxt_calc; + +end architecture behaviour; diff --git a/cpu/src/alu_pkg.vhd b/cpu/src/alu_pkg.vhd new file mode 100755 index 0000000..a125674 --- /dev/null +++ b/cpu/src/alu_pkg.vhd @@ -0,0 +1,154 @@ +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; diff --git a/cpu/src/common_pkg.vhd b/cpu/src/common_pkg.vhd index 01548e4..59ff7a7 100644 --- a/cpu/src/common_pkg.vhd +++ b/cpu/src/common_pkg.vhd @@ -4,12 +4,15 @@ use IEEE.std_logic_1164.all; use IEEE.numeric_std.all; package common_pkg is + constant WORD_WIDTH : INTEGER := 32; constant HWORD_WIDTH : INTEGER := 16; constant BYTE_WIDTH : INTEGER := 8; constant OPCODE_WIDTH : INTEGER := 5; constant DISPL_WIDTH : INTEGER := 15; + + constant REG_ZERO : gp_register_t := (others => '0'); constant INSTR_ADDR_WIDTH : INTEGER := 32; constant PHYS_INSTR_ADDR_WIDTH : INTEGER := 11; @@ -17,14 +20,43 @@ package common_pkg is constant DATA_ADDR_WIDTH : INTEGER := 32; constant PHYS_DATA_ADDR_WIDTH : INTEGER := 32; + subtype byte_t is std_logic_vector(BYTE_WIDTH-1 downto 0); + subtype hword_t is std_logic_vector(HWORD_WIDTH-1 downto 0); + subtype word_t is std_logic_vector(WORD_WIDTH-1 downto 0); + subtype instruction_word_t is std_logic_vector(WORD_WIDTH-1 downto 0); subtype instruction_addr_t is std_logic_vector(INSTR_ADDR_WIDTH-1 downto 0); - subtype gp_register_t is std_logic_vector(WORD_WIDTH-1 downto 0); - + subtype gp_register_t is word_t; + subtype gp_addr_t is unsigned(REG_ADDR_WIDTH-1 downto 0); subtype data_ram_word_t is std_logic_vector(WORD_WIDTH-1 downto 0); subtype data_ram_addr_t is std_logic_vector(DATA_ADDR_WIDTH-1 downto 0); subtype opcode_t is std_logic_vector(OPCODE_WIDTH-1 downto 0); + function inc(value : in std_logic_vector; constant by : in integer := 1) return std_logic_vector; + function log2c(constant value : in integer range 0 to integer'high) return integer; end package common_pkg; + +package body common_pkg; + + function inc(value : in std_logic_vector; constant by : in integer := 1) return std_logic_vector is + begin + return std_logic_vector(UNSIGNED(value)+by); + end function inc; + + function log2c(constant value : in integer range 0 to integer'high) return integer is + variable ret_value : integer; + variable cur_value : integer; + begin + ret_value := 0; + cur_value := 1; + + while cur_value < value loop + ret_value := ret_value + 1; + cur_value := cur_value * 2; + end loop; + return ret_value; + end function log2c; + +end package body common_pkg; -- 2.25.1