OpenCores
URL https://opencores.org/ocsvn/rv01_riscv_core/rv01_riscv_core/trunk

Subversion Repositories rv01_riscv_core

[/] [rv01_riscv_core/] [trunk/] [VHDL/] [RV01_lsu.vhd] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 madsilicon
-----------------------------------------------------------------
2
--                                                             --
3
-----------------------------------------------------------------
4
--                                                             --
5
-- Copyright (C) 2015 Stefano Tonello                          --
6
--                                                             --
7
-- This source file may be used and distributed without        --
8
-- restriction provided that this copyright statement is not   --
9
-- removed from the file and that any derivative work contains --
10
-- the original copyright notice and the associated disclaimer.--
11
--                                                             --
12
-- THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY         --
13
-- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED   --
14
-- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS   --
15
-- FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR      --
16
-- OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,         --
17
-- INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES    --
18
-- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE   --
19
-- GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR        --
20
-- BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF  --
21
-- LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT  --
22
-- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT  --
23
-- OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE         --
24
-- POSSIBILITY OF SUCH DAMAGE.                                 --
25
--                                                             --
26
-----------------------------------------------------------------
27
 
28
---------------------------------------------------------------
29
-- RV01 Load/Store Unit
30
---------------------------------------------------------------
31
 
32
library IEEE;
33
use IEEE.std_logic_1164.all;
34
use IEEE.numeric_std.all;
35
 
36
library work;
37
use work.RV01_CONSTS_PKG.all;
38
use work.RV01_TYPES_PKG.all;
39
use work.RV01_FUNCS_PKG.all;
40
use work.RV01_ARITH_PKG.all;
41
use work.RV01_OP_PKG.all;
42
 
43
entity RV01_LSU is
44
  port(
45
    CLK_i : in std_logic;
46
    RST_i : in std_logic;
47
    IV_i : in std_logic;
48
    LS_OP_i : in LS_OP_T;
49
    SU_i : in std_logic;
50
    OPA_i : in SDWORD_T;
51
    OPB_i : in SDWORD_T;
52
    IMM_i : in SDWORD_T;
53
    LDAT_i : in std_logic_vector(SDLEN-1 downto 0);
54
 
55
    RE_o : out std_logic;
56
    WE_o : out std_logic;
57
    MALGN_o : out std_logic;
58
    ADR_o : out unsigned(ALEN-1 downto 0);
59
    SBE_o : out std_logic_vector(4-1 downto 0);
60
    SDAT_o : out std_logic_vector(SDLEN-1 downto 0);
61
    LDATV_o : out std_logic;
62
    LDAT_o : out SDWORD_T
63
  );
64
end RV01_LSU;
65
 
66
architecture ARC of RV01_LSU is
67
 
68
  type SEL_T is (BS,BU,HS,HU);
69
 
70
  component RV01_ADDER_F is
71
    generic(
72
      LEN1 : integer := 16;
73
      LEN2 : integer := 16
74
    );
75
    port(
76
      OPA_i : in signed(LEN1+LEN2-1 downto 0);
77
      OPB_i : in signed(LEN1+LEN2-1 downto 0);
78
      CI_i : in std_logic;
79
 
80
      SUM_o : out signed(LEN1+LEN2-1 downto 0)
81
    );
82
  end component;
83
 
84
  signal ZERO : std_logic := '0';
85
  signal RE,WE : std_logic;
86
  --signal ADR : unsigned(ALEN-1 downto 0);
87
  signal DDATO : std_logic_vector(SDLEN-1 downto 0);
88
  signal LDATI_q,LDATI_S : std_logic_vector(16-1 downto 0);
89
  signal SBE : std_logic_vector(4-1 downto 0);
90
  signal SDATO : std_logic_vector(SDLEN-1 downto 0);
91
  signal LDATV_1C : std_logic;
92
  signal LDATV,LDATV_q,LDATV_q2 : std_logic;
93
  signal LS_OP_q : LS_OP_T;
94
  signal SHFT_q : std_logic_vector(2-1 downto 0);
95
  signal SU_q : std_logic;
96
  signal SEL,SEL_q : SEL_T;
97
  signal LDATO : SDWORD_T;
