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

Subversion Repositories oops

[/] [oops/] [trunk/] [rtl/] [icache_ctl.v] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 smjoshua
//////////////////////////////////////////////////////////////////
2
//                                                              //
3
//  OoOPs Core Instruction Cache Control module                 //
4
//                                                              //
5
//  This file is part of the OoOPs project                      //
6
//  http://www.opencores.org/project,oops                       //
7
//                                                              //
8
//  Description:                                                //
9
//  Controller for Instruction Cache.  Block takes requests from//
10
//  the IF stage, handles the inputs to the cache RAMs, detects //
11
//  cache hits, and generates bus requests if the cache misses. //
12
//  The controller is only capable of handling one outstanding  //
13
//  miss and does no prefetching.                               //
14
//                                                              //
15
//  Author(s):                                                  //
16
//      - Joshua Smith, smjoshua@umich.edu                      //
17
//                                                              //
18
//////////////////////////////////////////////////////////////////
19
//                                                              //
20
// Copyright (C) 2012 Authors and OPENCORES.ORG                 //
21
//                                                              //
22
// This source file may be used and distributed without         //
23
// restriction provided that this copyright statement is not    //
24
// removed from the file and that any derivative work contains  //
25
// the original copyright notice and the associated disclaimer. //
26
//                                                              //
27
// This source file is free software; you can redistribute it   //
28
// and/or modify it under the terms of the GNU Lesser General   //
29
// Public License as published by the Free Software Foundation; //
30
// either version 2.1 of the License, or (at your option) any   //
31
// later version.                                               //
32
//                                                              //
33
// This source is distributed in the hope that it will be       //
34
// useful, but WITHOUT ANY WARRANTY; without even the implied   //
35
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      //
36
// PURPOSE.  See the GNU Lesser General Public License for more //
37
// details.                                                     //
38
//                                                              //
39
// You should have received a copy of the GNU Lesser General    //
40
// Public License along with this source; if not, download it   //
41
// from http://www.opencores.org/lgpl.shtml                     //
42
//                                                              //
43
//////////////////////////////////////////////////////////////////
44
`include "ooops_defs.v"
45
 
46
module icache_ctl (
47
  input wire                      clk,
48
  input wire                      rst,
49
  input wire                      rob_pipe_flush,
50
 
51
  // Coprocessor interface (for IC enable)
52
  input wire                      cp0_ic_enable,
53
 
54
  // IF interface
55
  input wire                      if_ic_req,
56
  input wire  [`ADDR_SZ-1:0]      if_ic_fpc,
57
  input wire  [`ADDR_SZ-1:0]      r_if_ic_fpc,
58
  output wire [`INSTR_SZ-1:0]     ic_if_data,
59
  output wire                     ic_if_data_valid,
60
  output wire                     ic_if_ready,
61
 
62
  // Interface to cache memories
63
  input wire  [`IC_TAGRAM_SZ-1:0] ic_tagram_data,
64
  input wire  [`IC_LINE_SZ-1:0]   ic_dataram_data,
65
  output wire [`IC_LINE_SZ-1:0]   ic_dataram_wr_data,
66
  output wire [`IC_SI_SZ-1:0]     ic_dataram_addr,
67
  output wire                     ic_dataram_wren,
68
  output wire [`IC_TAGRAM_SZ-1:0] ic_tagram_wr_data,
69
  output wire [`IC_SI_SZ-1:0]     ic_tagram_addr,
70
  output wire                     ic_tagram_wren,
71
 
72
  // Memory interface
73
  output wire                     ic2bus_req,
74
  output wire [`ADDR_SZ-1:0]      ic2bus_fpc,
75
  input wire                      bus2ic_valid,
76
  input wire  [`SYS_BUS_SZ-1:0]   bus2ic_data
77
  );
78
 
79
  parameter IC_STATE_IDLE   = 3'h0,
80
            IC_STATE_REQ    = 3'h1,
81
            IC_STATE_WAIT   = 3'h2,
82
            IC_STATE_WR_RAM = 3'h3,
83
            IC_STATE_INIT   = 3'h4;
84
 
85
  // Internal wires/regs
