URL
https://opencores.org/ocsvn/tinyvliw8/tinyvliw8/trunk
Subversion Repositories tinyvliw8
[/] [tinyvliw8/] [trunk/] [src/] [vhdl/] [proc/] [alu.vhd] - Rev 2
Compare with Previous | Blame | View Log
----------------------------------------------------------------- -- Project: Aeternitas -- Author: Oliver Stecklina <stecklina@ihp-microelectronics.com -- Date: 13.11.2013 -- File: alu.vhd -- Design: AeternitasSWUR ----------------------------------------------------------------- -- Description : Arithmetic unit of IHPvliw8 processor ----------------------------------------------------------------- -- $Log$ ----------------------------------------------------------------- library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; entity vliwProc_alu is port ( state : in std_logic_vector(3 downto 0); enable_n : in std_logic; opcode : in std_logic_vector(2 downto 0); as : in std_logic_vector(1 downto 0); dstRegIn : in std_logic_vector(2 downto 0); dataIn : in std_logic_vector(7 downto 0); reg0 : in std_logic_vector(7 downto 0); reg1 : in std_logic_vector(7 downto 0); reg2 : in std_logic_vector(7 downto 0); reg3 : in std_logic_vector(7 downto 0); reg4 : in std_logic_vector(7 downto 0); reg5 : in std_logic_vector(7 downto 0); reg6 : in std_logic_vector(7 downto 0); reg7 : in std_logic_vector(7 downto 0); cIn : in std_logic; cOut : out std_logic; zOut : out std_logic; dstRegEn_n : out std_logic; dstRegOut : out std_logic_vector(2 downto 0); dataOut : out std_logic_vector(7 downto 0); rst_n : in std_logic ); end vliwProc_alu; architecture behavior of vliwProc_alu is signal cIn_s : std_logic; signal as_s : std_logic_vector(1 downto 0); signal opcode_s : std_logic_vector(2 downto 0); signal dstRegIn_s : std_logic_vector(2 downto 0); signal cShift_s : std_logic; signal cAdd_s : std_logic; signal shift_s : std_logic; signal logic_s : std_logic; signal arith_s : std_logic; signal dataOut_s : std_logic_vector(7 downto 0); signal op0_s : std_logic_vector(7 downto 0); signal op1_s : std_logic_vector(7 downto 0); signal aluEn_s : std_logic; signal rst_n_s : std_logic; begin rst_n_s <= rst_n; enable_p : process(rst_n_s, state(2)) begin if (rst_n_s = '0') then aluEn_s <= '0'; else if (state(2)'event and state(2) = '1') then if (enable_n = '0') then aluEn_s <= '1'; else aluEn_s <= '0'; end if; end if; end if; end process; commitIn_proc : process(rst_n_s, state(2)) variable shift_v : std_logic; variable logic_v : std_logic; variable arith_v : std_logic; variable op0_v : unsigned(8 downto 0); variable op1_v : unsigned(8 downto 0); begin if (rst_n_s = '0') then cIn_s <= '0'; as_s <= (others => '0'); opcode_s <= (others => '0'); dstRegIn_s <= (others => '0'); op0_v := (others => '0'); op1_v := (others => '0'); shift_v := '0'; logic_v := '0'; arith_v := '0'; cAdd_s <= '0'; else if (state(2)'event and state(2) = '1') then shift_v := '0'; logic_v := '0'; arith_v := '0'; if (enable_n = '0') then cIn_s <= cIn; as_s <= as; opcode_s <= opcode; dstRegIn_s <= dstRegIn; case opcode IS when "010" => arith_v := '1'; when "011" => shift_v := '1'; when "100" => logic_v := '1'; when "101" => logic_v := '1'; when "110" => logic_v := '1'; WHEN others => null; end case; if (shift_v = '1') then if (as(0) = '0' or as(1) = '0') then CASE dataIn(2 downto 0) IS WHEN "000" => op0_v := unsigned('0' & reg0); WHEN "001" => op0_v := unsigned('0' & reg1); WHEN "010" => op0_v := unsigned('0' & reg2); WHEN "011" => op0_v := unsigned('0' & reg3); WHEN "100" => op0_v := unsigned('0' & reg4); WHEN "101" => op0_v := unsigned('0' & reg5); WHEN "110" => op0_v := unsigned('0' & reg6); WHEN "111" => op0_v := unsigned('0' & reg7); WHEN others => null; END CASE; op1_v := unsigned('0' & dataIn); else -- mov Rx, #NUM op0_v := unsigned('0' & dataIn); end if; elsif (logic_v = '1') then if (as(0) = '0') then if (dataIn(7) = '0') then case dataIn(6 downto 4) is when "000" => op0_v := unsigned('0' & reg0); when "001" => op0_v := unsigned('0' & reg1); when "010" => op0_v := unsigned('0' & reg2); when "011" => op0_v := unsigned('0' & reg3); when "100" => op0_v := unsigned('0' & reg4); when "101" => op0_v := unsigned('0' & reg5); when "110" => op0_v := unsigned('0' & reg6); when "111" => op0_v := unsigned('0' & reg7); when others => null; end case; else case dataIn(6 downto 4) is when "000" => op0_v := unsigned(not('0' & reg0)); when "001" => op0_v := unsigned(not('0' & reg1)); when "010" => op0_v := unsigned(not('0' & reg2)); when "011" => op0_v := unsigned(not('0' & reg3)); when "100" => op0_v := unsigned(not('0' & reg4)); when "101" => op0_v := unsigned(not('0' & reg5)); when "110" => op0_v := unsigned(not('0' & reg6)); when "111" => op0_v := unsigned(not('0' & reg7)); when others => null; end case; end if; if (dataIn(3) = '0') then case dataIn(2 downto 0) is when "000" => op1_v := unsigned('0' & reg0); when "001" => op1_v := unsigned('0' & reg1); when "010" => op1_v := unsigned('0' & reg2); when "011" => op1_v := unsigned('0' & reg3); when "100" => op1_v := unsigned('0' & reg4); when "101" => op1_v := unsigned('0' & reg5); when "110" => op1_v := unsigned('0' & reg6); when "111" => op1_v := unsigned('0' & reg7); when others => null; end case; else case dataIn(2 downto 0) is when "000" => op1_v := unsigned(not('0' & reg0)); when "001" => op1_v := unsigned(not('0' & reg1)); when "010" => op1_v := unsigned(not('0' & reg2)); when "011" => op1_v := unsigned(not('0' & reg3)); when "100" => op1_v := unsigned(not('0' & reg4)); when "101" => op1_v := unsigned(not('0' & reg5)); when "110" => op1_v := unsigned(not('0' & reg6)); when "111" => op1_v := unsigned(not('0' & reg7)); when others => null; end case; end if; else CASE dstRegIn IS WHEN "000" => op0_v := unsigned('0' & reg0); WHEN "001" => op0_v := unsigned('0' & reg1); WHEN "010" => op0_v := unsigned('0' & reg2); WHEN "011" => op0_v := unsigned('0' & reg3); WHEN "100" => op0_v := unsigned('0' & reg4); WHEN "101" => op0_v := unsigned('0' & reg5); WHEN "110" => op0_v := unsigned('0' & reg6); WHEN "111" => op0_v := unsigned('0' & reg7); WHEN others => null; END CASE; op1_v := unsigned('0' & dataIn); end if; elsif (arith_v = '1') then if (as(0) = '0') then if (dataIn(7) = '0') then case dataIn(6 downto 4) is when "000" => op0_v := unsigned('0' & reg0); when "001" => op0_v := unsigned('0' & reg1); when "010" => op0_v := unsigned('0' & reg2); when "011" => op0_v := unsigned('0' & reg3); when "100" => op0_v := unsigned('0' & reg4); when "101" => op0_v := unsigned('0' & reg5); when "110" => op0_v := unsigned('0' & reg6); when "111" => op0_v := unsigned('0' & reg7); when others => null; end case; else case dataIn(6 downto 4) is when "000" => op0_v := unsigned(not('0' & reg0)); when "001" => op0_v := unsigned(not('0' & reg1)); when "010" => op0_v := unsigned(not('0' & reg2)); when "011" => op0_v := unsigned(not('0' & reg3)); when "100" => op0_v := unsigned(not('0' & reg4)); when "101" => op0_v := unsigned(not('0' & reg5)); when "110" => op0_v := unsigned(not('0' & reg6)); when "111" => op0_v := unsigned(not('0' & reg7)); when others => null; end case; op0_v := op0_v + 1; end if; if (dataIn(3) = '0') then case dataIn(2 downto 0) is when "000" => op1_v := unsigned('0' & reg0); when "001" => op1_v := unsigned('0' & reg1); when "010" => op1_v := unsigned('0' & reg2); when "011" => op1_v := unsigned('0' & reg3); when "100" => op1_v := unsigned('0' & reg4); when "101" => op1_v := unsigned('0' & reg5); when "110" => op1_v := unsigned('0' & reg6); when "111" => op1_v := unsigned('0' & reg7); when others => null; end case; else -- two's complement case dataIn(2 downto 0) is when "000" => op1_v := unsigned(not('0' & reg0)); when "001" => op1_v := unsigned(not('0' & reg1)); when "010" => op1_v := unsigned(not('0' & reg2)); when "011" => op1_v := unsigned(not('0' & reg3)); when "100" => op1_v := unsigned(not('0' & reg4)); when "101" => op1_v := unsigned(not('0' & reg5)); when "110" => op1_v := unsigned(not('0' & reg6)); when "111" => op1_v := unsigned(not('0' & reg7)); when others => null; end case; op1_v := op1_v + 1; end if; else CASE dstRegIn IS WHEN "000" => op0_v := unsigned('0' & reg0); WHEN "001" => op0_v := unsigned('0' & reg1); WHEN "010" => op0_v := unsigned('0' & reg2); WHEN "011" => op0_v := unsigned('0' & reg3); WHEN "100" => op0_v := unsigned('0' & reg4); WHEN "101" => op0_v := unsigned('0' & reg5); WHEN "110" => op0_v := unsigned('0' & reg6); WHEN "111" => op0_v := unsigned('0' & reg7); WHEN others => null; END CASE; op1_v := unsigned('0' & dataIn); end if; -- addition op0_v := op0_v + op1_v; -- carry add if (as(1) = '1' and cIn = '1') then op0_v := op0_v + 1; end if; cAdd_s <= std_logic(op0_v(8)); end if; end if; end if; end if; shift_s <= std_logic(shift_v); logic_s <= std_logic(logic_v); arith_s <= std_logic(arith_v); op0_s <= std_logic_vector(op0_v(7 downto 0)); op1_s <= std_logic_vector(op1_v(7 downto 0)); end process; cShift_s <= op0_s(7) when as_s(0) = '0' and as(1) = '0' else -- shift left op0_s(0) when as_s(0) = '0' and as(1) = '1' else -- shift right '0'; dataOut_s <= op0_s(6 downto 0) & '0' when shift_s = '1' and as_s = "00" and op1_s(3) = '0' else op0_s(6 downto 0) & cIn_s when shift_s = '1' and as_s = "00" and op1_s(3) = '1' else op0_s(7) & op0_s(7 downto 1) when shift_s = '1' and as_s = "01" and op1_s(3) = '0' else cIn_s & op0_s(7 downto 1) when shift_s = '1' and as_s = "01" and op1_s(3) = '1' else not(op0_s) when shift_s = '1' and as_s = "10" and op1_s(3) = '1' else op0_s when shift_s = '1' and as_s(0) = '1' else op0_s and op1_s when logic_s = '1' and opcode_s = "100" and as_s(1) = '0' else not(op0_s and op1_s) when logic_s = '1' and opcode_s = "100" and as_s(1) = '1' else op0_s or op1_s when logic_s = '1' and opcode_s = "101" and as_s(1) = '0' else not(op0_s or op1_s) when logic_s = '1' and opcode_s = "101" and as_s(1) = '1' else op0_s xor op1_s when logic_s = '1' and opcode_s = "110" and as_s(1) = '0' else not(op0_s xor op1_s) when logic_s = '1' and opcode_s = "110" and as_s(1) = '1' else op0_s when arith_s = '1' else (others => '0'); cOut <= cAdd_s when aluEn_s = '1' and arith_s = '1' else -- arithmetic operations cShift_s when aluEn_s = '1' and shift_s = '1' and as_s(0) = '0' else -- shift '0'; dataOut <= dataOut_s when aluEn_s = '1' else (others => '0'); zOut <= '1' when aluEn_s = '1' and dataOut_s = "00000000" else '0'; dstRegEn_n <= '0' when aluEn_s = '1' else '1'; dstRegOut <= dstRegIn_s when aluEn_s = '1' else (others => '0'); end behavior;