]> rtime.felk.cvut.cz Git - fpga/lx-cpu1/tumbl.git/blobdiff - hw/mem.vhd
Reformat code and restructure decoder to save LUTs and fit critical path
[fpga/lx-cpu1/tumbl.git] / hw / mem.vhd
index 6d549820ca90e49b62b7c09910c90a8a11896bf2..139451c0385c04837133479a957b475754eed535 100644 (file)
 --  Remarks:
 --------------------------------------------------------------------------------
 
-
 LIBRARY IEEE;
 USE IEEE.std_logic_1164.all;
 USE work.mbl_Pkg.all;
 
-
 --------------------------------------------------------------------------------
 ENTITY mem IS
 --------------------------------------------------------------------------------
-    PORT (
-        EX2MEM_i    :  IN EX2MEM_Type;
-        --
-        DMEMB_i     :  IN DMEMB2CORE_Type;
-        DMEMB_o     : OUT CORE2DMEMB_Type;
-        --
-        MEM_REG_i   :  IN MEM_REG_Type;
-        MEM_REG_o   : OUT MEM_REG_Type;
-        --
-        MEM_WRB_o   : OUT WRB_Type;
-        MEM2CTRL_o  : OUT MEM2CTRL_Type
-        );
+       PORT
+       (
+               EX2MEM_i    :  IN EX2MEM_Type;
+               --
+               DMEMB_i     :  IN DMEMB2CORE_Type;
+               DMEMB_o     : OUT CORE2DMEMB_Type;
+               --
+               MEM_REG_i   :  IN MEM_REG_Type;
+               MEM_REG_o   : OUT MEM_REG_Type;
+               --
+               MEM_WRB_o   : OUT WRB_Type;
+               MEM2CTRL_o  : OUT MEM2CTRL_Type
+       );
 END ENTITY mem;
 
-
 --------------------------------------------------------------------------------
 ARCHITECTURE rtl OF mem IS
 --------------------------------------------------------------------------------
 
 BEGIN
 
-    -- writeback in case of reads from the data memory bus:
-    -- delay wrb-ctrl signals (see core_ctrl) to stay in sync
-    -- with synchronous dmem data output
-    -- Following are only the unconditional pass-through signals. More are in the p_mem process.
-    MEM_REG_o.wrb_Action  <= EX2MEM_i.wrb_Action;
-    MEM_REG_o.exeq_result <= EX2MEM_i.exeq_result;
-    MEM_REG_o.byte_Enable <= EX2MEM_i.byte_Enable;
-    MEM_REG_o.wrix_rD     <= EX2MEM_i.wrix_rD;
-    --
-    MEM_WRB_o.wrb_Action <= MEM_REG_i.wrb_Action;
-    MEM_WRB_o.wrix_rD    <= MEM_REG_i.wrix_rD;
-    -- also signal 'slow memory decices' and interrupts from devices
-    MEM2CTRL_o.clken <= DMEMB_i.clken;
-    MEM2CTRL_o.int   <= DMEMB_i.int;
-    -- pass byte_select signal (NOTE: BIG ENDIAN)
-    DMEMB_o.bSel     <= EX2MEM_i.byte_Enable;
+       -- writeback in case of reads from the data memory bus:
+       -- delay wrb-ctrl signals (see core_ctrl) to stay in sync
+       -- with synchronous dmem data output
+       -- Following are only the unconditional pass-through signals. More are in the p_mem process.
+       MEM_REG_o.wrb_Action  <= EX2MEM_i.wrb_Action;
+       MEM_REG_o.exeq_result <= EX2MEM_i.exeq_result;
+       MEM_REG_o.byte_Enable <= EX2MEM_i.byte_Enable;
+       MEM_REG_o.wrix_rD     <= EX2MEM_i.wrix_rD;
+       --
+       MEM_WRB_o.wrb_Action <= MEM_REG_i.wrb_Action;
+       MEM_WRB_o.wrix_rD    <= MEM_REG_i.wrix_rD;
+       -- also signal 'slow memory decices' and interrupts from devices
+       MEM2CTRL_o.clken <= DMEMB_i.clken;
+       MEM2CTRL_o.int   <= DMEMB_i.int;
+       -- pass byte_select signal (NOTE: BIG ENDIAN)
+       DMEMB_o.bSel     <= EX2MEM_i.byte_Enable;
 
 p_mem:
