]> rtime.felk.cvut.cz Git - fpga/lx-cpu1/tumbl.git/blobdiff - hw/decode.vhd
Customized instruction set (with compatibility mode)
[fpga/lx-cpu1/tumbl.git] / hw / decode.vhd
index b9004590f89084af80734b7209943f2529ad7b5e..9d02421b452af95b470dd9183e193f961a3b91c6 100644 (file)
@@ -25,8 +25,9 @@ USE WORK.mbl_Pkg.all;
 ENTITY decode IS
 --------------------------------------------------------------------------------
     GENERIC (
-        USE_HW_MUL_g : BOOLEAN := FALSE;
-        USE_BARREL_g : BOOLEAN := FALSE
+        USE_HW_MUL_g : BOOLEAN := TRUE;
+        USE_BARREL_g : BOOLEAN := TRUE;
+        COMPATIBILITY_MODE_g : BOOLEAN := FALSE
         );
     PORT (
         IF2ID_i     :  IN IF2ID_Type;
@@ -37,8 +38,8 @@ ENTITY decode IS
         --
         INT_CTRL_i  :  IN INT_CTRL_Type;
         ID2CTRL_o   : OUT ID2CTRL_Type;
-                               --
-                               noLiteOpc_s : OUT STD_LOGIC
+        --
+        noLiteOpc_o : OUT STD_LOGIC
         );
 END ENTITY decode;
 
@@ -59,7 +60,6 @@ p_decode:
         VARIABLE rA_v            : STD_LOGIC_VECTOR ( 4 DOWNTO 0);
         VARIABLE rB_v            : STD_LOGIC_VECTOR ( 4 DOWNTO 0);
         VARIABLE IMM16_v         : STD_LOGIC_VECTOR (15 DOWNTO 0);
-        VARIABLE FSL_Mode_v      : STD_LOGIC_VECTOR ( 4 DOWNTO 0);
         VARIABLE code_x26_v      : STD_LOGIC_VECTOR ( 2 DOWNTO 0);
         VARIABLE IMM_Lock_v      : STD_LOGIC;
         VARIABLE alu_Action_v    : ALU_ACTION_Type;
@@ -83,7 +83,9 @@ p_decode:
         rB_v            := instruction_v (15 DOWNTO 11);
         IMM16_v         := instruction_v (15 DOWNTO  0);
         IMM_Lock_v      := '0';
-        delayBit_v      := '0';
+        IF (COMPATIBILITY_MODE_g = TRUE) THEN
+            delayBit_v      := '0';
+        END IF;
         alu_Cin_v       := CIN_ZERO;
         alu_Action_v    := A_NOP;
         msr_Action_v    := KEEP_CARRY;
@@ -91,12 +93,11 @@ p_decode:
         mem_Action_v    := NO_MEM;
         transfer_Size_v := WORD;
         wrb_Action_v    := WRB_EX;
-        FSL_Mode_v      := "01010";
         -- for decoding SEXT16, SEXT8, SRC, SRC or SRL
         code_x26_v      := instruction_v(6) & instruction_v(5) & instruction_v(0);
         int_busy_v      := INT_CTRL_i.int_busy;
         -- for debugging purposes
-        noLiteOpc_s     <= '0';
+        noLiteOpc_o     <= '0';
 
         IF (INT_CTRL_i.setup_int = '1') THEN
 
@@ -122,8 +123,8 @@ p_decode:
 
             CASE opcIx_v (5 DOWNTO 4) IS
 
-                WHEN "00" =>                                            -- ADD / RSUB / CMP
-                    IF (opcIx_v(0) = '1') THEN                          -- RSUB / CMP
+                WHEN "00" =>                                            -- ADD / RSUB
+                    IF (opcIx_v(0) = '1') THEN                          -- RSUB
                         alu_Op1_v := ALU_IN_NOT_REGA;
                     END IF;
                     IF (opcIx_v(1) = '0') THEN                          -- xxx
@@ -135,8 +136,8 @@ p_decode:
                     ELSE                                                -- xxxC
                         alu_Cin_v := FROM_MSR;
                     END IF;
-                    IF ((opcIx_v(3 DOWNTO 0) = "0101") AND (IMM16_v(0)= '1')) THEN
-                    -- special CMP(U) and not RSUB(I)K
+                    IF ((COMPATIBILITY_MODE_g = TRUE) AND (opcIx_v(3 DOWNTO 0) = "0101") AND (IMM16_v(0)= '1')) THEN
+                    -- special CMP(U) and not RSUB(I)K, supported only in compatibility mode
                         IF (IMM16_v(1) = '1') THEN                        -- U-bit set, CMPU
                             alu_Action_v := A_CMPU;
                         ELSE
@@ -149,13 +150,13 @@ p_decode:
                         END IF;
                     END IF;
 
