URL
https://opencores.org/ocsvn/rv01_riscv_core/rv01_riscv_core/trunk
Subversion Repositories rv01_riscv_core
[/] [rv01_riscv_core/] [trunk/] [VHDL/] [RV01_arith_pkg.vhd] - Rev 2
Compare with Previous | Blame | View Log
----------------------------------------------------------------- -- -- ----------------------------------------------------------------- -- -- -- Copyright (C) 2015 Stefano Tonello -- -- -- -- This source file may be used and distributed without -- -- restriction provided that this copyright statement is not -- -- removed from the file and that any derivative work contains -- -- the original copyright notice and the associated disclaimer.-- -- -- -- THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY -- -- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED -- -- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -- -- FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR -- -- OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -- -- INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -- -- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE -- -- GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR -- -- BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -- -- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -- -- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT -- -- OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -- -- POSSIBILITY OF SUCH DAMAGE. -- -- -- ----------------------------------------------------------------- --------------------------------------------------------------- -- Arithmetic operations macros and shifting functions --------------------------------------------------------------- library IEEE; use IEEE.std_logic_1164.all; use IEEE.numeric_std.all; library WORK; use WORK.RV01_CONSTS_PKG.all; use WORK.RV01_TYPES_PKG.all; use WORK.RV01_FUNCS_PKG.all; package RV01_ARITH_PKG is ---------------------------------------------------- -- ALU operation types ---------------------------------------------------- -- addition operation type type ADD_CTRL is ( AC_ADD, AC_SUB, AC_SLT, AC_NIL ); -- multiplication operation type type MUL_CTRL is ( MC_MUL, MC_MULH, MC_MULHSU, MC_MULHU, MC_NIL ); -- division operation type type DIV_CTRL is ( DC_DIV, DC_DIVU, DC_REM, DC_REMU, DC_NIL ); -- shifting operation type type SHF_CTRL is ( SC_SHL, SC_SHR, SC_NIL ); -- logic (boolean) operation type type LOG_CTRL is ( LC_AND, LC_OR, LC_XOR, LC_LUI, LC_NIL ); ---------------------------------------------------- -- shifting functions ---------------------------------------------------- -- 32-bit left shift function shift_left32(SI : SDWORD_T;SHFT : SHORT_SHIFT_T) return SDWORD_T; -- 32-bit arithmetic right shift function shift_right32(SI : SDWORD_T;SHFT : SHORT_SHIFT_T) return SDWORD_T; -- 32-bit logical right shift function shift_right32(SI : SDWORDU_T;SHFT : SHORT_SHIFT_T) return SDWORDU_T; -- 64-bit left shift function shift_left64(SI : LDWORD_T;SHFT : LONG_SHIFT_T) return LDWORD_T; -- 64-bit arithmetic right shift function shift_right64(SI : LDWORD_T;SHFT : LONG_SHIFT_T) return LDWORD_T; ---------------------------------------------------- -- Wrap-up sum ---------------------------------------------------- function wrap_sum(A,B : unsigned(SDLEN-1 downto 0)) return unsigned; ---------------------------------------------------- -- Sign-extension ---------------------------------------------------- function EXTS32(V : std_logic_vector) return signed; function EXTS64(V : std_logic_vector) return signed; end RV01_ARITH_PKG; package body RV01_ARITH_PKG is ---------------------------------------------------- -- shifting functions ---------------------------------------------------- function shift_left32(SI : SDWORD_T;SHFT : SHORT_SHIFT_T) return SDWORD_T is variable SO : SDWORD_T; begin case SHFT is when 0 => SO := shift_left(SI, 0); when 1 => SO := shift_left(SI, 1); when 2 => SO := shift_left(SI, 2); when 3 => SO := shift_left(SI, 3); when 4 => SO := shift_left(SI, 4); when 5 => SO := shift_left(SI, 5); when 6 => SO := shift_left(SI, 6); when 7 => SO := shift_left(SI, 7); when 8 => SO := shift_left(SI, 8); when 9 => SO := shift_left(SI, 9); when 10 => SO := shift_left(SI,10); when 11 => SO := shift_left(SI,11); when 12 => SO := shift_left(SI,12); when 13 => SO := shift_left(SI,13); when 14 => SO := shift_left(SI,14); when 15 => SO := shift_left(SI,15); when 16 => SO := shift_left(SI,16); when 17 => SO := shift_left(SI,17); when 18 => SO := shift_left(SI,18); when 19 => SO := shift_left(SI,19); when 20 => SO := shift_left(SI,20); when 21 => SO := shift_left(SI,21); when 22 => SO := shift_left(SI,22); when 23 => SO := shift_left(SI,23); when 24 => SO := shift_left(SI,24); when 25 => SO := shift_left(SI,25); when 26 => SO := shift_left(SI,26); when 27 => SO := shift_left(SI,27); when 28 => SO := shift_left(SI,28); when 29 => SO := shift_left(SI,29); when 30 => SO := shift_left(SI,30); when others => SO := shift_left(SI,31); end case; return(SO); end function; function shift_right32(SI : SDWORD_T;SHFT : SHORT_SHIFT_T) return SDWORD_T is variable SO : SDWORD_T; begin case SHFT is when 0 => SO := shift_right(SI, 0); when 1 => SO := shift_right(SI, 1); when 2 => SO := shift_right(SI, 2); when 3 => SO := shift_right(SI, 3); when 4 => SO := shift_right(SI, 4); when 5 => SO := shift_right(SI, 5); when 6 => SO := shift_right(SI, 6); when 7 => SO := shift_right(SI, 7); when 8 => SO := shift_right(SI, 8); when 9 => SO := shift_right(SI, 9); when 10 => SO := shift_right(SI,10); when 11 => SO := shift_right(SI,11); when 12 => SO := shift_right(SI,12); when 13 => SO := shift_right(SI,13); when 14 => SO := shift_right(SI,14); when 15 => SO := shift_right(SI,15); when 16 => SO := shift_right(SI,16); when 17 => SO := shift_right(SI,17); when 18 => SO := shift_right(SI,18); when 19 => SO := shift_right(SI,19); when 20 => SO := shift_right(SI,20); when 21 => SO := shift_right(SI,21); when 22 => SO := shift_right(SI,22); when 23 => SO := shift_right(SI,23); when 24 => SO := shift_right(SI,24); when 25 => SO := shift_right(SI,25); when 26 => SO := shift_right(SI,26); when 27 => SO := shift_right(SI,27); when 28 => SO := shift_right(SI,28); when 29 => SO := shift_right(SI,29); when 30 => SO := shift_right(SI,30); when others => SO := shift_right(SI,31); end case; return(SO); end function; function shift_right32(SI : SDWORDU_T;SHFT : SHORT_SHIFT_T) return SDWORDU_T is variable SO : SDWORDU_T; begin case SHFT is when 0 => SO := shift_right(SI, 0); when 1 => SO := shift_right(SI, 1); when 2 => SO := shift_right(SI, 2); when 3 => SO := shift_right(SI, 3); when 4 => SO := shift_right(SI, 4); when 5 => SO := shift_right(SI, 5); when 6 => SO := shift_right(SI, 6); when 7 => SO := shift_right(SI, 7); when 8 => SO := shift_right(SI, 8); when 9 => SO := shift_right(SI, 9); when 10 => SO := shift_right(SI,10); when 11 => SO := shift_right(SI,11); when 12 => SO := shift_right(SI,12); when 13 => SO := shift_right(SI,13); when 14 => SO := shift_right(SI,14); when 15 => SO := shift_right(SI,15); when 16 => SO := shift_right(SI,16); when 17 => SO := shift_right(SI,17); when 18 => SO := shift_right(SI,18); when 19 => SO := shift_right(SI,19); when 20 => SO := shift_right(SI,20); when 21 => SO := shift_right(SI,21); when 22 => SO := shift_right(SI,22); when 23 => SO := shift_right(SI,23); when 24 => SO := shift_right(SI,24); when 25 => SO := shift_right(SI,25); when 26 => SO := shift_right(SI,26); when 27 => SO := shift_right(SI,27); when 28 => SO := shift_right(SI,28); when 29 => SO := shift_right(SI,29); when 30 => SO := shift_right(SI,30); when others => SO := shift_right(SI,31); end case; return(SO); end function; function shift_left64(SI : LDWORD_T;SHFT : LONG_SHIFT_T) return LDWORD_T is variable SO : LDWORD_T; begin case SHFT is when 0 => SO := shift_left(SI, 0); when 1 => SO := shift_left(SI, 1); when 2 => SO := shift_left(SI, 2); when 3 => SO := shift_left(SI, 3); when 4 => SO := shift_left(SI, 4); when 5 => SO := shift_left(SI, 5); when 6 => SO := shift_left(SI, 6); when 7 => SO := shift_left(SI, 7); when 8 => SO := shift_left(SI, 8); when 9 => SO := shift_left(SI, 9); when 10 => SO := shift_left(SI,10); when 11 => SO := shift_left(SI,11); when 12 => SO := shift_left(SI,12); when 13 => SO := shift_left(SI,13); when 14 => SO := shift_left(SI,14); when 15 => SO := shift_left(SI,15); when 16 => SO := shift_left(SI,16); when 17 => SO := shift_left(SI,17); when 18 => SO := shift_left(SI,18); when 19 => SO := shift_left(SI,19); when 20 => SO := shift_left(SI,20); when 21 => SO := shift_left(SI,21); when 22 => SO := shift_left(SI,22); when 23 => SO := shift_left(SI,23); when 24 => SO := shift_left(SI,24); when 25 => SO := shift_left(SI,25); when 26 => SO := shift_left(SI,26); when 27 => SO := shift_left(SI,27); when 28 => SO := shift_left(SI,28); when 29 => SO := shift_left(SI,29); when 30 => SO := shift_left(SI,30); when 31 => SO := shift_left(SI,31); when 32 => SO := shift_left(SI,32); when 33 => SO := shift_left(SI,33); when 34 => SO := shift_left(SI,34); when 35 => SO := shift_left(SI,35); when 36 => SO := shift_left(SI,36); when 37 => SO := shift_left(SI,37); when 38 => SO := shift_left(SI,38); when 39 => SO := shift_left(SI,39); when 40 => SO := shift_left(SI,40); when 41 => SO := shift_left(SI,41); when 42 => SO := shift_left(SI,42); when 43 => SO := shift_left(SI,43); when 44 => SO := shift_left(SI,44); when 45 => SO := shift_left(SI,45); when 46 => SO := shift_left(SI,46); when 47 => SO := shift_left(SI,47); when 48 => SO := shift_left(SI,48); when 49 => SO := shift_left(SI,49); when 50 => SO := shift_left(SI,50); when 51 => SO := shift_left(SI,51); when 52 => SO := shift_left(SI,52); when 53 => SO := shift_left(SI,53); when 54 => SO := shift_left(SI,54); when 55 => SO := shift_left(SI,55); when 56 => SO := shift_left(SI,56); when 57 => SO := shift_left(SI,57); when 58 => SO := shift_left(SI,58); when 59 => SO := shift_left(SI,59); when 60 => SO := shift_left(SI,60); when 61 => SO := shift_left(SI,61); when 62 => SO := shift_left(SI,62); when others => SO := shift_left(SI,63); end case; return(SO); end function; function shift_right64(SI : LDWORD_T;SHFT : LONG_SHIFT_T) return LDWORD_T is variable SO : LDWORD_T; begin case SHFT is when 0 => SO := shift_right(SI, 0); when 1 => SO := shift_right(SI, 1); when 2 => SO := shift_right(SI, 2); when 3 => SO := shift_right(SI, 3); when 4 => SO := shift_right(SI, 4); when 5 => SO := shift_right(SI, 5); when 6 => SO := shift_right(SI, 6); when 7 => SO := shift_right(SI, 7); when 8 => SO := shift_right(SI, 8); when 9 => SO := shift_right(SI, 9); when 10 => SO := shift_right(SI,10); when 11 => SO := shift_right(SI,11); when 12 => SO := shift_right(SI,12); when 13 => SO := shift_right(SI,13); when 14 => SO := shift_right(SI,14); when 15 => SO := shift_right(SI,15); when 16 => SO := shift_right(SI,16); when 17 => SO := shift_right(SI,17); when 18 => SO := shift_right(SI,18); when 19 => SO := shift_right(SI,19); when 20 => SO := shift_right(SI,20); when 21 => SO := shift_right(SI,21); when 22 => SO := shift_right(SI,22); when 23 => SO := shift_right(SI,23); when 24 => SO := shift_right(SI,24); when 25 => SO := shift_right(SI,25); when 26 => SO := shift_right(SI,26); when 27 => SO := shift_right(SI,27); when 28 => SO := shift_right(SI,28); when 29 => SO := shift_right(SI,29); when 30 => SO := shift_right(SI,30); when 31 => SO := shift_right(SI,31); when 32 => SO := shift_right(SI,32); when 33 => SO := shift_right(SI,33); when 34 => SO := shift_right(SI,34); when 35 => SO := shift_right(SI,35); when 36 => SO := shift_right(SI,36); when 37 => SO := shift_right(SI,37); when 38 => SO := shift_right(SI,38); when 39 => SO := shift_right(SI,39); when 40 => SO := shift_right(SI,40); when 41 => SO := shift_right(SI,41); when 42 => SO := shift_right(SI,42); when 43 => SO := shift_right(SI,43); when 44 => SO := shift_right(SI,44); when 45 => SO := shift_right(SI,45); when 46 => SO := shift_right(SI,46); when 47 => SO := shift_right(SI,47); when 48 => SO := shift_right(SI,48); when 49 => SO := shift_right(SI,49); when 50 => SO := shift_right(SI,50); when 51 => SO := shift_right(SI,51); when 52 => SO := shift_right(SI,52); when 53 => SO := shift_right(SI,53); when 54 => SO := shift_right(SI,54); when 55 => SO := shift_right(SI,55); when 56 => SO := shift_right(SI,56); when 57 => SO := shift_right(SI,57); when 58 => SO := shift_right(SI,58); when 59 => SO := shift_right(SI,59); when 60 => SO := shift_right(SI,60); when 61 => SO := shift_right(SI,61); when 62 => SO := shift_right(SI,62); when others => SO := shift_right(SI,63); end case; return(SO); end function; ---------------------------------------------------- -- Wrap-up sum ---------------------------------------------------- function wrap_sum(A,B : unsigned(SDLEN-1 downto 0)) return unsigned is variable TMP : unsigned(SDLEN downto 0); begin -- A is an unsigned value and thus is zero-extended -- B has to be instead treated as a signed value and thus is sign-extended TMP := ('0' & A) + (B(SDLEN-1) & B); -- result is TMP with MSb removed (wrap-up) return(TMP(SDLEN-1 downto 0)); end function; ---------------------------------------------------- -- Sign-extension ---------------------------------------------------- function EXTS32(V : std_logic_vector) return signed is variable S : signed(SDLEN-1 downto 0); begin S(V'HIGH downto 0) := to_signed(V); S(SDLEN-1 downto V'HIGH+1) := (others => V(V'HIGH)); return(S); end function; function EXTS64(V : std_logic_vector) return signed is variable S : signed(LDLEN-1 downto 0); begin S(V'HIGH downto 0) := to_signed(V); S(LDLEN-1 downto V'HIGH+1) := (others => V(V'HIGH)); return(S); end function; end RV01_ARITH_PKG;