-    PROCESS (EX2MEM_i, DMEMB_i, MEM_REG_i)
-        VARIABLE exeq_data_v : STD_LOGIC_VECTOR (31 DOWNTO 0);
-        VARIABLE dmem_data_v : STD_LOGIC_VECTOR (31 DOWNTO 0);
+       PROCESS (EX2MEM_i, DMEMB_i, MEM_REG_i)
+               VARIABLE exeq_data_v : STD_LOGIC_VECTOR (31 DOWNTO 0);
+               VARIABLE dmem_data_v : STD_LOGIC_VECTOR (31 DOWNTO 0);
+
+       BEGIN
+
+               -- always align Big Endian input data from memory(-bus)
+               CASE MEM_REG_i.byte_Enable IS
+                       WHEN "1000" => dmem_data_v := C_24_ZEROS & DMEMB_i.data(31 DOWNTO 24);
+                       WHEN "0100" => dmem_data_v := C_24_ZEROS & DMEMB_i.data(23 DOWNTO 16);
+                       WHEN "0010" => dmem_data_v := C_24_ZEROS & DMEMB_i.data(15 DOWNTO  8);
+                       WHEN "0001" => dmem_data_v := C_24_ZEROS & DMEMB_i.data( 7 DOWNTO  0);
+                       WHEN "1100" => dmem_data_v := C_16_ZEROS & DMEMB_i.data(31 DOWNTO 16);
+                       WHEN "0011" => dmem_data_v := C_16_ZEROS & DMEMB_i.data(15 DOWNTO  0);
+                       WHEN OTHERS => dmem_data_v :=              DMEMB_i.data;
+               END CASE;
+
+               -- output to dmem-bus
+               CASE EX2MEM_i.mem_Action IS
 
-    BEGIN
+                       WHEN WR_MEM =>
+                               -- write (or forward) to data memory bus
+                               DMEMB_o.addr <= EX2MEM_i.exeq_result;
+                               DMEMB_o.ena  <= '1';
+                               DMEMB_o.wre  <= '1';
+                               -- Note: use MEM_REG_i here, since MEM_WRB_o (output) cannot be read
+                               IF ((MEM_REG_i.wrb_Action /= NO_WRB) AND
+                                       (EX2MEM_i.wrix_rD = MEM_REG_i.wrix_rD)) THEN
+                                       CASE MEM_REG_i.wrb_Action IS
+                                               WHEN WRB_EX  =>
+                                                       -- forward exeq output, to handle e.g. add rD,rA,xx; sw rD,mem[y]; ...
+                                                       exeq_data_v := MEM_REG_i.exeq_result;
+                                               WHEN OTHERS  =>
+                                                       -- forward mem_data just read, to handle e.g. lhu rD,mem[x]; sh rD,mem[y]; ...
+                                                       exeq_data_v := dmem_data_v;
+                                       END CASE;
+                               ELSE
+                                       exeq_data_v := EX2MEM_i.data_rD;
+                               END IF;
+                               -- output data will be in Big Endian format
+                               CASE EX2MEM_i.byte_Enable IS
+                                       WHEN "1000" => DMEMB_o.data <=              exeq_data_v( 7 DOWNTO 0) & C_24_ZEROS;
+                                       WHEN "0100" => DMEMB_o.data <=  C_8_ZEROS & exeq_data_v( 7 DOWNTO 0) & C_16_ZEROS;
+                                       WHEN "0010" => DMEMB_o.data <= C_16_ZEROS & exeq_data_v( 7 DOWNTO 0) &  C_8_ZEROS;
+                                       WHEN "0001" => DMEMB_o.data <= C_24_ZEROS & exeq_data_v( 7 DOWNTO 0);
+                                       WHEN "1100" => DMEMB_o.data <=              exeq_data_v(15 DOWNTO 0) & C_16_ZEROS;
+                                       WHEN "0011" => DMEMB_o.data <= C_16_ZEROS & exeq_data_v(15 DOWNTO 0);
+                                       WHEN OTHERS => DMEMB_o.data <=              exeq_data_v;
+                               END CASE;
 
-        -- always align Big Endian input data from memory(-bus)
-        CASE MEM_REG_i.byte_Enable IS
-            WHEN "1000" => dmem_data_v := C_24_ZEROS & DMEMB_i.data(31 DOWNTO 24);
-            WHEN "0100" => dmem_data_v := C_24_ZEROS & DMEMB_i.data(23 DOWNTO 16);
-            WHEN "0010" => dmem_data_v := C_24_ZEROS & DMEMB_i.data(15 DOWNTO  8);
-            WHEN "0001" => dmem_data_v := C_24_ZEROS & DMEMB_i.data( 7 DOWNTO  0);
-            WHEN "1100" => dmem_data_v := C_16_ZEROS & DMEMB_i.data(31 DOWNTO 16);
-            WHEN "0011" => dmem_data_v := C_16_ZEROS & DMEMB_i.data(15 DOWNTO  0);
-            WHEN OTHERS => dmem_data_v :=              DMEMB_i.data;
-        END CASE;
+                       WHEN RD_MEM =>
+                               -- read from data memory bus
+                               DMEMB_o.addr <= EX2MEM_i.exeq_result;
+                               DMEMB_o.ena  <= '1';
+                               DMEMB_o.wre  <= '0';
+                               DMEMB_o.data <= EX2MEM_i.data_rD;   -- (OTHERS => 'Z');
 
