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
|
`include "defs.svh"
module mem_cache
#( SET_BITS = 8
)
( input bit clock
, input bit reset
, input bit clear
, output bit core_command_ready
, input bit core_command_valid
, input pdp_command_t core_command_data
, input bit ram_command_ready
, output bit ram_command_valid
, output pdp_command_t ram_command_data
, output bit ram_response_ready
, input bit ram_response_valid
, input pdp_read_response_t ram_response_data
, input bit core_response_ready
, output bit core_response_valid
, output pdp_read_response_t core_response_data
);
localparam ADDRESS_TAG_LO = $clog2(`RAM_LINE_WORDS)+SET_BITS;
typedef bit [`PDP_ADDRESS_BITS-1:ADDRESS_TAG_LO] address_tag_t;
typedef bit [ADDRESS_TAG_LO-1:$clog2(`RAM_LINE_WORDS)] set_t;
typedef struct packed {
bit valid;
address_tag_t address;
} tag_t;
typedef struct packed {
tag_t tag;
ram_line_t data;
} cache_entry_t;
(* ramstyle = "no_rw_check, M9K" *) cache_entry_t cache [(1<<SET_BITS)-1:0];
bit outstanding_fill;
bit [SET_BITS:0] reset_entry;
always @(posedge clock) begin
if (reset) begin
core_command_ready = 0;
ram_command_valid = 0;
ram_response_ready = 0;
core_response_valid = 0;
outstanding_fill = 0;
reset_entry = 0;
end else begin
if (clear)
reset_entry = 0;
if (ram_command_ready && ram_command_valid)
ram_command_valid = 0;
if (core_response_ready && core_response_valid)
core_response_valid = 0;
if (!outstanding_fill && !reset_entry[SET_BITS]) begin
cache[reset_entry[SET_BITS-1:0]] = 0;
++reset_entry;
end else if (ram_response_ready && ram_response_valid && outstanding_fill) begin
automatic address_tag_t tag;
automatic set_t set;
automatic cache_entry_t entry;
{tag, set} = ram_response_data.address;
entry.tag.valid = 1;
entry.tag.address = tag;
entry.data = ram_response_data.data;
cache[set] = entry;
core_response_valid = 1;
core_response_data = ram_response_data;
outstanding_fill = 0;
end else if (core_command_ready && core_command_valid) begin
automatic address_tag_t tag;
automatic set_t set;
{tag, set} = core_command_data.address;
if (core_command_data.write) begin
automatic cache_entry_t entry;
entry.tag.valid = 1;
entry.tag.address = tag;
// FIXME masked stores
entry.data = core_command_data.data;
cache[set] = entry;
ram_command_valid = 1;
ram_command_data = core_command_data;
end else begin
automatic cache_entry_t entry = cache[set];
if (entry.tag.valid && entry.tag.address == tag) begin
core_response_valid = 1;
core_response_data.address = {tag, set};
core_response_data.data = entry.data;
end else begin
ram_command_valid = 1;
ram_command_data = core_command_data;
outstanding_fill = 1;
end
end
end
core_command_ready = reset_entry[SET_BITS] && !ram_command_valid && !core_response_valid && !outstanding_fill;
ram_response_ready = !core_response_valid;
end
end
endmodule
|