98
  signal MALGN : std_logic;
99
  signal ZOPA,ZIMM,ZADR : signed(SDLEN downto 0);
100
 
101
begin
102
 
103
  ----------------------------------------------
104
  -- Pipeline organisation
105
  ----------------------------------------------
106
 
107
  -- LSU employs a 3-stage pipeline:
108
  -- stage 1: load/store address generation.
109
  -- stage 2: lw data forwarding, lb*/lh* data alignment.
110
  -- stage 3: lb*/lh* data sign/zero-extension.
111
 
112
  -- LSU design is based on the assumption that
113
  -- lw instructions are far more frequent than
114
  -- others load instructions and therefore only
115
  -- their result is made available in second
116
  -- pipe stage to forwarding logic. Result from
117
  -- other load instructions is, instead, generated
118
  -- in third pipe stage and is not avaialble for
119
  -- forwarding.
120
 
121
  -- Note: load/store instructions immediate value
122
  -- must be provided separately from OPA_i and OPB_i
123
  -- because OPB_i stores store data!
124
 
125
  ----------------------------------------------
126
  -- 1st pipe stage
127
  ----------------------------------------------
128
 
129
  -- generate load/store address
130
 
131
  --process(LS_OP_i,OPA_i,IMM_i)
132
  --  variable TMP : signed(SDLEN downto 0);
133
  --begin
134
  --  -- calculate effective address (extra bit prevents overflow)
135
  --  TMP := ('0' & OPA_i) + ('0' & IMM_i);
136
  --  ADR <= to_unsigned(TMP(ALEN-1 downto 0));
137
  --end process;
138
 
139
  ZOPA <= ('0' & OPA_i);
140
  ZIMM <= ('0' & IMM_i);
141
 
142
  U_ADDF : RV01_ADDER_F
143
    generic map(
144
      LEN1 => SDLEN/2+1,
145
      LEN2 => SDLEN/2
146
    )
147
    port map(
148
      OPA_i => ZOPA,
149
      OPB_i => ZIMM,
150
      CI_i => ZERO,
151
      SUM_o => ZADR
152
    );
153
 
154
  -- external memory address
155
  ADR_o <= to_unsigned(ZADR(ALEN-1 downto 0));
156
 
157
  -- generate write-enable flag
158
  WE <= IV_i when (
159
    LS_OP_i = LS_SW or
160
    LS_OP_i = LS_SB or
161
    LS_OP_i = LS_SH
162
  ) else '0';
163
 
164
  -- external memory write-enable flag
165
  WE_o <= WE;
166
 
167
  -- generate read-enable flag
168
  RE <= IV_i when (
169
    LS_OP_i = LS_LB or
170
    LS_OP_i = LS_LH or
171
    LS_OP_i = LS_LW
172
  ) else '0';
173
 
174
  -- external memory read-enable flag
175
  RE_o <= RE;
176
 
177
  -- alignment error flag
178
  process(ZADR,LS_OP_i)
179
  begin
180
    case LS_OP_i is
181
      when LS_SW|LS_LW =>
182
        MALGN <= ZADR(1) or ZADR(0);
183
      when LS_SH|LS_LH =>
184
        MALGN <= ZADR(0);
185
      when others =>
186
        MALGN <= '0';
187
    end case;
188
  end process;
189
 
190
  -- Mis-alignment flag (this flag is used to trigger
191
  -- exception processing).
192
 
193
  MALGN_o <= MALGN;
194
 
195
  -- store data alignment and byte-enable flags generation
196
  process(LS_OP_i,OPB_i,ZADR)
197
    variable B0,B1,B2,B3 : std_logic_vector(8-1 downto 0);
198
  begin
199
    B0 := to_std_logic_vector(OPB_i(8-1 downto 0));
200
    B1 := to_std_logic_vector(OPB_i(16-1 downto 8));
201
    B2 := to_std_logic_vector(OPB_i(24-1 downto 16));
202
    B3 := to_std_logic_vector(OPB_i(32-1 downto 24));
203
    SBE <= "0000";
204
    case LS_OP_i is
205
      when LS_SB =>
206
        SDATO <= B0 & B0 & B0 & B0;
207
        case ZADR(2-1 downto 0) is