-        -- output to dmem-bus
---      DMEMB_o.addr <= EX2MEM_i.exeq_result;
-        CASE EX2MEM_i.mem_Action IS
-            WHEN WR_MEM =>
-                -- write (or forward) to data memory bus
-                DMEMB_o.addr <= EX2MEM_i.exeq_result;
-                DMEMB_o.ena  <= '1';
-                DMEMB_o.wre  <= '1';
-                -- Note: use MEM_REG_i here, since MEM_WRB_o (output) cannot be read
-                IF ((MEM_REG_i.wrb_Action /= NO_WRB) AND
-                        (EX2MEM_i.wrix_rD = MEM_REG_i.wrix_rD)) THEN
-                    CASE MEM_REG_i.wrb_Action IS
-                        WHEN WRB_EX  =>
-                            -- forward exeq output, to handle e.g. add rD,rA,xx; sw rD,mem[y]; ...
-                            exeq_data_v := MEM_REG_i.exeq_result;
-                        WHEN OTHERS  =>
-                            -- forward mem_data just read, to handle e.g. lhu rD,mem[x]; sh rD,mem[y]; ...
-                            exeq_data_v := dmem_data_v;
-                    END CASE;
-                ELSE
-                    exeq_data_v := EX2MEM_i.data_rD;
-                END IF;
-                -- output data will be in Big Endian format
-                CASE EX2MEM_i.byte_Enable IS
-                    WHEN "1000" => DMEMB_o.data <=              exeq_data_v( 7 DOWNTO 0) & C_24_ZEROS;
-                    WHEN "0100" => DMEMB_o.data <=  C_8_ZEROS & exeq_data_v( 7 DOWNTO 0) & C_16_ZEROS;
-                    WHEN "0010" => DMEMB_o.data <= C_16_ZEROS & exeq_data_v( 7 DOWNTO 0) &  C_8_ZEROS;
-                    WHEN "0001" => DMEMB_o.data <= C_24_ZEROS & exeq_data_v( 7 DOWNTO 0);
-                    WHEN "1100" => DMEMB_o.data <=              exeq_data_v(15 DOWNTO 0) & C_16_ZEROS;
-                    WHEN "0011" => DMEMB_o.data <= C_16_ZEROS & exeq_data_v(15 DOWNTO 0);
-                    WHEN OTHERS => DMEMB_o.data <=              exeq_data_v;
-                END CASE;
-            WHEN RD_MEM =>
-                -- read from data memory bus
-                DMEMB_o.addr <= EX2MEM_i.exeq_result;
-                DMEMB_o.ena  <= '1';
-                DMEMB_o.wre  <= '0';
-                DMEMB_o.data <= EX2MEM_i.data_rD;   -- (OTHERS => 'Z');
-            WHEN OTHERS =>      -- NO_MEM
-                DMEMB_o.addr <= C_32_ZEROS;
-                DMEMB_o.ena  <= '0';
-                DMEMB_o.wre  <= '0';
-                DMEMB_o.data <= EX2MEM_i.data_rD;   -- (OTHERS => 'Z');
-        END CASE;
+                       WHEN OTHERS =>      -- NO_MEM
+                               DMEMB_o.addr <= C_32_ZEROS;
+                               DMEMB_o.ena  <= '0';
+                               DMEMB_o.wre  <= '0';
+                               DMEMB_o.data <= EX2MEM_i.data_rD;   -- (OTHERS => 'Z');
+               END CASE;
 
-        -- additional wrb signals
-        CASE MEM_REG_i.wrb_Action IS
-            WHEN WRB_MEM => MEM_WRB_o.data_rD <= dmem_data_v;
-            WHEN OTHERS  => MEM_WRB_o.data_rD <= MEM_REG_i.exeq_result;
-        END CASE;
+               -- additional wrb signals
+               CASE MEM_REG_i.wrb_Action IS
+                       WHEN WRB_MEM => MEM_WRB_o.data_rD <= dmem_data_v;
+                       WHEN OTHERS  => MEM_WRB_o.data_rD <= MEM_REG_i.exeq_result;
+               END CASE;
 
-    END PROCESS;
+       END PROCESS;
 
 END ARCHITECTURE rtl;