]> rtime.felk.cvut.cz Git - fpga/lx-cpu1/tumbl.git/blob - hw/mem.vhd
Attempt to fix forward from memory read to write over when Tumbl is being to stop.
[fpga/lx-cpu1/tumbl.git] / hw / mem.vhd
1 ---------------------------------------------------------------------------------
2 --
3 --  Entity:       mem
4 --  Filename:     mem.vhd
5 --  Description:  the Memory (MEM) control unit for
6 --                the TUD MB-Lite implementation
7 --
8 --  Author:       Huib Lincklaen Arriens
9 --                Delft University of Technology
10 --                Faculty EEMCS, Department ME&CE, Circuits and Systems
11 --  Date:         October, 2010
12 --
13 --  Modified:     December, 2010: handle S_FSL Data Input (Huib)
14 --  Remarks:
15 --------------------------------------------------------------------------------
16
17 LIBRARY IEEE;
18 USE IEEE.std_logic_1164.all;
19 USE WORK.mbl_pkg.all;
20
21 --------------------------------------------------------------------------------
22 ENTITY mem IS
23 --------------------------------------------------------------------------------
24         PORT
25         (
26                 EX2MEM_i    :  IN EX2MEM_Type;
27                 --
28                 DMEMB_i     :  IN DMEMB2CORE_Type;
29                 DMEMB_o     : OUT CORE2DMEMB_Type;
30                 --
31                 MEM_REG_i   :  IN MEM_REG_Type;
32                 MEM_REG_o   : OUT MEM_REG_Type;
33                 --
34                 MEM_WRB_o   : OUT WRB_Type;
35                 MEM2CTRL_o  : OUT MEM2CTRL_Type
36         );
37 END ENTITY mem;
38
39 --------------------------------------------------------------------------------
40 ARCHITECTURE rtl OF mem IS
41 --------------------------------------------------------------------------------
42
43 BEGIN
44
45         -- writeback in case of reads from the data memory bus:
46         -- delay wrb-ctrl signals (see core_ctrl) to stay in sync
47         -- with synchronous dmem data output
48         -- Following are only the unconditional pass-through signals. More are in the p_mem process.
49         MEM_REG_o.wrb_Action  <= EX2MEM_i.wrb_Action;
50         MEM_REG_o.exeq_result <= EX2MEM_i.exeq_result;
51         MEM_REG_o.byte_Enable <= EX2MEM_i.byte_Enable;
52         MEM_REG_o.wrix_rD     <= EX2MEM_i.wrix_rD;
53         --
54         MEM_WRB_o.wrb_Action <= MEM_REG_i.wrb_Action;
55         MEM_WRB_o.wrix_rD    <= MEM_REG_i.wrix_rD;
56         -- also signal 'slow memory decices' and interrupts from devices
57         MEM2CTRL_o.bus_taken <= '0' WHEN EX2MEM_i.mem_Action = NO_MEM ELSE DMEMB_i.bus_taken;
58         MEM2CTRL_o.bus_wait  <= '0' WHEN EX2MEM_i.mem_Action = NO_MEM ELSE DMEMB_i.bus_wait;
59         MEM2CTRL_o.int   <= DMEMB_i.int;
60
61 p_mem:
62         PROCESS (EX2MEM_i, DMEMB_i, MEM_REG_i)
63                 VARIABLE exeq_data_v : STD_LOGIC_VECTOR (31 DOWNTO 0);
64                 VARIABLE dmem_data_v : STD_LOGIC_VECTOR (31 DOWNTO 0);
65
66         BEGIN
67
68                 -- always align Big Endian input data from memory(-bus)
69                 CASE MEM_REG_i.byte_Enable IS
70                         WHEN "1000" => dmem_data_v := C_24_ZEROS & DMEMB_i.data(31 DOWNTO 24);
71                         WHEN "0100" => dmem_data_v := C_24_ZEROS & DMEMB_i.data(23 DOWNTO 16);
72                         WHEN "0010" => dmem_data_v := C_24_ZEROS & DMEMB_i.data(15 DOWNTO  8);
73                         WHEN "0001" => dmem_data_v := C_24_ZEROS & DMEMB_i.data( 7 DOWNTO  0);
74                         WHEN "1100" => dmem_data_v := C_16_ZEROS & DMEMB_i.data(31 DOWNTO 16);
75                         WHEN "0011" => dmem_data_v := C_16_ZEROS & DMEMB_i.data(15 DOWNTO  0);
76                         WHEN OTHERS => dmem_data_v :=              DMEMB_i.data;
77                 END CASE;
78
79                 MEM2CTRL_o.read_data <= dmem_data_v;
80                 MEM2CTRL_o.need_keep <= '0';
81
82                 -- output to dmem-bus
83                 CASE EX2MEM_i.mem_Action IS
84
85                         WHEN WR_MEM =>
86                                 -- write (or forward) to data memory bus
87                                 DMEMB_o.addr  <= EX2MEM_i.exeq_result(16 downto 2);
88                                 DMEMB_o.rd    <= '0';
89                                 DMEMB_o.bls   <= EX2MEM_i.byte_Enable;
90                                 -- Note: use MEM_REG_i here, since MEM_WRB_o (output) cannot be read
91                                 IF ((MEM_REG_i.wrb_Action /= NO_WRB) AND
92                                         (EX2MEM_i.wrix_rD = MEM_REG_i.wrix_rD)) THEN
93                                         CASE MEM_REG_i.wrb_Action IS
94                                                 WHEN WRB_EX  =>
95                                                         -- forward exeq output, to handle e.g. add rD,rA,xx; sw rD,mem[y]; ...
96                                                         exeq_data_v := MEM_REG_i.exeq_result;
97                                                 WHEN OTHERS  =>
98                                                         -- forward mem_data just read, to handle e.g. lhu rD,mem[x]; sh rD,mem[y]; ...
99                                                         exeq_data_v := dmem_data_v;
100                                                         MEM2CTRL_o.need_keep <= '1';
101                                         END CASE;
102                                 ELSE
103                                         exeq_data_v := EX2MEM_i.data_rD;
104                                 END IF;
105                                 -- output data will be in Big Endian format
106                                 CASE EX2MEM_i.byte_Enable IS
107                                         WHEN "1000" => DMEMB_o.data <=              exeq_data_v( 7 DOWNTO 0) & C_24_ZEROS;
108                                         WHEN "0100" => DMEMB_o.data <=  C_8_ZEROS & exeq_data_v( 7 DOWNTO 0) & C_16_ZEROS;
109                                         WHEN "0010" => DMEMB_o.data <= C_16_ZEROS & exeq_data_v( 7 DOWNTO 0) &  C_8_ZEROS;
110                                         WHEN "0001" => DMEMB_o.data <= C_24_ZEROS & exeq_data_v( 7 DOWNTO 0);
111                                         WHEN "1100" => DMEMB_o.data <=              exeq_data_v(15 DOWNTO 0) & C_16_ZEROS;
112                                         WHEN "0011" => DMEMB_o.data <= C_16_ZEROS & exeq_data_v(15 DOWNTO 0);
113                                         WHEN OTHERS => DMEMB_o.data <=              exeq_data_v;
114                                 END CASE;
115
116                         WHEN RD_MEM =>
117                                 -- read from data memory bus
118                                 DMEMB_o.addr <= EX2MEM_i.exeq_result(16 downto 2);
119                                 DMEMB_o.rd   <= '1';
120                                 DMEMB_o.bls  <= (others => '0');
121                                 DMEMB_o.data <= EX2MEM_i.data_rD;   -- (OTHERS => 'Z');
122
123                         WHEN OTHERS =>      -- NO_MEM
124                                 DMEMB_o.addr <= (others => '0');
125                                 DMEMB_o.rd   <= '0';
126                                 DMEMB_o.bls  <= (others => '0');
127                                 DMEMB_o.data <= EX2MEM_i.data_rD;   -- (OTHERS => 'Z');
128                 END CASE;
129
130                 -- additional wrb signals
131                 CASE MEM_REG_i.wrb_Action IS
132                         WHEN WRB_MEM => MEM_WRB_o.data_rD <= dmem_data_v;
133                         WHEN OTHERS  => MEM_WRB_o.data_rD <= MEM_REG_i.exeq_result;
134                 END CASE;
135
136         END PROCESS;
137
138 END ARCHITECTURE rtl;