208
          when "00" => SBE(0) <= '1';
209
          when "01" => SBE(1) <= '1';
210
          when "10" => SBE(2) <= '1';
211
          when others => SBE(3) <= '1';
212
        end case;
213
      when LS_SH =>
214
        SDATO <= B1 & B0 & B1 & B0;
215
        if(ZADR(1) = '0') then
216
          SBE(1 downto 0) <= "11";
217
        else
218
          SBE(3 downto 2) <= "11";
219
        end if;
220
      when others =>
221
        SDATO <= B3 & B2 & B1 & B0;
222
        SBE <= "1111";
223
    end case;
224
  end process;
225
 
226
  SDAT_o <= SDATO;
227
  SBE_o <= SBE;
228
 
229
  -- lw data valid flag.
230
  LDATV_1C <= IV_i when (
231
    LS_OP_i = LS_LW
232
  ) else '0';
233
 
234
  -- lb*/lh* data valid flag
235
  LDATV <= IV_i when (
236
    LS_OP_i = LS_LB or
237
    LS_OP_i = LS_LH
238
  ) else '0';
239
 
240
  -- pipe registers
241
 
242
  process(CLK_i)
243
  begin
244
    if(CLK_i = '1' and CLK_i'event) then
245
      if(RST_i = '1') then
246
        LDATV_q <= '0';
247
      else
248
        LDATV_q <= LDATV;
249
      end if;
250
      LS_OP_q <= LS_OP_i;
251
      SU_q <= SU_i;
252
      SHFT_q <= to_std_logic_vector(ZADR(2-1 downto 0));
253
    end if;
254
  end process;
255
 
256
  ----------------------------------------------
257
  -- 2nd pipe stage
258
  ----------------------------------------------
259
 
260
  -- This stage outputs lw data to forward logic
261
  -- and performs alignment for lb*/lh*.
262
 
263
  process(LDAT_i,SHFT_q)
264
    variable ZERO24 : std_logic_vector(24-1 downto 0) := (others => '0');
265
    variable TMP,TMP_S : unsigned(SDLEN-1 downto 0);
266
  begin
267
    TMP := to_unsigned(LDAT_i);
268
    case SHFT_q is
269
      when "00" => TMP_S := shift_right(TMP,0);
270
      when "01" => TMP_S := shift_right(TMP,8);
271
      when "10" => TMP_S := shift_right(TMP,16);
272
      when others => TMP_S := shift_right(TMP,24);
273
    end case;
274
    LDATI_S <= to_std_logic_vector(TMP_S(16-1 downto 0));
275
  end process;
276
 
277
  SEL <=
278
    BS when (LS_OP_q = LS_LB and SU_q = '1') else
279
    BU when (LS_OP_q = LS_LB and SU_q = '0') else
280
    HS when (LS_OP_q = LS_LH and SU_q = '1') else
281
    HU;
282
 
283
  process(CLK_i)
284
  begin
285
    if(CLK_i = '1' and CLK_i'event) then
286
      if(RST_i = '1') then
287
        LDATV_q2 <= '0';
288
      else
289
        LDATV_q2 <= LDATV_q;
290
      end if;
291
      LDATI_q <= LDATI_S;
292
      SEL_q <= SEL;
293
    end if;
294
  end process;
295
 
296
  ----------------------------------------------
297
  -- 3rd pipe stage (ls*/lh* data-out)
298
  ----------------------------------------------
299
 
300
  process(LDATI_q,SEL_q)
301
    variable ZERO16 : signed(16-1 downto 0) := (others => '0');
302
    variable ZERO24 : signed(24-1 downto 0) := (others => '0');
303
  begin
304
    case SEL_q is
305
      when BS => LDATO <= EXTS32(LDATI_q(8-1 downto 0));
306
      when BU => LDATO <= ZERO24 & to_signed(LDATI_q(8-1 downto 0));
307
      when HS => LDATO <= EXTS32(LDATI_q);
308
      when HU => LDATO <= ZERO16 & to_signed(LDATI_q);
309
    end case;
310
  end process;
311
 
312
  LDAT_o <= LDATO;
313
  LDATV_o <= LDATV_q2;
314
 
315
end ARC;

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.