Added arithmetic and logical vhdl functions
authorMarkus Hofstaetter <markus.hofstaetter@gmx.net>
Sun, 14 Nov 2010 00:29:01 +0000 (01:29 +0100)
committerU-merlin\Schakal <Schakal@merlin.(none)>
Sun, 14 Nov 2010 00:30:21 +0000 (01:30 +0100)
cpu/src/alu_b.vhd [new file with mode: 0755]
cpu/src/alu_pkg.vhd [new file with mode: 0755]
cpu/src/common_pkg.vhd

diff --git a/cpu/src/alu_b.vhd b/cpu/src/alu_b.vhd
new file mode 100755 (executable)
index 0000000..533ed7f
--- /dev/null
@@ -0,0 +1,38 @@
+library IEEE;\r
+use IEEE.std_logic_1164.all;\r
+use IEEE.numeric_std.all;\r
+\r
+use work.core_pkg.all;\r
+use work.alu_pkg.all;\r
+\r
+architecture behaviour of alu is\r
+\r
+begin\r
+\r
+syn: process(sys_clk, reset)\r
+\r
+begin\r
+\r
+       if (reset = RESET_VALUE) then\r
+                               \r
+       elsif rising_edge(sys_clk) then\r
+               \r
+       end if;\r
+       \r
+end process syn; \r
+\r
+\r
+nxt_calc: process(sys_clk, reset)\r
+\r
+begin\r
+\r
+       \r
+       case new_op is\r
+       when ADD_SUB =>\r
+               \r
+       when others => null;\r
+       end case;\r
+       \r
+end process nxt_calc; \r
+\r
+end architecture behaviour;\r
diff --git a/cpu/src/alu_pkg.vhd b/cpu/src/alu_pkg.vhd
new file mode 100755 (executable)
index 0000000..a125674
--- /dev/null
@@ -0,0 +1,154 @@
+library IEEE;\r
+\r
+use IEEE.std_logic_1164.all;\r
+use IEEE.numeric_std.all;\r
+\r
+use work.common_pkg.all;\r
+--use work.core_extension.all;\r
+\r
+\r
+package alu_pkg is\r
+       \r
+       type status_rec is record\r
+               zero : std_logic;\r
+               oflo : std_logic;\r
+               sign : std_logic;\r
+               carry : std_logic;\r
+       end record;\r
+       \r
+       subtype status_t is byte_t;\r
+       type alu_interal_rec is record\r
+               \r
+       end record alu_internal_rec;\r
+       \r
+       type alu_result_rec is record\r
+               result : gp_register_t;\r
+               result_addr : gp_addr_t;\r
+               \r
+               status : status_rec;\r
+               stackpointer : gp_register_t;\r
+\r
+               alu_jmp : std_logic;\r
+               brpr_bit : std_logic;\r
+               reg_op : std_logic;\r
+               mem_op  : std_logic;\r
+               \r
+               hw_op   : std_logic;\r
+               byte_op : std_logic;\r
+               sign_xt : std_logic;\r
+               \r
+       end record alu_result_rec;\r
+       \r
+       constant SHIFT_WIDTH : integer := log2c(gp_register_t'length);\r
+       \r
+       function add_oflo(l_neg, r_neg, res_neg : std_logic) return std_logic;\r
+       function addsub_op(left_operand, right_operand : gp_register_t; sub : std_logic; alu_result : alu_result_rec) return alu_result_rec;\r
+       \r
+       function and_op(left_operand, right_operand : gp_register_t; alu_result : alu_result_rec) return alu_result_rec;\r
+       function or_op(left_operand, right_operand : gp_register_t; alu_result : alu_result_rec) return alu_result_rec;\r
+       function xor_op(left_operand, right_operand : gp_register_t; alu_result : alu_result_rec) return alu_result_rec;\r
+       \r
+       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
+       \r
+       \r
+end package alu_pkg;\r
+\r
+package body alu_pkg is\r
+\r
+       function add_oflo(l_neg, r_neg , res_neg: std_logic) return std_logic is\r
+       begin\r
+               return (l_neg AND r_neg AND not(res_neg)) OR \r
+                               (not(l_neg) AND not(r_neg) AND res_neg);\r
+       end function add_oflo;\r
+       \r
+       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
+               variable alu_result_out : alu_result_rec;\r
+               variable complement             : gp_register_t;\r
+               variable carry_res              : unsigned(gp_register_t'length downto 0);\r
+               variable tmp_right_operand : unsigned(gp_register_t'length downto 0);\r
+               variable oflo1, oflo2, l_neg, r_neg : std_logic;\r
+               variable addcarry               : unsigned(carry_res'range);\r
+       begin\r
+               alu_result_out := alu_result;\r
+               \r
+               addcarry := (others =>'0');\r
+               addcarry(0) := unsigned(alu_result.status.carry and addc);\r
+               \r
+               complement := inc(not(right_operand));\r
+               l_neg := left_operand(gp_register_t'high);\r
+               \r
+               carry_res := unsigned('0' & left_operand)+addcarry;\r
+               oflo1 := add_oflo(l_neg,'0',std_logic_vector(carry_res)(gp_register_t'high));\r
+               \r
+               if sub = '1' then\r
+                       tmp_right_operand := unsigned('0' & complement);\r
+               else\r
+                       tmp_right_operand := unsigned('0' & right_operand);\r
+               end if;\r
+               \r
+               l_neg := std_logic_vector(carry_res)(gp_register_t'high);\r
+               r_neg := std_logic_vector(tmp_right_operand)(gp_register_t'high);\r
+               \r
+               carry_res := carry_res + tmp_right_operand;\r
+               oflo2 := add_oflo(l_neg,r_neg,std_logic_vector(carry_res)(gp_register_t'high));\r
+               \r
+\r
+               alu_result_out.result := std_logic_vector(carry_res)(gp_register_t'range);\r
+               alu_result_out.status.carry := std_logic_vector(carry_res)(carry_res'high);\r
+               \r
+               \r
+               alu_result_out.status.carry := oflo1 or oflo2;\r
+               \r
+               --sign will be set globally.\r
+               --zero will be set globally.\r
+               \r
+               return alu_result_out;\r
+       end function addsub_op;\r
+       \r
+       function and_op(left_operand, right_operand : gp_register_t; alu_result : alu_result_rec) return alu_result_rec is\r
+               variable alu_result_out : alu_result_rec;\r
+       begin\r
+               alu_result_out := alu_result;\r
+               alu_result_out.result := left_operand and right_operand;\r
+       end function and_op;\r
+       \r
+       function or_op(left_operand, right_operand : gp_register_t; alu_result : alu_result_rec) return alu_result_rec is\r
+               variable alu_result_out : alu_result_rec;\r
+       begin\r
+               alu_result_out := alu_result;\r
+               alu_result_out.result := left_operand or right_operand;\r
+       end function or_op;\r
+       \r
+       function xor_op(left_operand, right_operand : gp_register_t; alu_result : alu_result_rec) return alu_result_rec is\r
+               variable alu_result_out : alu_result_rec;\r
+       begin\r
+               alu_result_out := alu_result;\r
+               alu_result_out.result := left_operand xor right_operand;\r
+       end function xor_op;\r
+       \r
+       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
+               variable alu_result_out : alu_result_rec;\r
+               variable tmp_shift : bit_vector(gp_register_t'length+1 downto 0);\r
+               variable tmp_sb : std_logic;\r
+       begin\r
+               alu_result_out := alu_result;\r
+               \r
+               if rs = '1' then\r
+                       tmp_sb := (carry and alu_result.status.carry and not(arith)) or (arith and left_operand(gp_register_t'high));\r
+                       tmp_shift := bit_vector(tmp_sb & left_operand & alu_result.status.carry);\r
+                       tmp_shift := tmp_shift sra to_integer(unsigned(right_operand)(SHIFT_WIDTH-1 downto 0));\r
+                       \r
+                       alu_result_out.status.carry := std_logic_vector(tmp_shift)(0);\r
+               else\r
+                       tmp_sb := (carry and alu_result.status.carry and not(arith));\r
+                       tmp_shift :=  bit_vector(alu_result.status.carry & left_operand & tmp_sb);\r
+                       tmp_shift :=  tmp_shift sla to_integer(unsigned(right_operand)(SHIFT_WIDTH-1 downto 0));\r
+                       \r
+                       alu_result_out.status.carry := std_logic_vector(tmp_shift)(tmp_shift'high);\r
+               end if;\r
+               \r
+               alu_result_out.result := std_logic_vector(tmp_shift)(gp_register_t'length downto 1);\r
+               \r
+       end function shift_op;\r
+\r
+end package body alu_pkg;\r
index 01548e44bdad09ec854e51b231e2f9b37756cd67..59ff7a7e9566866c7ee85753a3fcf15b76060aac 100644 (file)
@@ -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;