Repository navigation
Expand file tree
/
Copy pathcam2.sv
More file actions
102 lines (91 loc) · 3.98 KB
/
Copy pathcam2.sv
File metadata and controls
102 lines (91 loc) · 3.98 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
// Cache using CAM
module cam2
#(
parameter WORDS=8, // default number of words
parameter BITS=8, // default number of bits per word
parameter ADDR_LEFT=$clog2(WORDS)-1, // log base 2 of the number of words
// which is # of bits needed to address
// the memory for read and write
parameter TAG_SZ=8 // size of the tag
)
(
output logic [BITS-1:0] cache_data, // the data
output logic cache_hit, // was in the CAM
output logic cache_full, // CAM is full
input [TAG_SZ-1:0] check_tag, // the tag to match
input read, // read signal
input write_, // write_ signal
input [ADDR_LEFT:0] w_addr, // address to write (for clear only)
input [BITS-1:0] wdata, // data to write
input [TAG_SZ-1:0] new_tag, // the new tag
input new_valid, // new valid bit
input clk, // system clock
input rst_ // system reset
);
`include "cam_params.vh"
logic [BITS-1:0] data_mem[0:WORDS-1]; // data memory
logic [TAG_SZ-1:0] tag_mem[0:WORDS-1]; // tag memory
logic [WORDS-1:0] val_mem; // valid memory
integer index; // for the read loop
logic [ADDR_LEFT:0] match_index; // where we found it (read)
logic found; // did we find it (read)
// New variables for HW10 write logic
integer windex; // for the write loop
logic [ADDR_LEFT:0] write_index; // where to write
logic write_found; // found an empty spot
// Reset and Write Logic (Sequential)
always_ff @(posedge clk or negedge rst_) begin
if (!rst_) begin
// Initialize all memories to 0 on reset
for (integer i = 0; i < WORDS; i++) begin
data_mem[i] <= {BITS{1'b0}};
tag_mem[i] <= {TAG_SZ{1'b0}};
val_mem[i] <= 1'b0;
end
end else if (!write_) begin
// Two modes of operation:
if (new_valid) begin
// Write mode: CAM finds empty spot and writes there
if (!cache_full) begin
data_mem[write_index] <= wdata;
tag_mem[write_index] <= new_tag;
val_mem[write_index] <= 1'b1;
end
// else: CAM is full, ignore the write
end else begin
// Clear mode: invalidate entry at w_addr
val_mem[w_addr] <= 1'b0;
end
end
end
// CAM Read Search Logic (Combinational)
always_comb begin
found = 1'b0;
match_index = INDEX_PACKED[5:0] & {{(6-ADDR_LEFT-1){1'b0}}, {(ADDR_LEFT+1){1'b1}}};
if (read) begin
// Search all entries in parallel for matching tag
for (index = 0; index < WORDS; index++) begin
if (val_mem[index] && (tag_mem[index] == check_tag)) begin
match_index = INDEX_PACKED[(index*6) +: 6] & {{(6-ADDR_LEFT-1){1'b0}}, {(ADDR_LEFT+1){1'b1}}};
found = 1'b1;
end
end
end
end
// CAM Write Search Logic (Combinational) - Find first empty spot
always_comb begin
write_found = 1'b0;
write_index = INDEX_PACKED[5:0] & {{(6-ADDR_LEFT-1){1'b0}}, {(ADDR_LEFT+1){1'b1}}};
// Search for first invalid entry (empty spot)
for (windex = 0; windex < WORDS; windex++) begin
if (!val_mem[windex] && !write_found) begin
write_index = INDEX_PACKED[(windex*6) +: 6] & {{(6-ADDR_LEFT-1){1'b0}}, {(ADDR_LEFT+1){1'b1}}};
write_found = 1'b1;
end
end
end
// Output assignments
assign cache_data = found ? data_mem[match_index] : {BITS{1'b0}};
assign cache_hit = found;
assign cache_full = !write_found; // CAM is full if no empty spot found
endmodule