diff options
Diffstat (limited to '')
| -rw-r--r-- | hdl/mem_cache.sv | 108 |
1 files changed, 108 insertions, 0 deletions
diff --git a/hdl/mem_cache.sv b/hdl/mem_cache.sv new file mode 100644 index 0000000..5f3db73 --- /dev/null +++ b/hdl/mem_cache.sv | |||
| @@ -0,0 +1,108 @@ | |||
| 1 | `include "defs.svh" | ||
| 2 | |||
| 3 | module mem_cache | ||
| 4 | #( SET_BITS = 8 | ||
| 5 | ) | ||
| 6 | ( input bit clock | ||
| 7 | , input bit reset | ||
| 8 | |||
| 9 | , output bit core_command_ready | ||
| 10 | , input bit core_command_valid | ||
| 11 | , input pdp_command_t core_command_data | ||
| 12 | |||
| 13 | , input bit ram_command_ready | ||
| 14 | , output bit ram_command_valid | ||
| 15 | , output pdp_command_t ram_command_data | ||
| 16 | |||
| 17 | , output bit ram_response_ready | ||
| 18 | , input bit ram_response_valid | ||
| 19 | , input pdp_read_response_t ram_response_data | ||
| 20 | |||
| 21 | , input bit core_response_ready | ||
| 22 | , output bit core_response_valid | ||
| 23 | , output pdp_read_response_t core_response_data | ||
| 24 | ); | ||
| 25 | |||
| 26 | localparam ADDRESS_TAG_LO = $clog2(`RAM_LINE_WORDS)+SET_BITS; | ||
| 27 | |||
| 28 | typedef bit [`PDP_ADDRESS_BITS-1:ADDRESS_TAG_LO] address_tag_t; | ||
| 29 | typedef bit [ADDRESS_TAG_LO-1:$clog2(`RAM_LINE_WORDS)] set_t; | ||
| 30 | |||
| 31 | typedef struct packed { | ||
| 32 | bit valid; | ||
| 33 | address_tag_t address; | ||
| 34 | } tag_t; | ||
| 35 | |||
| 36 | typedef struct packed { | ||
| 37 | tag_t tag; | ||
| 38 | ram_line_t data; | ||
| 39 | } cache_entry_t; | ||
| 40 | |||
| 41 | (* ramstyle = "no_rw_check, M9K" *) cache_entry_t cache [(1<<SET_BITS)-1:0]; | ||
| 42 | |||
| 43 | bit outstanding_fill; | ||
| 44 | |||
| 45 | bit [SET_BITS:0] reset_entry; | ||
| 46 | |||
| 47 | always @(posedge clock) begin | ||
| 48 | if (reset) begin | ||
| 49 | core_command_ready = 0; | ||
| 50 | ram_command_valid = 0; | ||
| 51 | ram_response_ready = 0; | ||
| 52 | core_response_valid = 0; | ||
| 53 | outstanding_fill = 0; | ||
| 54 | reset_entry = 0; | ||
| 55 | end else if (reset_entry < (1<<SET_BITS)) begin | ||
| 56 | cache[reset_entry] = 0; | ||
| 57 | ++reset_entry; | ||
| 58 | end else begin | ||
| 59 | if (ram_command_ready && ram_command_valid) | ||
| 60 | ram_command_valid = 0; | ||
| 61 | if (core_response_ready && core_response_valid) | ||
| 62 | core_response_valid = 0; | ||
| 63 | |||
| 64 | if (ram_response_ready && ram_response_valid) begin | ||
| 65 | automatic address_tag_t tag; | ||
| 66 | automatic set_t set; | ||
| 67 | automatic cache_entry_t entry; | ||
| 68 | {tag, set} = ram_response_data.address; | ||
| 69 | entry.tag.valid = 1; | ||
| 70 | entry.tag.address = tag; | ||
| 71 | entry.data = ram_response_data.data; | ||
| 72 | cache[set] = entry; | ||
| 73 | core_response_valid = 1; | ||
| 74 | core_response_data = ram_response_data; | ||
| 75 | outstanding_fill = 0; | ||
| 76 | end else if (core_command_ready && core_command_valid) begin | ||
| 77 | automatic address_tag_t tag; | ||
| 78 | automatic set_t set; | ||
| 79 | {tag, set} = core_command_data.address; | ||
| 80 | if (core_command_data.write) begin | ||
| 81 | automatic cache_entry_t entry; | ||
| 82 | entry.tag.valid = 1; | ||
| 83 | entry.tag.address = tag; | ||
| 84 | // FIXME masked stores | ||
| 85 | entry.data = core_command_data.data; | ||
| 86 | cache[set] = entry; | ||
| 87 | ram_command_valid = 1; | ||
| 88 | ram_command_data = core_command_data; | ||
| 89 | end else begin | ||
| 90 | automatic cache_entry_t entry = cache[set]; | ||
| 91 | if (entry.tag.valid && entry.tag.address == tag) begin | ||
| 92 | core_response_valid = 1; | ||
| 93 | core_response_data.address = {tag, set}; | ||
| 94 | core_response_data.data = entry.data; | ||
| 95 | end else begin | ||
| 96 | ram_command_valid = 1; | ||
| 97 | ram_command_data = core_command_data; | ||
| 98 | outstanding_fill = 1; | ||
| 99 | end | ||
| 100 | end | ||
| 101 | end | ||
| 102 | |||
| 103 | core_command_ready = !ram_command_valid && !core_response_valid && !outstanding_fill; | ||
| 104 | ram_response_ready = !core_response_valid; | ||
| 105 | end | ||
| 106 | end | ||
| 107 | |||
| 108 | endmodule | ||
