Commit 294bafd8064b09fd220ba38ecc17d97045208e1b

Authored by Sankara Ramesh
1 parent d3c3d4e520

updating icache sizes

Showing 1 changed file with 1 additions and 1 deletions Inline Diff

mips_cpu/mips_core/i_cache.sv View file @ 294bafd
/* 1 1 /*
* i_cache.sv 2 2 * i_cache.sv
* Author: Zinsser Zhang 3 3 * Author: Zinsser Zhang
* Last Revision: 03/13/2022 4 4 * Last Revision: 03/13/2022
* 5 5 *
* This is a direct-mapped instruction cache. Line size and depth (number of 6 6 * This is a direct-mapped instruction cache. Line size and depth (number of
* lines) are set via INDEX_WIDTH and BLOCK_OFFSET_WIDTH parameters. Notice that 7 7 * lines) are set via INDEX_WIDTH and BLOCK_OFFSET_WIDTH parameters. Notice that
* line size means number of words (each consist of 32 bit) in a line. Because 8 8 * line size means number of words (each consist of 32 bit) in a line. Because
* all addresses in mips_core are 26 byte addresses, so the sum of TAG_WIDTH, 9 9 * all addresses in mips_core are 26 byte addresses, so the sum of TAG_WIDTH,
* INDEX_WIDTH and BLOCK_OFFSET_WIDTH is `ADDR_WIDTH - 2. 10 10 * INDEX_WIDTH and BLOCK_OFFSET_WIDTH is `ADDR_WIDTH - 2.
* 11 11 *
* Typical line sizes are from 2 words to 8 words. The memory interfaces only 12 12 * Typical line sizes are from 2 words to 8 words. The memory interfaces only
* support up to 8 words line size. 13 13 * support up to 8 words line size.
* 14 14 *
* Because we need a hit latency of 1 cycle, we need an asynchronous read port, 15 15 * Because we need a hit latency of 1 cycle, we need an asynchronous read port,
* i.e. data is ready during the same cycle when address is calculated. However, 16 16 * i.e. data is ready during the same cycle when address is calculated. However,
* SRAMs only support synchronous read, i.e. data is ready the cycle after the 17 17 * SRAMs only support synchronous read, i.e. data is ready the cycle after the
* address is calculated. Due to this conflict, we need to read from the banks 18 18 * address is calculated. Due to this conflict, we need to read from the banks
* on the clock edge at the beginning of the cycle. As a result, we need both 19 19 * on the clock edge at the beginning of the cycle. As a result, we need both
* the registered version of address and a non-registered version of address 20 20 * the registered version of address and a non-registered version of address
* (which will effectively be registered in SRAM). 21 21 * (which will effectively be registered in SRAM).
* 22 22 *
* See wiki page "Synchronous Caches" for details. 23 23 * See wiki page "Synchronous Caches" for details.
*/ 24 24 */
`include "mips_core.svh" 25 25 `include "mips_core.svh"
26 26
module i_cache #( 27 27 module i_cache #(
parameter INDEX_WIDTH = 5, 28 28 parameter INDEX_WIDTH = 8,
parameter BLOCK_OFFSET_WIDTH = 2 29 29 parameter BLOCK_OFFSET_WIDTH = 2
)( 30 30 )(
// General signals 31 31 // General signals
input clk, // Clock 32 32 input clk, // Clock
input rst_n, // Synchronous reset active low 33 33 input rst_n, // Synchronous reset active low
34 34
// Request 35 35 // Request
pc_ifc.in i_pc_current, 36 36 pc_ifc.in i_pc_current,
pc_ifc.in i_pc_next, 37 37 pc_ifc.in i_pc_next,
38 38
// Response 39 39 // Response
cache_output_ifc.out out, 40 40 cache_output_ifc.out out,
41 41
// Memory interface 42 42 // Memory interface
axi_read_address.master mem_read_address, 43 43 axi_read_address.master mem_read_address,
axi_read_data.master mem_read_data 44 44 axi_read_data.master mem_read_data
); 45 45 );
localparam TAG_WIDTH = `ADDR_WIDTH - INDEX_WIDTH - BLOCK_OFFSET_WIDTH - 2; 46 46 localparam TAG_WIDTH = `ADDR_WIDTH - INDEX_WIDTH - BLOCK_OFFSET_WIDTH - 2;
localparam LINE_SIZE = 1 << BLOCK_OFFSET_WIDTH; 47 47 localparam LINE_SIZE = 1 << BLOCK_OFFSET_WIDTH;
localparam DEPTH = 1 << INDEX_WIDTH; 48 48 localparam DEPTH = 1 << INDEX_WIDTH;
49 49
// Check if the parameters are set correctly 50 50 // Check if the parameters are set correctly
generate 51 51 generate
if(TAG_WIDTH <= 0 || LINE_SIZE > 16) 52 52 if(TAG_WIDTH <= 0 || LINE_SIZE > 16)
begin 53 53 begin
INVALID_I_CACHE_PARAM invalid_i_cache_param (); 54 54 INVALID_I_CACHE_PARAM invalid_i_cache_param ();
end 55 55 end
endgenerate 56 56 endgenerate
57 57
// Parsing 58 58 // Parsing
logic [TAG_WIDTH - 1 : 0] i_tag; 59 59 logic [TAG_WIDTH - 1 : 0] i_tag;
logic [INDEX_WIDTH - 1 : 0] i_index; 60 60 logic [INDEX_WIDTH - 1 : 0] i_index;
logic [BLOCK_OFFSET_WIDTH - 1 : 0] i_block_offset; 61 61 logic [BLOCK_OFFSET_WIDTH - 1 : 0] i_block_offset;
62 62
logic [INDEX_WIDTH - 1 : 0] i_index_next; 63 63 logic [INDEX_WIDTH - 1 : 0] i_index_next;
64 64
assign {i_tag, i_index, i_block_offset} = i_pc_current.pc[`ADDR_WIDTH - 1 : 2]; 65 65 assign {i_tag, i_index, i_block_offset} = i_pc_current.pc[`ADDR_WIDTH - 1 : 2];
assign i_index_next = i_pc_next.pc[BLOCK_OFFSET_WIDTH + 2 +: INDEX_WIDTH]; 66 66 assign i_index_next = i_pc_next.pc[BLOCK_OFFSET_WIDTH + 2 +: INDEX_WIDTH];
// Above line uses +: slice, a feature of SystemVerilog 67 67 // Above line uses +: slice, a feature of SystemVerilog
// See https://stackoverflow.com/questions/18067571 68 68 // See https://stackoverflow.com/questions/18067571
69 69
// States 70 70 // States
enum logic[1:0] { 71 71 enum logic[1:0] {
STATE_READY, // Ready for incoming requests 72 72 STATE_READY, // Ready for incoming requests
STATE_REFILL_REQUEST, // Sending out a memory read request 73 73 STATE_REFILL_REQUEST, // Sending out a memory read request
STATE_REFILL_DATA // Missing on a read 74 74 STATE_REFILL_DATA // Missing on a read
} state, next_state; 75 75 } state, next_state;
76 76
// Registers for refilling 77 77 // Registers for refilling
logic [INDEX_WIDTH - 1:0] r_index; 78 78 logic [INDEX_WIDTH - 1:0] r_index;
logic [TAG_WIDTH - 1:0] r_tag; 79 79 logic [TAG_WIDTH - 1:0] r_tag;
80 80
// databank signals 81 81 // databank signals
logic [LINE_SIZE - 1 : 0] databank_select; 82 82 logic [LINE_SIZE - 1 : 0] databank_select;
logic [LINE_SIZE - 1 : 0] databank_we; 83 83 logic [LINE_SIZE - 1 : 0] databank_we;
logic [`DATA_WIDTH - 1 : 0] databank_wdata; 84 84 logic [`DATA_WIDTH - 1 : 0] databank_wdata;
logic [INDEX_WIDTH - 1 : 0] databank_waddr; 85 85 logic [INDEX_WIDTH - 1 : 0] databank_waddr;
logic [INDEX_WIDTH - 1 : 0] databank_raddr; 86 86 logic [INDEX_WIDTH - 1 : 0] databank_raddr;
logic [`DATA_WIDTH - 1 : 0] databank_rdata [LINE_SIZE]; 87 87 logic [`DATA_WIDTH - 1 : 0] databank_rdata [LINE_SIZE];
88 88
// databanks 89 89 // databanks
genvar g; 90 90 genvar g;
generate 91 91 generate
for (g = 0; g < LINE_SIZE; g++) 92 92 for (g = 0; g < LINE_SIZE; g++)
begin : databanks 93 93 begin : databanks
cache_bank #( 94 94 cache_bank #(
.DATA_WIDTH (`DATA_WIDTH), 95 95 .DATA_WIDTH (`DATA_WIDTH),
.ADDR_WIDTH (INDEX_WIDTH) 96 96 .ADDR_WIDTH (INDEX_WIDTH)
) databank ( 97 97 ) databank (
.clk, 98 98 .clk,
.i_we (databank_we[g]), 99 99 .i_we (databank_we[g]),
.i_wdata(databank_wdata), 100 100 .i_wdata(databank_wdata),
.i_waddr(databank_waddr), 101 101 .i_waddr(databank_waddr),
.i_raddr(databank_raddr), 102 102 .i_raddr(databank_raddr),
103 103
.o_rdata(databank_rdata[g]) 104 104 .o_rdata(databank_rdata[g])
); 105 105 );
end 106 106 end
endgenerate 107 107 endgenerate
108 108
// tagbank signals 109 109 // tagbank signals
logic tagbank_we; 110 110 logic tagbank_we;
logic [TAG_WIDTH - 1 : 0] tagbank_wdata; 111 111 logic [TAG_WIDTH - 1 : 0] tagbank_wdata;
logic [INDEX_WIDTH - 1 : 0] tagbank_waddr; 112 112 logic [INDEX_WIDTH - 1 : 0] tagbank_waddr;
logic [INDEX_WIDTH - 1 : 0] tagbank_raddr; 113 113 logic [INDEX_WIDTH - 1 : 0] tagbank_raddr;
logic [TAG_WIDTH - 1 : 0] tagbank_rdata; 114 114 logic [TAG_WIDTH - 1 : 0] tagbank_rdata;
115 115
cache_bank #( 116 116 cache_bank #(
.DATA_WIDTH (TAG_WIDTH), 117 117 .DATA_WIDTH (TAG_WIDTH),
.ADDR_WIDTH (INDEX_WIDTH) 118 118 .ADDR_WIDTH (INDEX_WIDTH)
) tagbank ( 119 119 ) tagbank (
.clk, 120 120 .clk,
.i_we (tagbank_we), 121 121 .i_we (tagbank_we),
.i_wdata (tagbank_wdata), 122 122 .i_wdata (tagbank_wdata),
.i_waddr (tagbank_waddr), 123 123 .i_waddr (tagbank_waddr),
.i_raddr (tagbank_raddr), 124 124 .i_raddr (tagbank_raddr),
125 125
.o_rdata (tagbank_rdata) 126 126 .o_rdata (tagbank_rdata)
); 127 127 );
128 128
// Valid bits 129 129 // Valid bits
logic [DEPTH - 1 : 0] valid_bits; 130 130 logic [DEPTH - 1 : 0] valid_bits;
131 131
// Intermediate signals 132 132 // Intermediate signals
logic hit, miss; 133 133 logic hit, miss;
logic last_refill_word; 134 134 logic last_refill_word;
135 135
136 136
always_comb 137 137 always_comb
begin 138 138 begin
hit = valid_bits[i_index] 139 139 hit = valid_bits[i_index]
& (i_tag == tagbank_rdata) 140 140 & (i_tag == tagbank_rdata)
& (state == STATE_READY); 141 141 & (state == STATE_READY);
miss = ~hit; 142 142 miss = ~hit;
last_refill_word = databank_select[LINE_SIZE - 1] 143 143 last_refill_word = databank_select[LINE_SIZE - 1]
& mem_read_data.RVALID; 144 144 & mem_read_data.RVALID;
end 145 145 end
146 146
always_comb 147 147 always_comb
begin 148 148 begin
mem_read_address.ARADDR = {r_tag, r_index, 149 149 mem_read_address.ARADDR = {r_tag, r_index,
{BLOCK_OFFSET_WIDTH + 2{1'b0}}}; 150 150 {BLOCK_OFFSET_WIDTH + 2{1'b0}}};
mem_read_address.ARLEN = LINE_SIZE; 151 151 mem_read_address.ARLEN = LINE_SIZE;
mem_read_address.ARVALID = state == STATE_REFILL_REQUEST; 152 152 mem_read_address.ARVALID = state == STATE_REFILL_REQUEST;
mem_read_address.ARID = 4'd0; 153 153 mem_read_address.ARID = 4'd0;
154 154
// Always ready to consume data 155 155 // Always ready to consume data
mem_read_data.RREADY = 1'b1; 156 156 mem_read_data.RREADY = 1'b1;
end 157 157 end
158 158
always_comb 159 159 always_comb
begin 160 160 begin
if (mem_read_data.RVALID) 161 161 if (mem_read_data.RVALID)
databank_we = databank_select; 162 162 databank_we = databank_select;
else 163 163 else
databank_we = '0; 164 164 databank_we = '0;
165 165
databank_wdata = mem_read_data.RDATA; 166 166 databank_wdata = mem_read_data.RDATA;
databank_waddr = r_index; 167 167 databank_waddr = r_index;
databank_raddr = i_index_next; 168 168 databank_raddr = i_index_next;
end 169 169 end
170 170
always_comb 171 171 always_comb
begin 172 172 begin
tagbank_we = last_refill_word; 173 173 tagbank_we = last_refill_word;
tagbank_wdata = r_tag; 174 174 tagbank_wdata = r_tag;
tagbank_waddr = r_index; 175 175 tagbank_waddr = r_index;
tagbank_raddr = i_index_next; 176 176 tagbank_raddr = i_index_next;
end 177 177 end
178 178
always_comb 179 179 always_comb
begin 180 180 begin
out.valid = hit; 181 181 out.valid = hit;
out.data = databank_rdata[i_block_offset]; 182 182 out.data = databank_rdata[i_block_offset];
end 183 183 end
184 184
always_comb 185 185 always_comb
begin 186 186 begin
next_state = state; 187 187 next_state = state;
unique case (state) 188 188 unique case (state)
STATE_READY: 189 189 STATE_READY:
if (miss) 190 190 if (miss)
next_state = STATE_REFILL_REQUEST; 191 191 next_state = STATE_REFILL_REQUEST;
STATE_REFILL_REQUEST: 192 192 STATE_REFILL_REQUEST:
if (mem_read_address.ARREADY) 193 193 if (mem_read_address.ARREADY)
next_state = STATE_REFILL_DATA; 194 194 next_state = STATE_REFILL_DATA;
STATE_REFILL_DATA: 195 195 STATE_REFILL_DATA:
if (last_refill_word) 196 196 if (last_refill_word)
next_state = STATE_READY; 197 197 next_state = STATE_READY;
endcase 198 198 endcase
end 199 199 end
200 200
always_ff @(posedge clk) 201 201 always_ff @(posedge clk)
begin 202 202 begin
if(~rst_n) 203 203 if(~rst_n)
begin 204 204 begin
state <= STATE_READY; 205 205 state <= STATE_READY;
databank_select <= 1; 206 206 databank_select <= 1;
valid_bits <= '0; 207 207 valid_bits <= '0;
end 208 208 end
else 209 209 else