-                WHEN "01" =>                                            -- MUL / BS / FSL
+                WHEN "01" =>                                            -- MUL / BS
                     CASE opcIx_v (2 DOWNTO 0) IS
                         WHEN "000" =>                                   -- MUL
                             IF (USE_HW_MUL_g = TRUE) THEN
                                 alu_Action_v := A_MUL;
                             ELSE
-                                noLiteOpc_s <= '1';
+                                noLiteOpc_o <= '1';
                             END IF;
                         WHEN "001" =>                                   -- BS
                             IF (USE_BARREL_g = TRUE) THEN
@@ -169,24 +170,20 @@ p_decode:
                                     END IF;
                                 END IF;
                             ELSE
-                                noLiteOpc_s <= '1';
-                            END IF;
-                        WHEN "011" =>                                   -- FSL
-                            IF (opcIx_v(3) = '0') THEN
-                                FSL_Mode_v := instruction_v(10 DOWNTO  6);
-                            ELSE
-                                FSL_Mode_v := instruction_v(15 DOWNTO 11);
+                                noLiteOpc_o <= '1';
                             END IF;
-                            IF (FSL_Mode_v(4) = '0') THEN
-                                alu_Action_v := A_FSL_GET;
-                                wrb_Action_v := WRB_FSL;
+                        WHEN "010" =>                                             -- CMP / CMPU / CMPI (new format)
+                            IF (COMPATIBILITY_MODE_g = FALSE) THEN
+                                IF (IMM16_v(5) = '1') THEN   -- U-bit set, CMPU
+                                    alu_Action_v := A_CMPU;
+                                ELSE
+                                    alu_Action_v := A_CMP;
+                                END IF;
                             ELSE
-                                alu_Action_v := A_FSL_PUT;
-                                wrb_Action_v := NO_WRB;
+                                noLiteOpc_o <= '1';
                             END IF;
-                            msr_Action_v := UPDATE_CARRY;
                         WHEN OTHERS =>
-                            noLiteOpc_s <= '1';
+                            noLiteOpc_o <= '1';
                     END CASE;
 
                 WHEN "10" =>
@@ -201,7 +198,7 @@ p_decode:
                                     WHEN "10" =>                        -- SRL
                                         alu_Cin_v := CIN_ZERO;
                                     WHEN OTHERS =>
-                                        noLiteOpc_s <= '1';
+                                        noLiteOpc_o <= '1';
                                 END CASE;
                                 alu_Action_v := A_SHIFT;
                                 msr_Action_v := UPDATE_CARRY;
@@ -210,7 +207,7 @@ p_decode:
                             WHEN "111" =>                               -- SEXT16
                                 alu_Action_v := A_SEXT16;
                             WHEN OTHERS  =>
-                                noLiteOpc_s  <= '1';
+                                noLiteOpc_o  <= '1';
                         END CASE;
                     ELSIF (opcIx_v (3 DOWNTO 0) = "1100") THEN          -- IMM
                         IMM_Lock_v   := '1';
@@ -218,19 +215,19 @@ p_decode:
                         alu_Action_v := A_NOP;
                         wrb_Action_v := NO_WRB;
                     ELSIF (opcIx_v (3 DOWNTO 0) = "1101") THEN
-                        CASE rD_v IS
-                            WHEN "10001" =>                             -- RTID
+                        CASE rD_v (3 DOWNTO 0) IS
+                            WHEN "0001" =>                              -- RTI(D)
                                 int_busy_v := '0';
-                            WHEN "10000" =>                             -- RTSD
---                          WHEN "10010" =>                             -- RTBD
---                          WHEN "10100" =>                             -- RTED
+                            WHEN "0000" =>                              -- RTS(D)
                             WHEN OTHERS  =>
-                                noLiteOpc_s <= '1';
+                                noLiteOpc_o <= '1';
                         END CASE;
                         alu_Action_v    := A_ADD;
                         branch_Action_v := BR;
                         wrb_Action_v    := NO_WRB;
-                        delayBit_v      := '1';
+                        IF (COMPATIBILITY_MODE_g = TRUE) THEN
+                            delayBit_v  := rD_v(4);
+                        END IF;
                     ELSIF (opcIx_v (3 DOWNTO 0) = "0101") THEN
                         CASE IMM16_v IS
                             WHEN X"8001" =>                             -- MFS (MSR only)
@@ -239,7 +236,7 @@ p_decode:
                                 alu_Action_v := A_MTS;
                                 wrb_Action_v := NO_WRB;
                             WHEN OTHERS  =>
-                                noLiteOpc_s  <= '1';
+                                noLiteOpc_o  <= '1';
                         END CASE;
                         rB_v := (OTHERS => '0');    -- in order to prevent occasional hazards (r16, r24)
                     ELSE
