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

Subversion Repositories rv01_riscv_core

[/] [rv01_riscv_core/] [trunk/] [VHDL/] [RV01_ifq.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 Instruction Fetching Queue
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_IDEC_PKG.all;
40
 
41
entity RV01_IFQ is
42
  port(
43
    CLK_i : in std_logic;
44
    RST_i : in std_logic;
45
    ID_HALT_i : in std_logic;
46
    IX_BJX_i : in std_logic;
47
    ID_ISSUE_i : in std_logic_vector(2-1 downto 0);
48
    IF_V_i : in std_logic_vector(2-1 downto 0);
49
    IF_PC0_i : in unsigned(ALEN-1 downto 0);
50
    IF_PC1_i : in unsigned(ALEN-1 downto 0);
51
    IF_INSTR0_i : in std_logic_vector(ILEN-1 downto 0);
52
    IF_INSTR1_i : in std_logic_vector(ILEN-1 downto 0);
53
    IF_DEC_INSTR0_i : in DEC_INSTR_T;
54
    IF_DEC_INSTR1_i : in DEC_INSTR_T;
55
    IF_OPA_PC0_i : in std_logic;
56
    IF_OPA_PC1_i : in std_logic;
57
    IF_OPB_IMM0_i : in std_logic;
58
    IF_OPB_IMM1_i : in std_logic;
59
    IF_BPVD0_i : in std_logic_vector(3-1 downto 0);
60
    IF_BPVD1_i : in std_logic_vector(3-1 downto 0);
61
 
62
    PSTALL_o : out std_logic;
63
    ID_V_o : out std_logic_vector(2-1 downto 0);
64
    ID_PC0_o : out unsigned(ALEN-1 downto 0);
65
    ID_PC1_o : out unsigned(ALEN-1 downto 0);
66
    ID_INSTR0_o : out std_logic_vector(ILEN-1 downto 0);
67
    ID_INSTR1_o : out std_logic_vector(ILEN-1 downto 0);
68
    ID_DEC_INSTR0_o : out DEC_INSTR_T;
69
    ID_DEC_INSTR1_o : out DEC_INSTR_T;
70
    ID_OPA_PC0_o : out std_logic;
71
    ID_OPA_PC1_o : out std_logic;
72
    ID_OPB_IMM0_o : out std_logic;
73
    ID_OPB_IMM1_o : out std_logic;
74
    ID_BPVD0_o : out std_logic_vector(3-1 downto 0);
75
    ID_BPVD1_o : out std_logic_vector(3-1 downto 0)
76
  );
77
end RV01_IFQ;
78
 
79
architecture ARC of RV01_IFQ is
80
 
81
  constant IFQ_DEPTH : natural := 3;
82
 
83
  type IFQ_ENTRY_T is record
84
    DINSTR : DEC_INSTR_T;
85
    INSTR : std_logic_vector(ILEN-1 downto 0);
86
    PC : unsigned(ALEN-1 downto 0);
87
    OPA_PC : std_logic;
88
    OPB_IMM : std_logic;
89
    BPVD : std_logic_vector(3-1 downto 0);
90
  end record;
91
 
92
  type IFQ_T is array (natural range<>) of IFQ_ENTRY_T;
93
 
94
  signal IFQ_NEW_1,IFQ_NEW_0 : IFQ_ENTRY_T;
95
  signal IFQ,IFQ_q : IFQ_T(IFQ_DEPTH-1 downto 0);
96
  signal IFQV,IFQV_q : std_logic_vector(IFQ_DEPTH-1 downto 0);
97
  signal STALL,UPDT : std_logic;
98
 
99
begin
100
 
101
  ----------------------------------------------------
102
  -- Notes:
103
  -- The queue consists of 3 entries, entry #0 being the
104
  -- oldest entry and entry #2 being the newest one.
105
  -- Entries #0,1 act as pipeline registers between
106
  -- stages IF and ID (so that entries #0,1 are the
107
  -- currently decoded instructions).
108
  ----------------------------------------------------
109
 
110
  ----------------------------------------------------
111
  -- Fetch must stall if the number of empty queue
112
  -- entrie, plus the number of issued instructions
113
  -- is lower than two. 
114
  --
115
  -- Let's put this condition in truth table format:
116
  --
117
  -- 210 issue stall
118
  -- ---------------
119
  -- 000    00     0
120
  -- 001    00     0
121
  -- 001    01     0
122
  -- 01x    00     1
123
  -- 01x    01     0
124
  -- 01x    11     0
125
  -- 1xx    00     1
126
  -- 1xx    01     1
127
  -- 1xx    11     0 
128
  ----------------------------------------------------
129
 
130
  -- fetch stall flag
131
 
132
  --STALL <= '1' when (
133
  --  (IFQV_q(1) = '1' and ID_ISSUE_i = "00") or -- 2 instr. in queue and 0 issue
134
  --  (IFQV_q(2) = '1' and ID_ISSUE_i = "00") or -- 3 instr. in queue and 0 issue
135
  --  (IFQV_q(2) = '1' and ID_ISSUE_i = "01")    -- 3 instr. in queue and 1 issue
136
  --) else '0';
137
 
138
  -- ...re-coded to optimize timing
139
 
140
  STALL <= IFQV_q(2) when (ID_ISSUE_i = "01") else
141
    (IFQV_q(2) or IFQV_q(1)) when (ID_ISSUE_i = "00") else '0';
142
 
143
  ----------------------------------------------------
144
  -- Fetch queue data update
145
  -- 
146
  -- old       new
147
  -- 210 issue 210    keep entry
148
  -- ------------------------
149
  -- 000    ** 0nn B (keep -)
150
  -- 001    00 nno A (keep 0)
151
  -- 001    *1 0nn B (keep -)
152
  -- 01x    00 ooo - (stall)
153
  -- 01x    01 nno A (keep 1)
154
  -- 01x    11 0nn B (keep -)
155
  -- 1xx    00 ooo - (stall)
156
  -- 1xx    01 0oo C (stall) <- (*)
157
  -- 1xx    11 nno A (keep 2)
158
  --
159
  -- n = new instruction
160
  -- o = old instruction
161
  -- 0 = garbage
162
 
163
  -- (*) this is special case: fetch must be stalled because
164
  -- there's no room for a new instruction pair in the queue,
165
  -- but queue data must be updated, because one instruction
166
  -- is issued.
167
 
168
  ----------------------------------------------------
169
 
170
  -- queue update flag
171
 
172
  UPDT <= '0' when (
173
    (IFQV_q(1) = '1' and ID_ISSUE_i = "00") or -- 2 instr. in queue and 0 issue
174
    (IFQV_q(2) = '1' and ID_ISSUE_i = "00") -- 3 instr. in queue and 0 issue
175
  ) else '1';
176
 
177
  IFQ_NEW_0 <= (
178
    IF_DEC_INSTR0_i,
179
    IF_INSTR0_i,
180
    IF_PC0_i,
181
    IF_OPA_PC0_i,
182
    IF_OPB_IMM0_i,
183
    IF_BPVD0_i
184
  );
185
 
186
  IFQ_NEW_1 <= (
187
    IF_DEC_INSTR1_i,
188
    IF_INSTR1_i,
189
    IF_PC1_i,
190
    IF_OPA_PC1_i,
191
    IF_OPB_IMM1_i,
192
    IF_BPVD1_i
193
  );
194
 
195
  -- fetch queue data update logic
196
  process(IFQV_q,IFQ_q,IF_V_i,ID_ISSUE_i,IFQ_NEW_1,IFQ_NEW_0)
197
    variable KEEP : natural range 2 downto 0;
198
  begin
199
    case ID_ISSUE_i is
200
      when "00" => KEEP := 0;
201
      when "01" => KEEP := 1;
202
      when others => KEEP := 2;
203
    end case;
204
    if(
205
      (IFQV_q(2 downto 0) = "001" and ID_ISSUE_i = "00") or
206
      (IFQV_q(2 downto 1) = "01" and ID_ISSUE_i = "01") or
207
      (IFQV_q(2) = '1' and ID_ISSUE_i = "11")
208
    ) then
209
      -- "A" case (1 old instr. in queue)
210
      IFQV <= IF_V_i & IFQV_q(KEEP);
211
      IFQ <= (IFQ_NEW_1,IFQ_NEW_0,IFQ_q(KEEP));
212
    elsif(
213
      (IFQV_q(2 downto 0) = "000") or
214
      (IFQV_q(2 downto 0) = "001" and ID_ISSUE_i(0) = '1') or
215
      (IFQV_q(2 downto 1) = "01" and ID_ISSUE_i = "11")
216
    ) then
217
      -- "B" case (no old instr. in queue)
218
      IFQV <= '0' & IF_V_i;
219
      IFQ <= (IFQ_q(2),IFQ_NEW_1,IFQ_NEW_0);
220
    else -- if(IFQV_q(2) = '1' and ID_ISSUE_i = "01")
221
      -- "C" case (2 old instr. in queue)
222
      IFQV <= '0' & IFQV_q(2 downto 1);
223
      IFQ <= (IFQ_q(2),IFQ_q(2),IFQ_q(1));
224
    end if;
225
  end process;
226
 
227
  -- fetch queue data registers
228
  process(CLK_i)
229
  begin
230
    if(CLK_i = '1' and CLK_i'event) then
231
 
232
      if(RST_i = '1' or IX_BJX_i = '1') then
233
        IFQV_q <= (others => '0');
234
      elsif(UPDT = '1' and ID_HALT_i = '0') then
235
        IFQV_q <= IFQV;
236
      elsif(ID_HALT_i = '1') then
237
        IFQV_q <= (others => '0');
238
      end if;
239
 
240
      if(UPDT = '1') then
241
        IFQ_q <= IFQ;
242
      end if;
243
 
244
    end if;
245
  end process;
246
 
247
  ----------------------------------------------------
248
  -- outputs
249
  ----------------------------------------------------
250
 
251
  PSTALL_o <= STALL and not(IX_BJX_i);
252
 
253
  ID_V_o <= IFQV_q(1 downto 0);
254
  ID_PC0_o <= IFQ_q(0).PC;
255
  ID_PC1_o <= IFQ_q(1).PC;
256
  ID_INSTR0_o <= IFQ_q(0).INSTR;
257
  ID_INSTR1_o <= IFQ_q(1).INSTR;
258
  ID_DEC_INSTR0_o <= IFQ_q(0).DINSTR;
259
  ID_DEC_INSTR1_o <= IFQ_q(1).DINSTR;
260
  ID_OPA_PC0_o <= IFQ_q(0).OPA_PC;
261
  ID_OPA_PC1_o <= IFQ_q(1).OPA_PC;
262
  ID_OPB_IMM0_o <= IFQ_q(0).OPB_IMM;
263
  ID_OPB_IMM1_o <= IFQ_q(1).OPB_IMM;
264
  ID_BPVD0_o <= IFQ_q(0).BPVD;
265
  ID_BPVD1_o <= IFQ_q(1).BPVD;
266
 
267
end;
268
 

powered by: WebSVN 2.1.0

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