OpenCores
URL https://opencores.org/ocsvn/c16/c16/trunk

Subversion Repositories c16

[/] [c16/] [trunk/] [vhdl/] [alu8.vhd] - Diff between revs 25 and 26

Only display areas with differences | Details | Blame | View Log

Rev 25 Rev 26
library IEEE;
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
 
 
--  Uncomment the following lines to use the declarations that are
--  Uncomment the following lines to use the declarations that are
--  provided for instantiating Xilinx primitive components.
--  provided for instantiating Xilinx primitive components.
--library UNISIM;
--library UNISIM;
--use UNISIM.VComponents.all;
--use UNISIM.VComponents.all;
 
 
use work.cpu_pack.ALL;
use work.cpu_pack.ALL;
 
 
entity alu8 is
entity alu8 is
        PORT(   CLK_I : in   std_logic;
        PORT(   CLK_I : in   std_logic;
                        T2    : in   std_logic;
                        T2    : in   std_logic;
                        CLR   : in   std_logic;
                        CLR   : in   std_logic;
                        CE    : in   std_logic;
                        CE    : in   std_logic;
 
 
                        ALU_OP : in  std_logic_vector( 4 downto 0);
                        ALU_OP : in  std_logic_vector( 4 downto 0);
                        XX     : in  std_logic_vector(15 downto 0);
                        XX     : in  std_logic_vector(15 downto 0);
                        YY     : in  std_logic_vector(15 downto 0);
                        YY     : in  std_logic_vector(15 downto 0);
 
 
                        ZZ     : out std_logic_vector(15 downto 0)
                        ZZ     : out std_logic_vector(15 downto 0)
                );
                );
end alu8;
end alu8;
 
 
architecture Behavioral of alu8 is
architecture Behavioral of alu8 is
 
 
 
 
        function sh_mask(Y    : unsigned(3 downto 0);
        function sh_mask(Y    : unsigned(3 downto 0);
                                         YMAX : unsigned(3 downto 0);
                                         YMAX : unsigned(3 downto 0);
                         LR   : std_logic;
                         LR   : std_logic;
                         FILL : std_logic;
                         FILL : std_logic;
                                         X    : std_logic) return std_logic is
                                         X    : std_logic) return std_logic is
 
 
        begin
        begin
                if (YMAX >= Y) then                                                                     -- Y small
                if (YMAX >= Y) then                                                                     -- Y small
                        if (LR = '1') then              return  X;                      -- LSL
                        if (LR = '1') then              return  X;                      -- LSL
                        else                                    return  FILL;           -- LSR
                        else                                    return  FILL;           -- LSR
                        end if;
                        end if;
                else                                                                                            -- Y big
                else                                                                                            -- Y big
                        if (LR = '1') then              return  FILL;           -- LSL
                        if (LR = '1') then              return  FILL;           -- LSL
                        else                                    return  X;                      -- ASR/LSR
                        else                                    return  X;                      -- ASR/LSR
                        end if;
                        end if;
                end if;
                end if;
        end;
        end;
 
 
        function b8(A : std_logic) return std_logic_vector is
        function b8(A : std_logic) return std_logic_vector is
        begin
        begin
                return A & A & A & A & A & A & A & A;
                return A & A & A & A & A & A & A & A;
        end;
        end;
 
 
        function b16(A : std_logic) return std_logic_vector is
        function b16(A : std_logic) return std_logic_vector is
        begin
        begin
                return b8(A) & b8(A);
                return b8(A) & b8(A);
        end;
        end;
 
 
        function aoxn(A : std_logic_vector(3 downto 0)) return std_logic is
        function aoxn(A : std_logic_vector(3 downto 0)) return std_logic is
        begin
        begin
                case A is
                case A is
                        -- and
                        -- and
                        when "0000" =>  return '0';
                        when "0000" =>  return '0';
                        when "0001" =>  return '0';
                        when "0001" =>  return '0';
                        when "0010" =>  return '0';
                        when "0010" =>  return '0';
                        when "0011" =>  return '1';
                        when "0011" =>  return '1';
                        -- or
                        -- or
                        when "0100" =>  return '0';
                        when "0100" =>  return '0';
                        when "0101" =>  return '1';
                        when "0101" =>  return '1';
                        when "0110" =>  return '1';
                        when "0110" =>  return '1';
                        when "0111" =>  return '1';
                        when "0111" =>  return '1';
                        -- xor
                        -- xor
                        when "1000" =>  return '0';
                        when "1000" =>  return '0';
                        when "1001" =>  return '1';
                        when "1001" =>  return '1';
                        when "1010" =>  return '1';
                        when "1010" =>  return '1';
                        when "1011" =>  return '0';
                        when "1011" =>  return '0';
                        -- not Y
                        -- not Y
                        when "1100" =>  return '1';
                        when "1100" =>  return '1';
                        when "1101" =>  return '0';
                        when "1101" =>  return '0';
                        when "1110" =>  return '1';
                        when "1110" =>  return '1';
                        when others =>  return '0';
                        when others =>  return '0';
                end case;
                end case;
        end;
        end;
 
 
        signal MD_OR     : std_logic_vector(15 downto 0);                -- Multiplicator/Divisor
        signal MD_OR     : std_logic_vector(15 downto 0);                -- Multiplicator/Divisor
        signal PROD_REM  : std_logic_vector(31 downto 0);
        signal PROD_REM  : std_logic_vector(31 downto 0);
        signal MD_OP     : std_logic;                                           -- operation D/M, S/U
        signal MD_OP     : std_logic;                                           -- operation D/M, S/U
        signal QP_NEG    : std_logic;                                           -- product / quotient negative
        signal QP_NEG    : std_logic;                                           -- product / quotient negative
        signal RM_NEG    : std_logic;                                           -- remainder negative
        signal RM_NEG    : std_logic;                                           -- remainder negative
 
 
