--------------------------------------------------------------------------------- -- -- Entity: mem -- Filename: mem.vhd -- Description: the Memory (MEM) control unit for -- the TUD MB-Lite implementation -- -- Author: Huib Lincklaen Arriens -- Delft University of Technology -- Faculty EEMCS, Department ME&CE, Circuits and Systems -- Date: October, 2010 -- -- Modified: December, 2010: handle S_FSL Data Input (Huib) -- 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 ); 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; 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); 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 WHEN WR_MEM => -- write (or forward) to data memory bus DMEMB_o.addr <= EX2MEM_i.exeq_result(16 downto 2); DMEMB_o.rd <= '0'; DMEMB_o.bls <= EX2MEM_i.byte_Enable; -- 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(16 downto 2); DMEMB_o.rd <= '1'; DMEMB_o.bls <= (others => '0'); DMEMB_o.data <= EX2MEM_i.data_rD; -- (OTHERS => 'Z'); WHEN OTHERS => -- NO_MEM DMEMB_o.addr <= (others => '0'); DMEMB_o.rd <= '0'; DMEMB_o.bls <= (others => '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; END PROCESS; END ARCHITECTURE rtl;