@@ -257,7 +254,7 @@ p_decode:
                                 ELSE
                                     alu_Op2_v := ALU_IN_NOT_IMM;
                                 END IF;
-                            WHEN "110" =>                               -- BR(I)
+                            WHEN "110" =>                               -- BR(I)(D)
                                 IF (rA_v(2) = '1') THEN
                                     branch_Action_v := BRL;
                                 ELSE
@@ -269,10 +266,10 @@ p_decode:
                                 ELSE
                                     alu_Op1_v := ALU_IN_PC;
                                 END IF;
-                                IF (rA_v(4) = '1') THEN
-                                    delayBit_v  := '1';
-                                END IF;
                                 alu_Action_v    := A_ADD;
+                                IF (COMPATIBILITY_MODE_g = TRUE) THEN
+                                    delayBit_v  := rA_v(4);
+                                END IF;
                             WHEN "111" =>
                                 CASE rD_v(3 DOWNTO 0) IS
                                     WHEN "0000" =>                      -- BEQ
@@ -288,36 +285,43 @@ p_decode:
                                     WHEN "0101" =>                      -- BGE
                                         branch_Action_v := BGE;
                                     WHEN OTHERS =>
-                                        noLiteOpc_s <= '1';
+                                        noLiteOpc_o <= '1';
                                 END CASE;
                                 alu_Action_v := A_ADD;
                                 alu_Op1_v    := ALU_IN_PC;
-                                delayBit_v   := rD_v(4);
-                            wrb_Action_v := NO_WRB;     -- evaluate and update/overwrite in exeq
+                                IF (COMPATIBILITY_MODE_g = TRUE) THEN
+                                    delayBit_v := rD_v(4);
+                                END IF;
+                                wrb_Action_v := NO_WRB;     -- evaluate and update/overwrite in exeq
                             WHEN OTHERS =>
-                                noLiteOpc_s  <= '1';
+                                noLiteOpc_o  <= '1';
                         END CASE;
                     END IF;
 
                 WHEN "11" =>
-                    alu_Action_v :=  A_ADD;
-                    CASE opcIx_v (1 DOWNTO 0) IS
-                        WHEN "00"   => transfer_Size_v := BYTE;
-                        WHEN "01"   => transfer_Size_v := HALFWORD;
-                        WHEN "10"   => transfer_Size_v := WORD;
-                        WHEN OTHERS =>
-                            noLiteOpc_s <= '1';
-                    END CASE;
-                    IF (opcIx_v(2) = '0') THEN
-                        mem_Action_v := RD_MEM;
-                        wrb_Action_v := WRB_MEM;
-                    ELSE
-                        mem_Action_v := WR_MEM;
+                    IF (opcIx_v (3 DOWNTO 0) = "1111") THEN             -- HALT
+                        alu_Action_v :=  A_HALT;
                         wrb_Action_v := NO_WRB;
+                    ELSE
+                        alu_Action_v :=  A_ADD;
+                        CASE opcIx_v (1 DOWNTO 0) IS
+                            WHEN "00"   => transfer_Size_v := BYTE;
+                            WHEN "01"   => transfer_Size_v := HALFWORD;
+                            WHEN "10"   => transfer_Size_v := WORD;
+                            WHEN OTHERS =>
+                                noLiteOpc_o <= '1';
+                        END CASE;
+                        IF (opcIx_v(2) = '0') THEN
+                            mem_Action_v := RD_MEM;
+                            wrb_Action_v := WRB_MEM;
+                        ELSE
+                            mem_Action_v := WR_MEM;
+                            wrb_Action_v := NO_WRB;
+                        END IF;
                     END IF;
 
                 WHEN OTHERS =>
-                    noLiteOpc_s  <= '1';
+                    noLiteOpc_o  <= '1';
 
             END CASE;
 
@@ -342,16 +346,12 @@ p_decode:
         ID2EX_o.mem_Action       <= mem_Action_v;
         ID2EX_o.transfer_Size    <= transfer_Size_v;
         ID2EX_o.wrb_Action       <= wrb_Action_v;
-        ID2EX_o.FSL_Non_blocking <= FSL_Mode_v(3);
-        ID2EX_o.FSL_Control      <= FSL_Mode_v(2);
-        ID2EX_o.FSL_Test         <= FSL_Mode_v(1);
-        ID2EX_o.FSL_Atomic       <= FSL_Mode_v(0);
         --
-        ID2CTRL_o.delayBit      <= delayBit_v;
+        IF (COMPATIBILITY_MODE_g = TRUE) THEN
+            ID2CTRL_o.delayBit      <= delayBit_v;
+        END IF;
         ID2CTRL_o.int_busy      <= int_busy_v;
 
-
-
     END PROCESS;
 
 END ARCHITECTURE rtl;