begin
begin
 
 
        alumux: process(ALU_OP, MD_OP, XX, YY, QP_NEG, RM_NEG, PROD_REM)
        alumux: process(ALU_OP, MD_OP, XX, YY, QP_NEG, RM_NEG, PROD_REM)
 
 
                variable MASKED_X : std_logic_vector(15 downto 0);
                variable MASKED_X : std_logic_vector(15 downto 0);
                variable SCNT     : unsigned(3 downto 0);
                variable SCNT     : unsigned(3 downto 0);
                variable SFILL    : std_logic;
                variable SFILL    : std_logic;
                variable ROL1     : std_logic_vector(15 downto 0);
                variable ROL1     : std_logic_vector(15 downto 0);
                variable ROL2     : std_logic_vector(15 downto 0);
                variable ROL2     : std_logic_vector(15 downto 0);
                variable ROL4     : std_logic_vector(15 downto 0);
                variable ROL4     : std_logic_vector(15 downto 0);
                variable ROL8     : std_logic_vector(15 downto 0);
                variable ROL8     : std_logic_vector(15 downto 0);
                variable X_GE_Y   : std_logic;  -- signed   X >=  Y
                variable X_GE_Y   : std_logic;  -- signed   X >=  Y
                variable X_HS_Y   : std_logic;  -- unsigned X >=  Y
                variable X_HS_Y   : std_logic;  -- unsigned X >=  Y
                variable X_HSGE_Y : std_logic;  -- any      X >=  Y
                variable X_HSGE_Y : std_logic;  -- any      X >=  Y
                variable X_EQ_Y   : std_logic;  -- signed   X ==  Y
                variable X_EQ_Y   : std_logic;  -- signed   X ==  Y
                variable X_CMP_Y  : std_logic;
                variable X_CMP_Y  : std_logic;
 
 
        begin
        begin
                MASKED_X := XX and b16(ALU_OP(0));
                MASKED_X := XX and b16(ALU_OP(0));
                SFILL    := ALU_OP(0) and XX(15);
                SFILL    := ALU_OP(0) and XX(15);
 
 
                if (ALU_OP(1) = '1') then       -- LSL
                if (ALU_OP(1) = '1') then       -- LSL
                        SCNT := UNSIGNED(YY(3 downto 0));
                        SCNT := UNSIGNED(YY(3 downto 0));
                else                                            -- LSR / ASR
                else                                            -- LSR / ASR
                        SCNT := "0000" - UNSIGNED(YY(3 downto 0));
                        SCNT := "0000" - UNSIGNED(YY(3 downto 0));
                end if;
                end if;
 
 
                if (SCNT(0) = '0') then   ROL1 := XX;
                if (SCNT(0) = '0') then   ROL1 := XX;
                else                                    ROL1 := XX(14 downto 0) & XX(15);
                else                                    ROL1 := XX(14 downto 0) & XX(15);
                end if;
                end if;
 
 
                if (SCNT(1) = '0') then  ROL2 := ROL1;
                if (SCNT(1) = '0') then  ROL2 := ROL1;
                else                                    ROL2 := ROL1(13 downto 0) & ROL1(15 downto 14);
                else                                    ROL2 := ROL1(13 downto 0) & ROL1(15 downto 14);
                end if;
                end if;
 
 
                if (SCNT(2) = '0') then  ROL4 := ROL2;
                if (SCNT(2) = '0') then  ROL4 := ROL2;
                else                                    ROL4 := ROL2(11 downto 0) & ROL2(15 downto 12);
                else                                    ROL4 := ROL2(11 downto 0) & ROL2(15 downto 12);
                end if;
                end if;
 
 
                if (SCNT(3) = '0') then  ROL8 := ROL4;
                if (SCNT(3) = '0') then  ROL8 := ROL4;
                else                                    ROL8 := ROL4(7 downto 0) & ROL4(15 downto 8);
                else                                    ROL8 := ROL4(7 downto 0) & ROL4(15 downto 8);
                end if;
                end if;
 
 
                if (XX = YY) then               X_EQ_Y := '1';
                if (XX = YY) then               X_EQ_Y := '1';
                else                                    X_EQ_Y := '0';
                else                                    X_EQ_Y := '0';
                end if;
                end if;
 
 
                if (UNSIGNED(XX) >= UNSIGNED(YY)) then          X_HSGE_Y := '1';
                if (UNSIGNED(XX) >= UNSIGNED(YY)) then          X_HSGE_Y := '1';
                else                                                                            X_HSGE_Y := '0';
                else                                                                            X_HSGE_Y := '0';
                end if;
                end if;
 
 
                if (XX(15) /= YY(15)) then              -- different sign/high bit
                if (XX(15) /= YY(15)) then              -- different sign/high bit
                        X_HS_Y := XX(15);               -- X ia bigger iff high bit set
                        X_HS_Y := XX(15);               -- X ia bigger iff high bit set
                        X_GE_Y := YY(15);               -- X is bigger iff Y negative
                        X_GE_Y := YY(15);               -- X is bigger iff Y negative
                else                                                    -- same sign/high bit: GE == HS
                else                                                    -- same sign/high bit: GE == HS
                        X_HS_Y := X_HSGE_Y;
                        X_HS_Y := X_HSGE_Y;
                        X_GE_Y := X_HSGE_Y;
                        X_GE_Y := X_HSGE_Y;
                end if;
                end if;
 
 
                case ALU_OP is
                case ALU_OP is
                        when    ALU_X_HS_Y      =>      X_CMP_Y :=      X_HS_Y;
                        when    ALU_X_HS_Y      =>      X_CMP_Y :=      X_HS_Y;
                        when    ALU_X_LO_Y      =>      X_CMP_Y := not  X_HS_Y;
                        when    ALU_X_LO_Y      =>      X_CMP_Y := not  X_HS_Y;
                        when    ALU_X_HI_Y      =>      X_CMP_Y :=      X_HS_Y and not X_EQ_Y;
                        when    ALU_X_HI_Y      =>      X_CMP_Y :=      X_HS_Y and not X_EQ_Y;
                        when    ALU_X_LS_Y      =>      X_CMP_Y := not (X_HS_Y and not X_EQ_Y);
                        when    ALU_X_LS_Y      =>      X_CMP_Y := not (X_HS_Y and not X_EQ_Y);
                        when    ALU_X_GE_Y      =>      X_CMP_Y :=      X_GE_Y;
                        when    ALU_X_GE_Y      =>      X_CMP_Y :=      X_GE_Y;
                        when    ALU_X_LT_Y      =>      X_CMP_Y := not  X_GE_Y;
                        when    ALU_X_LT_Y      =>      X_CMP_Y := not  X_GE_Y;
                        when    ALU_X_GT_Y      =>      X_CMP_Y :=      X_GE_Y and not X_EQ_Y;
                        when    ALU_X_GT_Y      =>      X_CMP_Y :=      X_GE_Y and not X_EQ_Y;
                        when    ALU_X_LE_Y      =>      X_CMP_Y := not (X_GE_Y and not X_EQ_Y);
                        when    ALU_X_LE_Y      =>      X_CMP_Y := not (X_GE_Y and not X_EQ_Y);
                        when    ALU_X_EQ_Y      =>      X_CMP_Y :=      X_EQ_Y;
                        when    ALU_X_EQ_Y      =>      X_CMP_Y :=      X_EQ_Y;
                        when    others          =>      X_CMP_Y := not  X_EQ_Y;
                        when    others          =>      X_CMP_Y := not  X_EQ_Y;
                end case;
                end case;
 
 
                ZZ <= X"0000";
                ZZ <= X"0000";
 
 
                case ALU_OP is
                case ALU_OP is
                        when    ALU_X_HS_Y | ALU_X_LO_Y | ALU_X_HI_Y | ALU_X_LS_Y |
                        when    ALU_X_HS_Y | ALU_X_LO_Y | ALU_X_HI_Y | ALU_X_LS_Y |
                                        ALU_X_GE_Y | ALU_X_LT_Y | ALU_X_GT_Y | ALU_X_LE_Y |
                                        ALU_X_GE_Y | ALU_X_LT_Y | ALU_X_GT_Y | ALU_X_LE_Y |
                                        ALU_X_EQ_Y | ALU_X_NE_Y =>
                                        ALU_X_EQ_Y | ALU_X_NE_Y =>
                                ZZ  <= b16(X_CMP_Y);
                                ZZ  <= b16(X_CMP_Y);
 
 
                        when    ALU_NEG_Y |     ALU_X_SUB_Y =>
                        when    ALU_NEG_Y |     ALU_X_SUB_Y =>
                                ZZ  <= MASKED_X - YY;
                                ZZ  <= MASKED_X - YY;
 
 
                        when    ALU_MOVE_Y | ALU_X_ADD_Y =>
                        when    ALU_MOVE_Y | ALU_X_ADD_Y =>
                                ZZ  <= MASKED_X + YY;
                                ZZ  <= MASKED_X + YY;
 
 
                        when    ALU_X_AND_Y | ALU_X_OR_Y  | ALU_X_XOR_Y | ALU_NOT_Y =>
                        when    ALU_X_AND_Y | ALU_X_OR_Y  | ALU_X_XOR_Y | ALU_NOT_Y =>
                                for i in 0 to 15 loop
                                for i in 0 to 15 loop
                                        ZZ(i) <= aoxn(ALU_OP(1 downto 0) & XX(i) & YY(i));
                                        ZZ(i) <= aoxn(ALU_OP(1 downto 0) & XX(i) & YY(i));
                                end loop;
                                end loop;
 
 
                        when    ALU_X_LSR_Y | ALU_X_ASR_Y | ALU_X_LSL_Y =>
                        when    ALU_X_LSR_Y | ALU_X_ASR_Y | ALU_X_LSL_Y =>
                                for i in 0 to 15 loop
                                for i in 0 to 15 loop
                                        ZZ(i) <= sh_mask(SCNT, CONV_UNSIGNED(i, 4),
                                        ZZ(i) <= sh_mask(SCNT, CONV_UNSIGNED(i, 4),
                                                                         ALU_OP(1), SFILL, ROL8(i));
                                                                         ALU_OP(1), SFILL, ROL8(i));
                                end loop;
                                end loop;
 
 
                        when    ALU_X_MIX_Y =>
                        when    ALU_X_MIX_Y =>
                                        ZZ(15 downto 8) <= YY(7 downto 0);
                                        ZZ(15 downto 8) <= YY(7 downto 0);
                                        ZZ( 7 downto 0) <= XX(7 downto 0);
                                        ZZ( 7 downto 0) <= XX(7 downto 0);
 
 
                        when    ALU_MUL_IU | ALU_MUL_IS |
                        when    ALU_MUL_IU | ALU_MUL_IS |
                                        ALU_DIV_IU | ALU_DIV_IS | ALU_MD_STP => -- mult/div ini/step
                                        ALU_DIV_IU | ALU_DIV_IS | ALU_MD_STP => -- mult/div ini/step
                                        ZZ <= PROD_REM(15 downto 0);
                                        ZZ <= PROD_REM(15 downto 0);
 
 
                        when    ALU_MD_FIN =>   -- mult/div
                        when    ALU_MD_FIN =>   -- mult/div
                                if (QP_NEG = '0') then   ZZ <= PROD_REM(15 downto 0);
                                if (QP_NEG = '0') then   ZZ <= PROD_REM(15 downto 0);
                                else                                    ZZ <= X"0000" - PROD_REM(15 downto 0);
                                else                                    ZZ <= X"0000" - PROD_REM(15 downto 0);
                                end if;
                                end if;
 
 
                        when    others =>       -- modulo
                        when    others =>       -- modulo
                                if (RM_NEG = '0') then   ZZ <= PROD_REM(31 downto 16);
                                if (RM_NEG = '0') then   ZZ <= PROD_REM(31 downto 16);
                                else                                    ZZ <= X"0000" - PROD_REM(31 downto 16);
                                else                                    ZZ <= X"0000" - PROD_REM(31 downto 16);
                                end if;
                                end if;
                end case;
                end case;
        end process;
        end process;
 
 
        muldiv: process(CLK_I)
        muldiv: process(CLK_I)
 
 
                variable POS_YY : std_logic_vector(15 downto 0);
                variable POS_YY : std_logic_vector(15 downto 0);
                variable POS_XX : std_logic_vector(15 downto 0);
                variable POS_XX : std_logic_vector(15 downto 0);
                variable DIFF   : std_logic_vector(16 downto 0);
                variable DIFF   : std_logic_vector(16 downto 0);
                variable SUM    : std_logic_vector(16 downto 0);
                variable SUM    : std_logic_vector(16 downto 0);
 
 
        begin
        begin
                if (rising_edge(CLK_I)) then
                if (rising_edge(CLK_I)) then
                        if (T2 = '1') then
                        if (T2 = '1') then
                                if (CLR = '1') then
                                if (CLR = '1') then
                                        PROD_REM <= X"00000000";        -- product/remainder
                                        PROD_REM <= X"00000000";        -- product/remainder
                                        MD_OR    <= X"0000";            -- multiplicator/divisor
                                        MD_OR    <= X"0000";            -- multiplicator/divisor
                                        MD_OP    <= '0';                 -- mult(0)/div(1)
                                        MD_OP    <= '0';                 -- mult(0)/div(1)
                                        QP_NEG   <= '0';                 -- quotient/product negative
                                        QP_NEG   <= '0';                 -- quotient/product negative
                                        RM_NEG   <= '0';                 -- remainder negative
                                        RM_NEG   <= '0';                 -- remainder negative
                                elsif (CE = '1') then
                                elsif (CE = '1') then
                                        SUM  := ('0' & PROD_REM(31 downto 16)) + ('0' & MD_OR);
                                        SUM  := ('0' & PROD_REM(31 downto 16)) + ('0' & MD_OR);
                                        DIFF := ('0' & PROD_REM(30 downto 15)) - ('0' & MD_OR);
                                        DIFF := ('0' & PROD_REM(30 downto 15)) - ('0' & MD_OR);
 
 
                                        if (XX(15) = '0') then   POS_XX := XX;
                                        if (XX(15) = '0') then   POS_XX := XX;
                                        else                                    POS_XX := X"0000" - XX;
                                        else                                    POS_XX := X"0000" - XX;
                                        end if;
                                        end if;
 
 
                                        if (YY(15) = '0') then   POS_YY := YY;
                                        if (YY(15) = '0') then   POS_YY := YY;
                                        else                                    POS_YY := X"0000" - YY;
                                        else                                    POS_YY := X"0000" - YY;
                                        end if;
                                        end if;
 
 
                                        case  ALU_OP is
                                        case  ALU_OP is
                                                when    ALU_MUL_IU | ALU_MUL_IS | ALU_DIV_IU | ALU_DIV_IS =>
                                                when    ALU_MUL_IU | ALU_MUL_IS | ALU_DIV_IU | ALU_DIV_IS =>
                                                        MD_OP    <= ALU_OP(1);          -- div / mult
                                                        MD_OP    <= ALU_OP(1);          -- div / mult
                                                        MD_OR    <= POS_YY;             -- multiplicator/divisor
                                                        MD_OR    <= POS_YY;             -- multiplicator/divisor
                                                        QP_NEG   <= ALU_OP(0) and (XX(15) xor YY(15));
                                                        QP_NEG   <= ALU_OP(0) and (XX(15) xor YY(15));
                                                        RM_NEG   <= ALU_OP(0) and  XX(15);
                                                        RM_NEG   <= ALU_OP(0) and  XX(15);
                                                        PROD_REM <= X"0000" & POS_XX;
                                                        PROD_REM <= X"0000" & POS_XX;
 
 
                                                when    ALU_MD_STP =>
                                                when    ALU_MD_STP =>
                                                        if (MD_OP = '0') then            -- multiplication step
                                                        if (MD_OP = '0') then            -- multiplication step
 
 
                                                                PROD_REM(15 downto 0) <= PROD_REM(16 downto 1);
                                                                PROD_REM(15 downto 0) <= PROD_REM(16 downto 1);
                                                                if (PROD_REM(0) = '0') then
                                                                if (PROD_REM(0) = '0') then
                                                                                PROD_REM(31 downto 15) <=
                                                                                PROD_REM(31 downto 15) <=
                                                                                '0' & PROD_REM(31 downto 16);
                                                                                '0' & PROD_REM(31 downto 16);
                                                                else
                                                                else
                                                                        PROD_REM(31 downto 15) <= SUM;
                                                                        PROD_REM(31 downto 15) <= SUM;
                                                                end if;
                                                                end if;
                                                        else                                            -- division step
                                                        else                                            -- division step
                                                                if (DIFF(16) = '1') then        -- carry: small remainder
                                                                if (DIFF(16) = '1') then        -- carry: small remainder
                                                                        PROD_REM(31 downto 16) <= PROD_REM(30 downto 15);
                                                                        PROD_REM(31 downto 16) <= PROD_REM(30 downto 15);
                                                                else
                                                                else
                                                                        PROD_REM(31 downto 16) <= DIFF(15 downto 0);
                                                                        PROD_REM(31 downto 16) <= DIFF(15 downto 0);
                                                                end if;
                                                                end if;
 
 
                                                                PROD_REM(15 downto 1) <= PROD_REM(14 downto 0);
                                                                PROD_REM(15 downto 1) <= PROD_REM(14 downto 0);
                                                                PROD_REM(0) <= not DIFF(16);
                                                                PROD_REM(0) <= not DIFF(16);
                                                        end if;
                                                        end if;
 
 
                                                when    others =>
                                                when    others =>
                                        end case;
                                        end case;
                                end if;
                                end if;
                        end if;
                        end if;
                end if;
                end if;
        end process;
        end process;
 
 
end Behavioral;
end Behavioral;
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.