copyleft: gplv3 added and set repo to public
[calu.git] / cpu / src / alu_b.vhd
index 511b15426f36e640b167936aea137bc07290dd9c..9ebf6c5b5e9dc333ceec76e1c8e0d7ada4f7a8e1 100755 (executable)
-library IEEE;\r
-use IEEE.std_logic_1164.all;\r
-use IEEE.numeric_std.all;\r
-\r
-use work.alu_pkg.all;\r
-\r
-\r
-architecture behaviour of alu is\r
-       component exec_op is\r
-       port(\r
-               --System inputs\r
-               \r
-               clk : in std_logic;\r
-               reset : in std_logic;\r
-               --operation inputs\r
-               left_operand : in gp_register_t;\r
-               right_operand : in gp_register_t;\r
-               op_detail  : in op_opt_t;\r
-               alu_state  : in alu_result_rec;\r
-               alu_result : out alu_result_rec\r
-       );                      \r
-       end component exec_op;\r
-       \r
-       signal add_result, and_result, or_result, xor_result, shift_result : alu_result_rec;\r
-       \r
-begin\r
-\r
-       add_inst : exec_op\r
-       port map(clk,reset,left_operand, right_operand, op_detail, alu_state, add_result);\r
-       \r
-       and_inst : exec_op\r
-       port map(clk,reset,left_operand, right_operand, op_detail, alu_state, and_result);\r
-       or_inst : exec_op\r
-       port map(clk,reset,left_operand, right_operand, op_detail, alu_state, or_result);\r
-       xor_inst : exec_op\r
-       port map(clk,reset,left_operand, right_operand, op_detail, alu_state, xor_result);\r
-       \r
-       shift_inst : exec_op\r
-       port map(clk,reset,left_operand, right_operand, op_detail, alu_state, shift_result);\r
-\r
-calc: process(condition, op_group, op_detail ,alu_state,and_result,add_result,or_result,xor_result,shift_result)\r
-       variable result_v : alu_result_rec;\r
-       variable res_prod : std_logic;\r
-       variable cond_met : std_logic;\r
-       variable mem_en : std_logic;\r
-begin\r
-       result_v := alu_state;\r
-       \r
-       result_v.result := add_result.result;\r
-       res_prod := '1';\r
-       mem_en := '0';\r
-       \r
-       case condition is\r
-       when COND_NZERO =>\r
-               cond_met := not(alu_state.status.zero);\r
-       when COND_ZERO =>\r
-               cond_met := alu_state.status.zero;\r
-       when COND_NOFLO =>\r
-               cond_met := not(alu_state.status.oflo);\r
-       when COND_OFLO =>\r
-               cond_met := alu_state.status.oflo;\r
-       when COND_NCARRY =>\r
-               cond_met := not(alu_state.status.carry);\r
-       when COND_CARRY =>\r
-               cond_met := alu_state.status.carry;\r
-       when COND_NSIGN =>\r
-               cond_met := not(alu_state.status.sign);\r
-       when COND_SIGN =>\r
-               cond_met := alu_state.status.sign;\r
-       when COND_ABOVE =>\r
-               cond_met := not(alu_state.status.carry) and not(alu_state.status.zero);\r
-       when COND_BEQ =>\r
-               cond_met := alu_state.status.carry or alu_state.status.zero;\r
-       when COND_GEQ =>\r
-               cond_met := not(alu_state.status.sign xor alu_state.status.oflo);\r
-       when COND_LT =>\r
-               cond_met := alu_state.status.sign xor alu_state.status.oflo;\r
-       when COND_GT =>\r
-               cond_met := not(alu_state.status.zero) and not(alu_state.status.sign xor alu_state.status.oflo);\r
-       when COND_LEQ =>\r
-               cond_met := alu_state.status.zero or (alu_state.status.sign xor alu_state.status.oflo);\r
-       when COND_ALWAYS =>\r
-               cond_met := '1';\r
-       when COND_NEVER =>\r
-               cond_met := '0';\r
-       end case;\r
-       \r
-       case op_group is\r
-       when ADDSUB_OP =>\r
-               result_v := add_result;\r
-       when AND_OP =>\r
-               result_v := and_result;\r
-       when OR_OP =>\r
-               result_v := or_result;\r
-       when XOR_OP =>\r
-               result_v := xor_result;\r
-       when SHIFT_OP =>\r
-               result_v := shift_result;\r
-       end case;\r
-       \r
-       if result_v.result = REG_ZERO then\r
-               result_v.status.zero := '1';\r
-       end if;\r
-       \r
-       result_v.status.sign := result_v.result(gp_register_t'high);\r
-\r
-       if (op_detail(NO_PSW_OPT) = '1') or (cond_met = '0') then\r
-               result_v.status := alu_state.status;\r
-       end if;\r
-       \r
-       result_v.new_val := not(op_detail(NO_DST_OPT)) and res_prod and cond_met;\r
-       result_v.mem_en := mem_en and cond_met;\r
-       \r
-       alu_result <= result_v;\r
-       \r
-end process calc; \r
-\r
-end architecture behaviour;\r
-\r
-configuration alu_cfg of alu is\r
-\r
-       for behaviour\r
-               for add_inst : exec_op \r
-                       use entity work.exec_op(add_op);\r
-               end for;\r
-               for and_inst : exec_op \r
-                       use entity work.exec_op(and_op);\r
-               end for;\r
-               for or_inst : exec_op\r
-                       use entity work.exec_op(or_op);\r
-               end for;\r
-               for xor_inst : exec_op\r
-                       use entity work.exec_op(xor_op);\r
-               end for;\r
-               for shift_inst : exec_op\r
-                       use entity work.exec_op(shift_op);\r
-               end for;\r
-       end for;\r
-               \r
-end configuration alu_cfg;\r
+--   `Deep Thought', a softcore CPU implemented on a FPGA
+--
+--  Copyright (C) 2010 Markus Hofstaetter <markus.manrow@gmx.at>
+--  Copyright (C) 2010 Martin Perner <e0725782@student.tuwien.ac.at>
+--  Copyright (C) 2010 Stefan Rebernig <stefan.rebernig@gmail.com>
+--  Copyright (C) 2010 Manfred Schwarz <e0725898@student.tuwien.ac.at>
+--  Copyright (C) 2010 Bernhard Urban <lewurm@gmail.com>
+--
+--  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 <http://www.gnu.org/licenses/>.
+
+library IEEE;
+use IEEE.std_logic_1164.all;
+use IEEE.numeric_std.all;
+
+use work.alu_pkg.all;
+
+
+architecture behaviour of alu is
+       component exec_op is
+       port(
+               --System inputs
+               
+               clk : in std_logic;
+               reset : in std_logic;
+               --operation inputs
+               left_operand : in gp_register_t;
+               right_operand : in gp_register_t;
+               op_detail  : in op_opt_t;
+               alu_state  : in alu_result_rec;
+               alu_result : out alu_result_rec
+       );                      
+       end component exec_op;
+       
+       signal add_result, and_result, or_result, xor_result, shift_result : alu_result_rec;
+        signal left_o, right_o : gp_register_t;
+       
+begin
+
+       add_inst : entity work.exec_op(add_op)
+       port map(clk,reset,left_o, right_o, op_detail, alu_state, add_result);
+       
+       and_inst : entity work.exec_op(and_op)
+       port map(clk,reset,left_o, right_o, op_detail, alu_state, and_result);
+
+       or_inst : entity work.exec_op(or_op)
+       port map(clk,reset,left_o, right_o, op_detail, alu_state, or_result);
+
+       xor_inst : entity work.exec_op(xor_op)
+       port map(clk,reset,left_o, right_o, op_detail, alu_state, xor_result);
+       
+       shift_inst : entity work.exec_op(shift_op)
+       port map(clk,reset,left_o, right_o, op_detail, alu_state, shift_result);
+
+calc: process(left_operand, right_operand,displacement, cond, op_group, op_detail ,alu_state,and_result,add_result,or_result,xor_result,shift_result, prog_cnt,brpr, pval, pval_nxt)
+       variable result_v : alu_result_rec;
+       variable res_prod : std_logic;
+       variable cond_met : std_logic;
+       variable mem_en : std_logic;
+   variable mem_op, hword_op, byte_op : std_logic;
+       variable alu_jump : std_logic;
+       variable nop     : std_logic;
+       
+       variable pinc_v, pwr_en_v : std_logic;
+       
+       variable prog_cnt_nxt : std_logic_vector(prog_cnt'range);
+begin
+       result_v := alu_state;
+       
+       res_prod := '1';
+       mem_en := '0';
+    mem_op := '0';
+        hword_op := '0';
+        byte_op := '0';
+       alu_jump := '0';
+  
+        left_o <= left_operand;
+        right_o <= right_operand;
+
+        addr <= add_result.result;
+        data <= right_operand;
+       
+       pinc_v := '0';
+       pwr_en_v := '0';
+       
+       paddr <= (others =>'0');
+       
+       result_v.result := add_result.result;
+       if (op_detail(DIRECT_JUMP_OPT) = '0') then
+               prog_cnt_nxt := std_logic_vector(unsigned(prog_cnt)+1);
+       else
+               prog_cnt_nxt := prog_cnt;
+       end if;
+       case cond is
+       when COND_NZERO =>
+               cond_met := not(alu_state.status.zero);
+       when COND_ZERO =>
+               cond_met := alu_state.status.zero;
+       when COND_NOFLO =>
+               cond_met := not(alu_state.status.oflo);
+       when COND_OFLO =>
+               cond_met := alu_state.status.oflo;
+       when COND_NCARRY =>
+               cond_met := not(alu_state.status.carry);
+       when COND_CARRY =>
+               cond_met := alu_state.status.carry;
+       when COND_NSIGN =>
+               cond_met := not(alu_state.status.sign);
+       when COND_SIGN =>
+               cond_met := alu_state.status.sign;
+       when COND_ABOVE =>
+               cond_met := not(alu_state.status.carry) and not(alu_state.status.zero);
+       when COND_BEQ =>
+               cond_met := alu_state.status.carry or alu_state.status.zero;
+       when COND_GEQ =>
+               cond_met := not(alu_state.status.sign xor alu_state.status.oflo);
+       when COND_LT =>
+               cond_met := alu_state.status.sign xor alu_state.status.oflo;
+       when COND_GT =>
+               cond_met := not(alu_state.status.zero) and not(alu_state.status.sign xor alu_state.status.oflo);
+       when COND_LEQ =>
+               cond_met := alu_state.status.zero or (alu_state.status.sign xor alu_state.status.oflo);
+       when COND_ALWAYS =>
+               cond_met := '1';
+       when COND_NEVER =>
+               cond_met := '0';
+       when others => null;
+       end case;
+       
+       nop := (alu_state.alu_jump xnor alu_state.brpr);
+       cond_met := cond_met and nop;
+
+       case op_group is
+       when ADDSUB_OP =>
+               result_v := add_result;
+       when AND_OP =>
+               result_v := and_result;
+       when OR_OP =>
+               result_v := or_result;
+       when XOR_OP =>
+               result_v := xor_result;
+       when SHIFT_OP =>
+               result_v := shift_result;
+   when LDST_OP =>
+                res_prod := '0';
+                mem_op := '1';
+               --right_o <= displacement;
+               addr <= std_logic_vector(unsigned(left_operand)+unsigned(displacement));
+                if op_detail(IMM_OPT) = '1' then
+                                        
+                                                               result_v.result := right_operand;
+                                        
+                                                               if (op_detail(LDI_REPLACE_OPT) = '0') then
+                                                                       result_v.result := left_operand;
+                                                                       if (op_detail(LOW_HIGH_OPT) = '1') then
+                                                                               result_v.result(31 downto 16) := right_operand(31 downto 16);
+                                                                       else
+                                                                               result_v.result(15 downto 0) := right_operand(15 downto 0);
+                                                                       end if;
+                                                               end if;
+
+                        res_prod := '1';
+                        mem_op := '0';
+                end if;
+                if op_detail(ST_OPT) = '1' then
+                        mem_en := '1';
+                end if;
+                                        
+                                        hword_op := op_detail(HWORD_OPT);
+                                        byte_op := op_detail(BYTE_OPT);
+                                        
+       when JMP_OP =>
+               if op_detail(JMP_REG_OPT) = '0' then
+                       left_o <= prog_cnt;
+               end if;
+               alu_jump := '1';
+       when JMP_ST_OP => 
+               left_o <= prog_cnt;
+               mem_en := '1';
+               alu_jump := '1';
+               mem_op := '1';
+               pinc_v := '1';
+               pwr_en_v := '1';
+               paddr <= (others =>'0');
+               
+               addr <= pval;
+               data <= prog_cnt_nxt;
+               if op_detail(RET_OPT) = '1' then
+                       addr <= pval_nxt;
+                       mem_en := '0';
+                       pinc_v := '0';
+                       res_prod := '0';
+               end if;
+       when STACK_OP =>
+               mem_op := '1';
+               pwr_en_v := op_detail(PWREN_OPT);
+               if op_detail(PUSH_OPT) = '1' then
+                       mem_en := '1';
+                       pinc_v := '1';
+                       res_prod := '0';
+                       addr <= pval;
+                       data <= left_operand;
+               else
+                       addr <= pval_nxt;
+               end if;
+               
+       end case;
+       
+
+       result_v.status.zero := '0';
+       if result_v.result = REG_ZERO then
+               result_v.status.zero := '1';
+       end if;
+       
+       result_v.status.sign := result_v.result(gp_register_t'high);
+
+       if (op_detail(NO_PSW_OPT) = '1') or (cond_met = '0') then
+               result_v.status := alu_state.status;
+       end if;
+       
+       result_v.reg_op := not(op_detail(NO_DST_OPT)) and res_prod and cond_met;
+       result_v.mem_en := mem_en and cond_met;
+    result_v.mem_op := mem_op and cond_met;
+       result_v.alu_jump := alu_jump and cond_met;
+       result_v.brpr := brpr and nop;
+       
+       result_v.hw_op := hword_op and cond_met;
+       result_v.byte_op := byte_op and cond_met;
+       
+       pwr_en_v := pwr_en_v and cond_met;
+        
+       if (result_v.alu_jump = '0') and (brpr = '1') then
+               result_v.result := (others => '0');
+               result_v.result(prog_cnt'range) := prog_cnt_nxt;
+               --result_v.reg_op := '1';
+       end if;
+
+       -- if result_v.mem_op = '0' then --- do this if selecting enable for extension modules is too slow.
+               -- addr <= (others => '0');
+       -- end if;
+       alu_result <= result_v;
+       pinc <= pinc_v;
+       pwr_en <= pwr_en_v;
+       
+end process calc; 
+
+end architecture behaviour;
+