86
  wire                          ic_cache_hit;
87
  wire                          ic_tag_match;
88
  wire                          ic_tag_valid;
89
  wire [`IC_TAG_SZ-1:0]         ic_tag;
90
  wire                          r_if_ic_req;
91
 
92
  wire [2:0]                    ic_state;
93
  reg  [2:0]                    ic_nstate;
94
  wire [`IC_SI]                 ic_init_ctr;
95
  wire [`IC_SI]                 ic_init_nctr;
96
  wire                          ic_do_init;
97
  wire                          ic_init_done;
98
  wire                          ic_initialized;
99
  wire                          ic_initialized_ld;
100
 
101
  // Latch req signal so we can correctly assert "hit" and also request to memory
102
  // on a cache miss.
103
  MDFFR #(1) r_if_ic_req_ff (clk, rst, 1'b0, if_ic_req, r_if_ic_req);
104
 
105
  // If we get a cache miss and then a flush happens, need to make sure that instruction
106
  // coming back isn't sent down the pipe.
107
  wire rob_pipe_flush_seen, rob_pipe_flush_seen_in;
108
  assign rob_pipe_flush_seen_in = rob_pipe_flush_seen ? ~bus2ic_valid : rob_pipe_flush & (ic_state != IC_STATE_IDLE);
109
  MDFFR #(1) rob_pipe_flush_seen_ff (clk, rst, 1'b0, rob_pipe_flush_seen_in, rob_pipe_flush_seen);
110
 
111
  // Handle interface to Data and Tag SRAMs
112
  `ifdef USE_IC
113
  assign ic_do_init          = (ic_state == IC_STATE_INIT);
114
  assign ic_dataram_wren     = ic_do_init || (bus2ic_valid & !rob_pipe_flush_seen);
115
  assign ic_dataram_wr_data  = ic_do_init ? {`IC_LINE_SZ{1'b0}} : bus2ic_data;
116
  assign ic_dataram_addr     = (ic_state == IC_STATE_INIT) ? ic_init_ctr[`IC_SI] :
117
                               (ic_state == IC_STATE_WAIT) ? ic2bus_fpc[`IC_SI] :
118
                                                             if_ic_fpc[`IC_SI];
119
 
120
  assign ic_tagram_wren      = ic_do_init || (bus2ic_valid & !rob_pipe_flush_seen);
121
  assign ic_tagram_wr_data   = ic_do_init ? {`IC_TAGRAM_SZ{1'b0}} : {1'b1, 1'b0, ic2bus_fpc[`IC_TAG]};
122
  assign ic_tagram_addr      = (ic_state == IC_STATE_INIT) ? ic_init_ctr[`IC_SI] :
123
                               (ic_state == IC_STATE_WAIT) ? ic2bus_fpc[`IC_SI] :
