-- 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;