-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathca_ctrl.sv
More file actions
119 lines (102 loc) · 4.19 KB
/
ca_ctrl.sv
File metadata and controls
119 lines (102 loc) · 4.19 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
// Cache control state machine with FIFO replacement policy
module ca_ctrl
#(
parameter CACHE_ENTRIES = 8, // number of cache entries
parameter CACHE_ADDR_LEFT=$clog2(CACHE_ENTRIES)-1 // log2 of entries
)
(
output logic cache_read, // ok to read from cache
output logic cache_write_, // write to clear or set an entry
output logic [CACHE_ADDR_LEFT:0] cache_w_addr, // address to clear
output logic new_valid, // whether clearing or not
output logic cache_stall, // stall waiting for the cache
input cache_hit, // cache hit (or miss)
input cache_full, // cache is full
input branch_or_jump,// branching or jumping
input clk, // system clock
input rst_ // system reset
);
// State machine states
localparam STATE_BITS = 2;
localparam [STATE_BITS-1:0] IDLE = 2'h0; // Idle state
localparam [STATE_BITS-1:0] LOAD = 2'h1; // Load from memory state
localparam [STATE_BITS-1:0] CLEAR = 2'h2; // Clear a memory location
logic [STATE_BITS-1:0] state;
logic [STATE_BITS-1:0] next_state;
// FIFO replacement counter - simple counter to decide address to clear
logic [CACHE_ADDR_LEFT:0] fifo_counter;
// State register with FIFO counter
always_ff @(posedge clk or negedge rst_) begin
if (!rst_) begin
state <= IDLE;
fifo_counter <= {(CACHE_ADDR_LEFT+1){1'b0}};
end else begin
state <= next_state;
// Increment FIFO counter on replacement (when we clear an entry)
if (state == CLEAR) begin
if (fifo_counter == (CACHE_ENTRIES - 1))
fifo_counter <= {(CACHE_ADDR_LEFT+1){1'b0}};
else
fifo_counter <= fifo_counter + 1'b1;
end
end
end
// Next state logic
always_comb begin
case (state)
IDLE: begin
if (!cache_hit && !branch_or_jump) begin
// Cache miss and NOT jumping/branching
if (cache_full) begin
next_state = CLEAR; // Cache is full, need to evict first
end else begin
next_state = LOAD; // Free spot available, load directly
end
end else begin
next_state = IDLE; // Cache hit or control hazard, stay in IDLE
end
end
LOAD: begin
next_state = IDLE; // Load takes 1 cycle, return to IDLE
end
CLEAR: begin
next_state = LOAD; // After clear, go to LOAD
end
default: next_state = IDLE;
endcase
end
// Output logic
always_comb begin
// Default values
cache_read = 1'b1; // Always try to read from cache
cache_write_ = 1'b1; // No write by default
cache_w_addr = fifo_counter; // Use FIFO counter for victim selection
new_valid = 1'b0; // Default: clear mode (new_valid=0)
cache_stall = 1'b0; // No stall by default
case (state)
IDLE: begin
cache_read = 1'b1; // Always reading in IDLE
if (!cache_hit && !branch_or_jump) begin
cache_stall = 1'b1; // Stall on miss (unless branch/jump)
end
end
LOAD: begin
cache_write_ = 1'b0; // Write to cache
new_valid = 1'b1; // Set valid bit (write mode)
cache_stall = 1'b1; // Stall during load
end
CLEAR: begin
cache_write_ = 1'b0; // Write to cache
new_valid = 1'b0; // Clear valid bit (clear mode)
cache_w_addr = fifo_counter; // FIFO victim selection
cache_stall = 1'b1; // Stall during clear
end
default: begin
cache_read = 1'b1;
cache_write_ = 1'b1;
new_valid = 1'b0;
cache_stall = 1'b0;
end
endcase
end
endmodule