124
                                                             if_ic_fpc[`IC_SI];
125
  `else
126
  // If not including Icache, then just zero cache inputs out
127
  assign ic_do_init          = 1'b0;
128
  assign ic_dataram_wren     = 1'b0;
129
  assign ic_dataram_wr_data  = {`IC_LINE_SZ{1'b0}};
130
  assign ic_dataram_addr     = {`IC_SI_SZ{1'b0}};
131
 
132
  assign ic_tagram_wren      = 1'b0;
133
  assign ic_tagram_wr_data   = {`IC_LINE_SZ{1'b0}};
134
  assign ic_tagram_addr      = {`IC_SI_SZ{1'b0}};
135
  `endif
136
 
137
  // Handle tag comparison and IF interface
138
  // Note: ic_if_ready just means we've initialized SRAMs.  This will block
139
  // IF requests and stall the pipeline on startup.
140
  `ifdef USE_IC
141
  assign ic_tag           = ic_tagram_data[`IC_TAGRAM_TAG];
142
  assign ic_tag_valid     = ic_tagram_data[`IC_TAGRAM_VLD];
143
  assign ic_tag_match     = (ic_tag == r_if_ic_fpc[`IC_TAG]);
144
  assign ic_cache_hit     = ic_tag_match & (r_if_ic_req & ic_tag_valid & cp0_ic_enable & ic_initialized & !rob_pipe_flush_seen);
145
  assign ic_if_ready      = ic_initialized & (ic_nstate == IC_STATE_IDLE);
146
  assign ic_if_data       = r_if_ic_fpc[2] ? ic_dataram_data[63:32] : ic_dataram_data[31:0];
147
  assign ic_if_data_valid = ic_cache_hit;
148
  `else
149
  // If not including Icache, then need to force everything as a cache miss and only return bus2ic_data
150
  assign ic_tag           = {`IC_TAG_SZ{1'b0}};
151
  assign ic_tag_valid     = 1'b0;
152
  assign ic_tag_match     = 1'b0;
153
  assign ic_cache_hit     = bus2ic_valid & !rob_pipe_flush_seen;
154
  assign ic_if_ready      = 1'b1; // No need to initialize cache
155
  assign ic_if_data       = r_if_ic_fpc[2] ? bus2ic_data[63:32] : bus2ic_data[31:0];
156
  assign ic_if_data_valid = ic_cache_hit;
157
 
158
  `endif
159
 
160
 
161
  // Icache state machine
162
  always @*
163
    case (ic_state)
164
      // From the IDLE state
165
      //  + move to req if we detect a miss
166
      IC_STATE_IDLE: begin
167
          if (r_if_ic_req & !ic_cache_hit)
168
            ic_nstate = IC_STATE_REQ;
169
          else
170
            ic_nstate = IC_STATE_IDLE;
171
        end
172
 
173
      // In the REQ state we send the request to memory for the needed data.
174
      // Then transition to WAIT state to wait for memory response
175
      // TODO: Need to stall here if arbiter doesn't accept our request
176
      IC_STATE_REQ: begin
177
        ic_nstate = IC_STATE_WAIT;
178
        end
179
 
180
      // In the WAIT state we wait for memory response, then transition to
181
      // WR_RAM state to write the data.
182
      IC_STATE_WAIT: begin
183
        if (bus2ic_valid) ic_nstate = IC_STATE_IDLE;
184
        else              ic_nstate = IC_STATE_WAIT;
185
        end
186
 
187
      // From the INIT state, we initialize each line of the cache to invalid
188
      // and transition to IDLE after writing each line.
189
      IC_STATE_INIT: begin
190
          if (ic_init_ctr == `IC_NUM_LINES-1)
191
            ic_nstate = IC_STATE_IDLE;
192
          else
193
            ic_nstate = IC_STATE_INIT;
194
        end
195
 
196
      default: ic_nstate = IC_STATE_IDLE;
197
    endcase
198
 
199
  // For the initialization, just loop through every set in cache and write it as invalid.  When done
200
  // set ic_initialized.
201
  `ifdef USE_IC
202
  assign ic_init_done      = (ic_state == IC_STATE_INIT) & (ic_init_ctr == `IC_NUM_LINES-1);
203
  assign ic_initialized_ld = ic_init_done;
204
  assign ic_init_nctr      = ic_init_ctr + `IC_SI_SZ'h1;
205
  `else
206
  assign ic_init_done      = 1'b1;
207
  assign ic_initialized_ld = 1'b0;
208
  assign ic_init_nctr      = {`IC_SI_SZ{1'b0}};
209
  `endif
210
 
211
  MDFFR  #(3)         ic_state_ff (clk, rst, IC_STATE_INIT, ic_nstate, ic_state);
212
  MDFFLR #(`IC_SI_SZ) ic_init_ctr_ff (clk, rst, (ic_state == IC_STATE_INIT), `IC_SI_SZ'h0, ic_init_nctr, ic_init_ctr);
213
  MDFFLR #(1)         ic_initialized_ff (clk, rst, ic_initialized_ld, 1'b0, 1'b1, ic_initialized);
214
 
215
  // Handle memory request outputs
216
  // Note that we request from the bus the cycle after detecting a hit, so if_ic_fpc should be corrected from miss already.
217
  assign ic2bus_fpc = if_ic_fpc;
218
  assign ic2bus_req = (ic_state == IC_STATE_REQ);
219
 
220
endmodule

powered by: WebSVN 2.1.0

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