| @@ -1,148 +1,75 @@ | ||
| import lc3b_types::*; | ||
|
|
||
| module DGM_tb; | ||
|
|
||
| timeunit 1ns; | ||
| timeprecision 1ns; | ||
|
|
||
| logic clk; | ||
| /* | ||
| logic a_mem_resp; | ||
| logic a_mem_read; | ||
| logic a_mem_write; | ||
| logic [1:0] a_mem_byte_enable; | ||
| logic [15:0] a_mem_address; | ||
| logic [15:0] a_mem_rdata; | ||
| logic [15:0] a_mem_wdata; | ||
| logic b_mem_resp; | ||
| logic b_mem_read; | ||
| logic b_mem_write; | ||
| logic [1:0] b_mem_byte_enable; | ||
| logic [15:0] b_mem_address; | ||
| logic [15:0] b_mem_rdata; | ||
| logic [15:0] b_mem_wdata; | ||
| */ | ||
|
|
||
| logic resp; | ||
| logic [127:0] rdata; | ||
| logic read; | ||
| logic write; | ||
| logic [15:0] address; | ||
| logic [127:0] wdata; | ||
|
|
||
|
|
||
| /* Clock generator */ | ||
| initial clk = 0; | ||
| always #5 clk = ~clk; | ||
|
|
||
| //assign a_mem_write = 1'b0; | ||
| //assign a_mem_wdata = 16'h0; | ||
|
|
||
| //assign b_mem_byte_enable = 2'b11; | ||
|
|
||
|
|
||
|
|
||
|
|
||
| DGM top( | ||
|
|
||
| .clk(clk), | ||
| .resp(resp), | ||
| .rdata(rdata), | ||
| .address(address), | ||
| .read(read), | ||
| .write(write), | ||
| .wdata(wdata) | ||
|
|
||
| ); | ||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
| physical_memory the_memory( | ||
| .clk(clk), | ||
| .read(read), | ||
| .write(write), | ||
| .address(address), | ||
| .wdata(wdata), | ||
| .resp(resp), | ||
| .rdata(rdata) | ||
| ); | ||
|
|
||
| endmodule : DGM_tb | ||
|
|
||
|
|
| @@ -9,7 +9,8 @@ module lru | ||
| output logic lru_out | ||
| ); | ||
|
|
||
| /* lru bits changed to 16 bits for increasing cache size */ | ||
| logic lru_bits[15:0]; | ||
|
|
||
| initial | ||
| begin | ||
| @@ -4,8 +4,10 @@ module adder #(parameter width = 16) | ||
| output logic [width-1:0] out | ||
| ); | ||
|
|
||
| //testing comment | ||
|
|
||
| always_comb | ||
| begin | ||
| out = a + b; | ||
| end | ||
| endmodule : adder | ||
| @@ -1,29 +1,29 @@ | ||
| import lc3b_types::*; | ||
|
|
||
| module addrgen | ||
| ( | ||
| input lru, | ||
| input pmem_address_sel, | ||
| input lc3b_word mem_address, | ||
| input lc3b_tag tag0, | ||
| input lc3b_tag tag1, | ||
| input lc3b_set set, | ||
| output lc3b_word addrgen_out | ||
| ); | ||
|
|
||
| always_comb | ||
| begin | ||
| if (pmem_address_sel == 0) | ||
| begin | ||
| addrgen_out = mem_address; | ||
| end | ||
| else | ||
| begin | ||
| if (lru == 0) | ||
| addrgen_out = {tag0, set, 4'b0}; | ||
| else | ||
| addrgen_out = {tag1, set, 4'b0}; | ||
| end | ||
| end | ||
|
|
||
| endmodule : addrgen |
| @@ -0,0 +1,29 @@ | ||
| import lc3b_types::*; | ||
|
|
||
| module addrgen_l2 | ||
| ( | ||
| input lru, | ||
| input pmem_address_sel, | ||
| input lc3b_word mem_address, | ||
| input lc3b_tag_l2 tag0, | ||
| input lc3b_tag_l2 tag1, | ||
| input lc3b_set_l2 set, | ||
| output lc3b_word addrgen_out | ||
| ); | ||
|
|
||
| always_comb | ||
| begin | ||
| if (pmem_address_sel == 0) | ||
| begin | ||
| addrgen_out = mem_address; | ||
| end | ||
| else | ||
| begin | ||
| if (lru == 0) | ||
| addrgen_out = {tag0, set, 4'b0}; | ||
| else | ||
| addrgen_out = {tag1, set, 4'b0}; | ||
| end | ||
| end | ||
|
|
||
| endmodule : addrgen_l2 |
| @@ -1,98 +1,97 @@ | ||
| import lc3b_types::*; | ||
|
|
||
| /** | ||
| * The arbiter of cache design | ||
| * The arbiter located in between of two parts of Level 1 cache, and level 2 cache | ||
| * It takes control for data input and output between level 1 and level 2 caches | ||
| * The arbiter should be fully combinational logic | ||
| */ | ||
|
|
||
| module arbiter ( | ||
| /* inputs */ | ||
| /* input from IF cache */ | ||
| input lc3b_word IF_address, | ||
| input logic IF_read, | ||
| input logic IF_write, | ||
| input lc3b_burst IF_wdata, | ||
|
|
||
| /* input from MEM cache */ | ||
| input lc3b_word MEM_address, | ||
| input logic MEM_read, | ||
| input logic MEM_write, | ||
| input lc3b_burst MEM_wdata, | ||
|
|
||
| /* input from L2 cache */ | ||
| input logic l2_resp, | ||
| input lc3b_burst l2_rdata, | ||
|
|
||
|
|
||
| /* outputs */ | ||
| /* output to IF cache */ | ||
| output logic l2i_resp, | ||
| output lc3b_burst l2i_rdata, | ||
| /* output to MEM cache */ | ||
| output logic l2d_resp, | ||
| output lc3b_burst l2d_rdata, | ||
| /* output to L2 cache */ | ||
| output lc3b_word l2_address, | ||
| output logic l2_read, | ||
| output logic l2_write, | ||
| output lc3b_burst l2_wdata | ||
| ); | ||
|
|
||
|
|
||
|
|
||
|
|
||
| /* The combinational logic made up arbiter */ | ||
| always_comb | ||
| begin | ||
| /* initial all signals */ | ||
| l2_read = 1'b0; | ||
| l2_write = 1'b0; | ||
| l2_address = 16'b0; | ||
| l2_wdata = 128'b0; | ||
| l2i_resp = 1'b0; | ||
| l2i_rdata = 128'b0; | ||
| l2d_resp = 1'b0; | ||
| l2d_rdata = 128'b0; | ||
|
|
||
| /* first detecting which cache is trying to access L2 */ | ||
| if(((IF_read == 1) || (IF_write == 1)) && (MEM_read == 0) && (MEM_write == 0)) | ||
| begin //case IF cache doing operation | ||
| // assign outputs to L2 | ||
| l2_read = IF_read; | ||
| l2_write = IF_write; | ||
| l2_address = IF_address; | ||
| l2_wdata = IF_wdata; | ||
| // assign output to IF cache | ||
| l2i_resp = l2_resp; | ||
| l2i_rdata = l2_rdata; | ||
| end | ||
| else if(MEM_read == 1 || MEM_write == 1)//all other conditions, operating MEM cache first | ||
| begin | ||
| //assign output to L2 | ||
| l2_read = MEM_read; | ||
| l2_write = MEM_write; | ||
| l2_address = MEM_address; | ||
| l2_wdata = MEM_wdata; | ||
| // assign output to MEM cache | ||
| l2d_resp = l2_resp; | ||
| l2d_rdata = l2_rdata; | ||
| end | ||
|
|
||
|
|
||
| end | ||
|
|
||
|
|
||
|
|
||
| endmodule: arbiter | ||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
| @@ -1,29 +1,30 @@ | ||
| module bitselect | ||
| ( | ||
| input sel0, | ||
| input sel1, | ||
| input lru, | ||
| input data0, | ||
| input data1, | ||
| output logic out | ||
| ); | ||
|
|
||
| always_comb | ||
| begin | ||
| out = 0; | ||
| if(sel0 == 1) | ||
| out = data0; | ||
| else if (sel1 == 1) | ||
| out = data1; | ||
| else | ||
| begin | ||
| case(lru) | ||
| 1'b0: | ||
| out = data0; | ||
| 1'b1: | ||
| out = data1; | ||
| endcase | ||
| end | ||
| end | ||
|
|
||
|
|
||
| endmodule : bitselect |
| @@ -0,0 +1,29 @@ | ||
| module bitselect_l2 | ||
| ( | ||
| input sel0, | ||
| input sel1, | ||
| input lru, | ||
| input data0, | ||
| input data1, | ||
| output logic out | ||
| ); | ||
|
|
||
| always_comb | ||
| begin | ||
| out = 0; | ||
| if(sel0 == 1) | ||
| out = data0; | ||
| else if (sel1 == 1) | ||
| out = data1; | ||
| else | ||
| begin | ||
| case(lru) | ||
| 1'b0: | ||
| out = data0; | ||
| 1'b1: | ||
| out = data1; | ||
| endcase | ||
| end | ||
| end | ||
|
|
||
| endmodule : bitselect_l2 |
| @@ -1,122 +1,121 @@ | ||
| /** | ||
| * The cache block for pipeline datapath | ||
| * It currently contains two level 1 cache, with seperation of Instruction cache | ||
| * and memory data cache. They are connected with arbiter in between | ||
| * | ||
| * The level two cache is much larger than the level one cache, which hold whwatever | ||
| * level one has also holds information level 1 dumps | ||
| * | ||
| * evict buffer should be designed after level 2 cache, which constantly writing data | ||
| * back into memory | ||
| */ | ||
|
|
||
| import lc3b_types::*; | ||
|
|
||
| module cache( | ||
| /* cache input from data path*/ | ||
| input clk, | ||
| /* IF memory signals */ | ||
| input lc3b_word if_memaddr, | ||
| input logic[1:0] if_mem_byte_enable, | ||
| input if_memread, | ||
| input lc3b_word if_mem_wdata, | ||
| input logic if_mem_write, | ||
|
|
||
| input logic l2i_resp, | ||
| input lc3b_burst l2i_rdata, | ||
|
|
||
|
|
||
| output lc3b_word if_mem_rdata, | ||
| output logic if_mem_resp, | ||
| output lc3b_word IF_address, | ||
| output lc3b_burst IF_wdata, | ||
| output logic IF_read, | ||
| output logic IF_write, | ||
|
|
||
| /* MEM memory signals */ | ||
| input lc3b_word mem_memaddr, | ||
| input logic[1:0] mem_mem_byte_enable, | ||
| input logic mem_memread, | ||
| input lc3b_word mem_mem_wdata, | ||
| input logic mem_mem_write, | ||
|
|
||
| input logic l2d_resp, | ||
| input lc3b_burst l2d_rdata, | ||
|
|
||
| output logic mem_mem_resp, | ||
| output lc3b_word mem_mem_rdata, | ||
| output lc3b_word MEM_address, | ||
| output lc3b_burst MEM_wdata, | ||
| output logic MEM_read, | ||
| output logic MEM_write | ||
|
|
||
|
|
||
| ); | ||
|
|
||
| /* cache module from MP2 was used and modified here */ | ||
|
|
||
|
|
||
| /* the instruction cache */ | ||
| cache_module IF_cache( | ||
| .clk, | ||
| .mem_address(if_memaddr), | ||
| .mem_rdata(if_mem_rdata), | ||
| .mem_wdata(if_mem_wdata), | ||
| .mem_read(if_memread), | ||
| .mem_write(if_mem_write), | ||
| .mem_byte_enable(if_mem_byte_enable), | ||
| .mem_resp(if_mem_resp), | ||
| .pmem_resp(l2i_resp), | ||
| .pmem_address(IF_address), | ||
| .pmem_rdata(l2i_rdata), | ||
| .pmem_wdata(IF_wdata), | ||
| .pmem_read(IF_read), | ||
| .pmem_write(IF_write) | ||
| ); | ||
|
|
||
| /* the data cache */ | ||
| cache_module MEM_cache( | ||
| .clk, | ||
| .mem_address(mem_memaddr), | ||
| .mem_rdata(mem_mem_rdata), | ||
| .mem_wdata(mem_mem_wdata), | ||
| .mem_read(mem_memread), | ||
| .mem_write(mem_mem_write), | ||
| .mem_byte_enable(mem_mem_byte_enable), | ||
| .mem_resp(mem_mem_resp), | ||
| .pmem_resp(l2d_resp), | ||
| .pmem_address(MEM_address), | ||
| .pmem_rdata(l2d_rdata), | ||
| .pmem_wdata(MEM_wdata), | ||
| .pmem_read(MEM_read), | ||
| .pmem_write(MEM_write) | ||
| ); | ||
|
|
||
|
|
||
|
|
||
| endmodule: cache | ||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
| @@ -1,112 +1,112 @@ | ||
| module cache_control | ||
| ( | ||
| input clk, | ||
| input mem_write, | ||
| input mem_read, | ||
| input pmem_resp, | ||
| input tag_hit, | ||
| input dirty, | ||
| input valid, | ||
|
|
||
| output logic mem_resp, | ||
| output logic load_valid, | ||
| output logic load_dirty, | ||
| output logic clear_dirty, | ||
| output logic load_tag, | ||
| output logic load_data, | ||
| output logic load_lru, | ||
| output logic pmem_addr_sel, | ||
| output logic pmem_write, | ||
| output logic pmem_read, | ||
| output logic cache_in_sel | ||
| ); | ||
|
|
||
| enum int unsigned { | ||
| cache_access, | ||
| physical_read, | ||
| physical_write | ||
| } state, next_state; | ||
|
|
||
| always_comb | ||
| begin : state_actions | ||
| mem_resp = 0; | ||
| load_valid = 0; | ||
| load_dirty = 0; | ||
| clear_dirty = 0; | ||
| load_tag = 0; | ||
| load_data = 0; | ||
| load_lru = 0; | ||
| pmem_addr_sel = 0; | ||
| pmem_write = 0; | ||
| pmem_read = 0; | ||
| cache_in_sel = 0; | ||
| case(state) | ||
| cache_access: begin | ||
| if(mem_read && valid && tag_hit) | ||
| begin | ||
| mem_resp = 1; | ||
| load_lru = 1; | ||
| end | ||
| else if(mem_write && valid && tag_hit) | ||
| begin | ||
| mem_resp = 1; | ||
| load_lru = 1; | ||
| load_dirty = 1; | ||
| load_data = 1; | ||
| cache_in_sel = 1; | ||
| end | ||
| end | ||
| physical_read: begin | ||
| if(pmem_resp) | ||
| begin | ||
| load_data = 1; | ||
| load_valid = 1; | ||
| clear_dirty = 1; | ||
| end | ||
| load_tag = 1; | ||
| pmem_read = 1; | ||
| end | ||
| physical_write: begin | ||
| pmem_addr_sel = 1; | ||
| pmem_write = 1; | ||
| end | ||
| endcase | ||
| end | ||
|
|
||
| always_comb | ||
| begin: next_state_logic | ||
| next_state = state; | ||
| case(state) | ||
| cache_access: begin | ||
| if ((valid == 0 || (tag_hit == 0 && dirty == 0)) && (mem_read == 1 || mem_write == 1)) | ||
| next_state = physical_read; | ||
| else if(tag_hit == 0 && dirty == 1 && (mem_read == 1 || mem_write == 1)) | ||
| next_state = physical_write; | ||
| else | ||
| next_state = cache_access; | ||
| end | ||
| physical_read: begin | ||
| if(pmem_resp == 0) | ||
| next_state = physical_read; | ||
| else | ||
| next_state = cache_access; | ||
| end | ||
| physical_write: begin | ||
| if(pmem_resp == 0) | ||
| next_state = physical_write; | ||
| else | ||
| next_state = physical_read; | ||
| end | ||
| default: | ||
| next_state = cache_access; | ||
| endcase | ||
| end | ||
|
|
||
| always_ff @(posedge clk) | ||
| begin : next_state_assignment | ||
| state <= next_state; | ||
| end | ||
|
|
||
| endmodule : cache_control | ||
|
|
||
|
|
| @@ -1,178 +1,181 @@ | ||
| import lc3b_types::*; | ||
|
|
||
| module cache_datapath( | ||
| input clk, | ||
| input load_data, | ||
| input load_valid, | ||
| input load_dirty, | ||
| input load_lru, | ||
| input load_tag, | ||
| input clear_dirty, | ||
| input cache_in_sel, | ||
| input [1:0] mem_byte_enable, | ||
| input lc3b_word mem_address, | ||
| input lc3b_word mem_wdata, | ||
| input pmem_addr_sel, | ||
| input lc3b_burst pmem_rdata, | ||
|
|
||
| output logic tag_hit, | ||
| output logic valid, | ||
| output logic dirty, | ||
| output lc3b_word mem_rdata, | ||
| output lc3b_word pmem_address, | ||
| output lc3b_burst pmem_wdata | ||
| ); | ||
|
|
||
| lc3b_burst cache_out1; | ||
| lc3b_burst cache_out2; | ||
| lc3b_burst cache_out; | ||
| lc3b_burst cache_wdata; | ||
| lc3b_burst cache_mux_out; | ||
| lc3b_tag tag0; | ||
| lc3b_tag tag1; | ||
| logic lru_out; | ||
| logic valid_bit0; | ||
| logic valid_bit1; | ||
| logic dirty_bit0; | ||
| logic dirty_bit1; | ||
| logic tag0_hit; | ||
| logic tag1_hit; | ||
|
|
||
| /* Data Array */ | ||
| dataselect DATA_OUT | ||
| ( | ||
| .sel0(tag0_hit), | ||
| .sel1(tag1_hit), | ||
| .lru(lru_out), | ||
| .data0(cache_out1), | ||
| .data1(cache_out2), | ||
| .out(cache_out) | ||
| ); | ||
| data_array DATA | ||
| ( | ||
| .clk(clk), | ||
| .load(load_data), | ||
| .tag0_hit(tag0_hit), | ||
| .tag1_hit(tag1_hit), | ||
| .lru(lru_out), | ||
| .in(cache_mux_out), | ||
| .set(mem_address[7:4]), | ||
| .cache_out1(cache_out1), | ||
| .cache_out2(cache_out2) | ||
| ); | ||
|
|
||
| wordselect DATASElECT | ||
| ( | ||
| .offset(mem_address[3:0]), | ||
| .data_burst(cache_out), | ||
| .out(mem_rdata) | ||
| ); | ||
|
|
||
| replace_word DATA_REPLACE | ||
| ( | ||
| .in(cache_out), | ||
| .offset(mem_address[3:0]), | ||
| .new_data(mem_wdata), | ||
| .mem_byte_enable(mem_byte_enable), | ||
| .out(cache_wdata) | ||
| ); | ||
|
|
||
| mux2 #(.width(128)) CACHE_IN_MUX | ||
| ( | ||
| .sel(cache_in_sel), | ||
| .a(pmem_rdata), | ||
| .b(cache_wdata), | ||
| .f(cache_mux_out) | ||
| ); | ||
|
|
||
| lru LRU | ||
| ( | ||
| .clk(clk), | ||
| .load(load_lru), | ||
| .tag0_hit(tag0_hit), | ||
| .tag1_hit(tag1_hit), | ||
| .set(mem_address[7:4]), | ||
| .lru_out(lru_out) | ||
| ); | ||
|
|
||
| /* Valid Bit Array */ | ||
| bitselect validselect | ||
| ( | ||
| .sel0(tag0_hit), | ||
| .sel1(tag1_hit), | ||
| .lru(lru_out), | ||
| .data0(valid_bit0), | ||
| .data1(valid_bit1), | ||
| .out(valid) | ||
| ); | ||
| twobitarray VALID_BITS | ||
| ( | ||
| .clk(clk), | ||
| .load(load_valid), | ||
| .clear(1'b0), | ||
| .lru(lru_out), | ||
| .tag0_hit(tag0_hit), | ||
| .tag1_hit(tag1_hit), | ||
| .set(mem_address[7:4]), | ||
| .outbit0(valid_bit0), | ||
| .outbit1(valid_bit1) | ||
| ); | ||
|
|
||
| /* Dirty Bit Array */ | ||
| dirtyselect DIRTY | ||
| ( | ||
| .lru(lru_out), | ||
| .dirty0(dirty_bit0), | ||
| .dirty1(dirty_bit1), | ||
| .dirty(dirty) | ||
| ); | ||
|
|
||
| twobitarray DIRTY_BITS | ||
| ( | ||
| .clk(clk), | ||
| .load(load_dirty), | ||
| .clear(clear_dirty), | ||
| .lru(lru_out), | ||
| .tag0_hit(tag0_hit), | ||
| .tag1_hit(tag1_hit), | ||
| .set(mem_address[7:4]), | ||
| .outbit0(dirty_bit0), | ||
| .outbit1(dirty_bit1) | ||
| ); | ||
|
|
||
| /* Tag Array */ | ||
| tag_comp TAG_COMP | ||
| ( | ||
| .tag(mem_address[15:8]), | ||
| .tag0(tag0), | ||
| .tag1(tag1), | ||
| .tag_hit(tag_hit), | ||
| .tag0_hit(tag0_hit), | ||
| .tag1_hit(tag1_hit) | ||
| ); | ||
|
|
||
| tag_array TAG_ARRAY | ||
| ( | ||
| .clk(clk), | ||
| .load(load_tag), | ||
| .lru(lru_out), | ||
| .tag(mem_address[15:8]), | ||
| .set(mem_address[7:4]), | ||
| .tag_out0(tag0), | ||
| .tag_out1(tag1) | ||
| ); | ||
|
|
||
| addrgen PMEM_GEN | ||
| ( | ||
| .lru(lru_out), | ||
| .pmem_address_sel(pmem_addr_sel), | ||
| .mem_address(mem_address), | ||
| .tag0(tag0), | ||
| .tag1(tag1), | ||
| .set(mem_address[7:4]), | ||
| .addrgen_out(pmem_address) | ||
| ); | ||
|
|
||
| assign pmem_wdata = cache_out; | ||
|
|
||
| endmodule : cache_datapath | ||
|
|
||
|
|
||
|
|
| @@ -0,0 +1,180 @@ | ||
| import lc3b_types::*; | ||
|
|
||
| module cache_datapath_l2( | ||
| input clk, | ||
| input load_data, | ||
| input load_valid, | ||
| input load_dirty, | ||
| input load_lru, | ||
| input load_tag, | ||
| input clear_dirty, | ||
| input cache_in_sel, | ||
| input [1:0] mem_byte_enable, | ||
| input lc3b_word mem_address, | ||
| input lc3b_burst mem_wdata, | ||
| input pmem_addr_sel, | ||
| input lc3b_burst pmem_rdata, | ||
|
|
||
| output logic tag_hit, | ||
| output logic valid, | ||
| output logic dirty, | ||
| output lc3b_burst mem_rdata, | ||
| output lc3b_word pmem_address, | ||
| output lc3b_burst pmem_wdata | ||
| ); | ||
|
|
||
| lc3b_burst cache_out1; | ||
| lc3b_burst cache_out2; | ||
| lc3b_burst cache_out; | ||
| lc3b_burst cache_wdata; | ||
| lc3b_burst cache_mux_out; | ||
| lc3b_tag_l2 tag0; | ||
| lc3b_tag_l2 tag1; | ||
| logic lru_out; | ||
| logic valid_bit0; | ||
| logic valid_bit1; | ||
| logic dirty_bit0; | ||
| logic dirty_bit1; | ||
| logic tag0_hit; | ||
| logic tag1_hit; | ||
|
|
||
| /* Data Array */ | ||
| dataselect_l2 DATA_OUT_l2 | ||
| ( | ||
| .sel0(tag0_hit), | ||
| .sel1(tag1_hit), | ||
| .lru(lru_out), | ||
| .data0(cache_out1), | ||
| .data1(cache_out2), | ||
| .out(cache_out) //this is the correct output with tag checked already | ||
| ); | ||
| data_array_l2 DATA_l2 | ||
| ( | ||
| .clk(clk), | ||
| .load(load_data), | ||
| .tag0_hit(tag0_hit), | ||
| .tag1_hit(tag1_hit), | ||
| .lru(lru_out), | ||
| .in(cache_mux_out), | ||
| .set(mem_address[8:4]), | ||
| .cache_out1(cache_out1), | ||
| .cache_out2(cache_out2) | ||
| ); | ||
|
|
||
| /* | ||
| wordselect_l2 DATASElECT_l2 | ||
| ( | ||
| .offset(mem_address[3:0]), | ||
| .data_burst(cache_out), | ||
| .out(mem_rdata) | ||
| );*/ | ||
| /* | ||
| replace_word_l2 DATA_REPLACE_l2 | ||
| ( | ||
| .in(cache_out), | ||
| .offset(mem_address[3:0]), | ||
| .new_data(mem_wdata), | ||
| .mem_byte_enable(mem_byte_enable), | ||
| .out(cache_wdata) | ||
| );*/ | ||
|
|
||
| mux2 #(.width(128)) CACHE_IN_MUX_l2 | ||
| ( | ||
| .sel(cache_in_sel), | ||
| .a(pmem_rdata), | ||
| .b(mem_wdata), | ||
| .f(cache_mux_out) | ||
| ); | ||
|
|
||
| lru_l2 LRU_l2 | ||
| ( | ||
| .clk(clk), | ||
| .load(load_lru), | ||
| .tag0_hit(tag0_hit), | ||
| .tag1_hit(tag1_hit), | ||
| .set(mem_address[8:4]), | ||
| .lru_out(lru_out) | ||
| ); | ||
|
|
||
| /* Valid Bit Array */ | ||
| bitselect_l2 validselect_l2 | ||
| ( | ||
| .sel0(tag0_hit), | ||
| .sel1(tag1_hit), | ||
| .lru(lru_out), | ||
| .data0(valid_bit0), | ||
| .data1(valid_bit1), | ||
| .out(valid) | ||
| ); | ||
| twobitarray_l2 VALID_BITS_l2 | ||
| ( | ||
| .clk(clk), | ||
| .load(load_valid), | ||
| .clear(1'b0), | ||
| .lru(lru_out), | ||
| .tag0_hit(tag0_hit), | ||
| .tag1_hit(tag1_hit), | ||
| .set(mem_address[8:4]), | ||
| .outbit0(valid_bit0), | ||
| .outbit1(valid_bit1) | ||
| ); | ||
|
|
||
| /* Dirty Bit Array */ | ||
| dirtyselect_l2 DIRTY_l2 | ||
| ( | ||
| .lru(lru_out), | ||
| .dirty0(dirty_bit0), | ||
| .dirty1(dirty_bit1), | ||
| .dirty(dirty) | ||
| ); | ||
|
|
||
| twobitarray_l2 DIRTY_BITS_l2 | ||
| ( | ||
| .clk(clk), | ||
| .load(load_dirty), | ||
| .clear(clear_dirty), | ||
| .lru(lru_out), | ||
| .tag0_hit(tag0_hit), | ||
| .tag1_hit(tag1_hit), | ||
| .set(mem_address[8:4]), | ||
| .outbit0(dirty_bit0), | ||
| .outbit1(dirty_bit1) | ||
| ); | ||
|
|
||
| /* Tag Array */ | ||
| tag_comp_l2 TAG_COMP_l2 | ||
| ( | ||
| .tag(mem_address[15:9]), | ||
| .tag0(tag0), | ||
| .tag1(tag1), | ||
| .tag_hit(tag_hit), | ||
| .tag0_hit(tag0_hit), | ||
| .tag1_hit(tag1_hit) | ||
| ); | ||
|
|
||
| tag_array_l2 TAG_ARRAY_l2 | ||
| ( | ||
| .clk(clk), | ||
| .load(load_tag), | ||
| .lru(lru_out), | ||
| .tag(mem_address[15:9]), | ||
| .set(mem_address[8:4]), | ||
| .tag_out0(tag0), | ||
| .tag_out1(tag1) | ||
| ); | ||
|
|
||
| addrgen_l2 PMEM_GEN_l2 | ||
| ( | ||
| .lru(lru_out), | ||
| .pmem_address_sel(pmem_addr_sel), | ||
| .mem_address(mem_address), | ||
| .tag0(tag0), | ||
| .tag1(tag1), | ||
| .set(mem_address[8:4]), | ||
| .addrgen_out(pmem_address) | ||
| ); | ||
|
|
||
| assign pmem_wdata = cache_out; | ||
| assign mem_rdata = cache_out; | ||
|
|
||
| endmodule : cache_datapath_l2 |
| @@ -1,86 +1,87 @@ | ||
| import lc3b_types::*; | ||
|
|
||
| module cache_module | ||
| ( | ||
| input clk, | ||
|
|
||
| //Signals from CPU | ||
| input mem_read, | ||
| input mem_write, | ||
| input lc3b_word mem_address, | ||
| input lc3b_word mem_wdata, | ||
| input [1:0] mem_byte_enable, | ||
|
|
||
| //Signals from Memory | ||
| input pmem_resp, | ||
| input lc3b_burst pmem_rdata, | ||
|
|
||
| //Signals to CPU | ||
| output mem_resp, | ||
| output lc3b_word mem_rdata, | ||
|
|
||
| //Signals to Memory | ||
| output pmem_read, | ||
| output pmem_write, | ||
| output lc3b_word pmem_address, | ||
| output lc3b_burst pmem_wdata | ||
| ); | ||
|
|
||
| logic load_data; | ||
| logic load_valid; | ||
| logic load_dirty; | ||
| logic clear_dirty; | ||
| logic load_lru; | ||
| logic load_tag; | ||
| logic cache_in_sel; | ||
| logic tag_hit; | ||
| logic dirty; | ||
| logic valid; | ||
| logic pmem_addr_sel; | ||
|
|
||
| cache_datapath CACHE_DATAPATH | ||
| ( | ||
| .clk(clk), | ||
| .load_data(load_data), | ||
| .load_valid(load_valid), | ||
| .load_dirty(load_dirty), | ||
| .clear_dirty(clear_dirty), | ||
| .load_lru(load_lru), | ||
| .load_tag(load_tag), | ||
| .cache_in_sel(cache_in_sel), | ||
| .mem_byte_enable(mem_byte_enable), | ||
| .mem_address(mem_address), | ||
| .mem_wdata(mem_wdata), | ||
| .pmem_rdata(pmem_rdata), | ||
| .tag_hit(tag_hit), | ||
| .valid(valid), | ||
| .dirty(dirty), | ||
| .mem_rdata(mem_rdata), | ||
| .pmem_address(pmem_address), | ||
| .pmem_addr_sel(pmem_addr_sel), | ||
| .pmem_wdata(pmem_wdata) | ||
| ); | ||
|
|
||
| cache_control CACHE_CONTROLLER | ||
| ( | ||
| .clk(clk), | ||
| .mem_write(mem_write), | ||
| .mem_read(mem_read), | ||
| .pmem_resp(pmem_resp), | ||
| .tag_hit(tag_hit), | ||
| .dirty(dirty), | ||
| .valid(valid), | ||
| .cache_in_sel(cache_in_sel), | ||
| .mem_resp(mem_resp), | ||
| .load_valid(load_valid), | ||
| .load_dirty(load_dirty), | ||
| .clear_dirty(clear_dirty), | ||
| .load_tag(load_tag), | ||
| .load_data(load_data), | ||
| .load_lru(load_lru), | ||
| .pmem_addr_sel(pmem_addr_sel), | ||
| .pmem_write(pmem_write), | ||
| .pmem_read(pmem_read) | ||
| ); | ||
|
|
||
|
|
||
| endmodule : cache_module |
| @@ -0,0 +1,86 @@ | ||
| import lc3b_types::*; | ||
|
|
||
| module cache_module_l2 | ||
| ( | ||
| input clk, | ||
|
|
||
| //Signals from CPU | ||
| input mem_read, | ||
| input mem_write, | ||
| input lc3b_word mem_address, | ||
| input lc3b_burst mem_wdata, | ||
| input [1:0] mem_byte_enable, | ||
|
|
||
| //Signals from Memory | ||
| input pmem_resp, | ||
| input lc3b_burst pmem_rdata, | ||
|
|
||
| //Signals to CPU | ||
| output mem_resp, | ||
| output lc3b_burst mem_rdata, | ||
|
|
||
| //Signals to Memory | ||
| output pmem_read, | ||
| output pmem_write, | ||
| output lc3b_word pmem_address, | ||
| output lc3b_burst pmem_wdata | ||
| ); | ||
|
|
||
| logic load_data; | ||
| logic load_valid; | ||
| logic load_dirty; | ||
| logic clear_dirty; | ||
| logic load_lru; | ||
| logic load_tag; | ||
| logic cache_in_sel; | ||
| logic tag_hit; | ||
| logic dirty; | ||
| logic valid; | ||
| logic pmem_addr_sel; | ||
|
|
||
| cache_datapath_l2 CACHE_DATAPATH_l2 | ||
| ( | ||
| .clk(clk), | ||
| .load_data(load_data), | ||
| .load_valid(load_valid), | ||
| .load_dirty(load_dirty), | ||
| .clear_dirty(clear_dirty), | ||
| .load_lru(load_lru), | ||
| .load_tag(load_tag), | ||
| .cache_in_sel(cache_in_sel), | ||
| .mem_byte_enable(mem_byte_enable), | ||
| .mem_address(mem_address), | ||
| .mem_wdata(mem_wdata), | ||
| .pmem_rdata(pmem_rdata), | ||
| .tag_hit(tag_hit), | ||
| .valid(valid), | ||
| .dirty(dirty), | ||
| .mem_rdata(mem_rdata), | ||
| .pmem_address(pmem_address), | ||
| .pmem_addr_sel(pmem_addr_sel), | ||
| .pmem_wdata(pmem_wdata) | ||
| ); | ||
|
|
||
| cache_control CACHE_CONTROLLER_l2 | ||
| ( | ||
| .clk(clk), | ||
| .mem_write(mem_write), | ||
| .mem_read(mem_read), | ||
| .pmem_resp(pmem_resp), | ||
| .tag_hit(tag_hit), | ||
| .dirty(dirty), | ||
| .valid(valid), | ||
| .cache_in_sel(cache_in_sel), | ||
| .mem_resp(mem_resp), | ||
| .load_valid(load_valid), | ||
| .load_dirty(load_dirty), | ||
| .clear_dirty(clear_dirty), | ||
| .load_tag(load_tag), | ||
| .load_data(load_data), | ||
| .load_lru(load_lru), | ||
| .pmem_addr_sel(pmem_addr_sel), | ||
| .pmem_write(pmem_write), | ||
| .pmem_read(pmem_read) | ||
| ); | ||
|
|
||
| endmodule : cache_module_l2 |
| @@ -10,7 +10,7 @@ module cccomp | ||
|
|
||
| always_comb | ||
| begin | ||
| if ((opcode == op_br && (cc[0] && nzp[0] || cc[1] && nzp[1] || cc[2] && nzp[2]|| nzp == 3'b111))) | ||
| branch_enable = 1; | ||
| else | ||
| branch_enable = 0; | ||
| @@ -1,55 +1,59 @@ | ||
| import lc3b_types::*; | ||
| module data_array | ||
| ( | ||
| input clk, | ||
| input load, | ||
| input lru, | ||
| input tag0_hit, | ||
| input tag1_hit, | ||
| input lc3b_burst in, | ||
| input lc3b_set set, | ||
| output lc3b_burst cache_out1, | ||
| output lc3b_burst cache_out2 | ||
| ); | ||
|
|
||
| /* cache size increased for L1 into 16 sets*/ | ||
| lc3b_burst way0 [15:0] /* synthesis ramstyle = "logic" */; | ||
| lc3b_burst way1 [15:0] /* synthesis ramstyle = "logic" */; | ||
|
|
||
| initial | ||
| begin | ||
| for (int i = 0; i < $size(way0); i++) | ||
| begin | ||
| way0[i] = 128'b0; | ||
| way1[i] = 128'b0; | ||
| end | ||
| end | ||
|
|
||
| always_ff @ (posedge clk) | ||
| begin | ||
| if(load == 1) | ||
| begin | ||
| if(tag0_hit) | ||
| way0[set] = in; | ||
| else if(tag1_hit) | ||
| way1[set] = in; | ||
| else | ||
| begin | ||
| case(lru) | ||
| 1'b0: begin | ||
| way0[set] = in; | ||
| end | ||
| 1'b1: begin | ||
| way1[set] = in; | ||
| end | ||
| endcase | ||
| end | ||
| end | ||
| end | ||
|
|
||
| always_comb | ||
| begin | ||
| cache_out1 = way0[set]; | ||
| cache_out2 = way1[set]; | ||
| end | ||
|
|
||
|
|
||
| endmodule : data_array | ||
|
|
||
|
|
| @@ -0,0 +1,56 @@ | ||
| import lc3b_types::*; | ||
| module data_array_l2 | ||
| ( | ||
| input clk, | ||
| input load, | ||
| input lru, | ||
| input tag0_hit, | ||
| input tag1_hit, | ||
| input lc3b_burst in, | ||
| input lc3b_set_l2 set, | ||
| output lc3b_burst cache_out1, | ||
| output lc3b_burst cache_out2 | ||
| ); | ||
|
|
||
| /* L2 cache contains total of 32 sets */ | ||
| lc3b_burst way0 [31:0] /* synthesis ramstyle = "logic" */; | ||
| lc3b_burst way1 [31:0] /* synthesis ramstyle = "logic" */; | ||
|
|
||
| initial | ||
| begin | ||
| for (int i = 0; i < $size(way0); i++) | ||
| begin | ||
| way0[i] = 128'b0; | ||
| way1[i] = 128'b0; | ||
| end | ||
| end | ||
|
|
||
| always_ff @ (posedge clk) | ||
| begin | ||
| if(load == 1) | ||
| begin | ||
| if(tag0_hit) | ||
| way0[set] = in; | ||
| else if(tag1_hit) | ||
| way1[set] = in; | ||
| else | ||
| begin | ||
| case(lru) | ||
| 1'b0: begin | ||
| way0[set] = in; | ||
| end | ||
| 1'b1: begin | ||
| way1[set] = in; | ||
| end | ||
| endcase | ||
| end | ||
| end | ||
| end | ||
|
|
||
| always_comb | ||
| begin | ||
| cache_out1 = way0[set]; | ||
| cache_out2 = way1[set]; | ||
| end | ||
|
|
||
| endmodule : data_array_l2 |
| @@ -0,0 +1,28 @@ | ||
| import lc3b_types::*; | ||
| module dataselect_l2 | ||
| ( | ||
| input sel0, | ||
| input sel1, | ||
| input lru, | ||
| input lc3b_burst data0, | ||
| input lc3b_burst data1, | ||
| output lc3b_burst out | ||
| ); | ||
|
|
||
| always_comb | ||
| begin | ||
| out = 128'b0; | ||
| if(sel0 == 1) | ||
| out = data0; | ||
| else if (sel1 == 1) | ||
| out = data1; | ||
| else | ||
| case(lru) | ||
| 1'b0: | ||
| out = data0; | ||
| 1'b1: | ||
| out = data1; | ||
| endcase | ||
| end | ||
|
|
||
| endmodule : dataselect_l2 |
| @@ -0,0 +1,19 @@ | ||
| module dirtyselect_l2( | ||
| input dirty0, | ||
| input dirty1, | ||
| input lru, | ||
| output logic dirty | ||
| ); | ||
|
|
||
| always_comb | ||
| begin | ||
| dirty = 0; | ||
| case(lru) | ||
| 1'b0: | ||
| dirty = dirty0; | ||
| 1'b1: | ||
| dirty = dirty1; | ||
| endcase | ||
| end | ||
|
|
||
| endmodule : dirtyselect_l2 |
| @@ -0,0 +1,167 @@ | ||
| import lc3b_types::*; | ||
|
|
||
| module forwarding_selector | ||
| ( | ||
| input lc3b_word mem_rdata, | ||
| input lc3b_word mem_alu_data, | ||
| input lc3b_word mem_addrgen, | ||
| //input logic [3:0] op_mem, | ||
| input lc3b_word wb_data, | ||
| input lc3b_ipacket mem_packet, | ||
| input lc3b_ipacket wb_packet, | ||
|
|
||
| output lc3b_word mem_out, | ||
| output lc3b_word wb_out | ||
| ); | ||
|
|
||
| always_comb | ||
| begin | ||
| //memory operation. Loaded with bbbb for debuging purposes | ||
| case (mem_packet.opcode) | ||
|
|
||
| op_add : begin | ||
| mem_out = mem_alu_data; | ||
| end | ||
|
|
||
| op_and : begin | ||
| mem_out = mem_alu_data; | ||
| end | ||
|
|
||
| op_br : begin | ||
| mem_out = 16'hbbbb; | ||
| end | ||
|
|
||
| op_jmp : begin | ||
| mem_out = 16'hbbbb; | ||
| end | ||
|
|
||
| op_jsr : begin | ||
| mem_out = mem_packet.pc; | ||
| end | ||
|
|
||
| op_ldb : begin | ||
| mem_out = mem_rdata; | ||
| end | ||
|
|
||
| op_ldi : begin | ||
| mem_out = mem_rdata; | ||
| end | ||
|
|
||
| op_ldr : begin | ||
| mem_out = mem_rdata; | ||
| end | ||
|
|
||
| op_lea : begin | ||
| mem_out = mem_addrgen; | ||
| end | ||
|
|
||
| op_not : begin | ||
| mem_out = mem_alu_data; | ||
| end | ||
|
|
||
| op_rti : begin | ||
| mem_out = 16'hbbbb; | ||
| end | ||
|
|
||
| op_shf : begin | ||
| mem_out = mem_alu_data; | ||
| end | ||
|
|
||
| op_stb : begin | ||
| mem_out = mem_rdata; | ||
| end | ||
|
|
||
| op_sti : begin | ||
| mem_out = mem_rdata; | ||
| end | ||
|
|
||
| op_str : begin | ||
| mem_out = mem_rdata; | ||
| end | ||
|
|
||
| op_trap : begin | ||
| mem_out = mem_packet.pc; | ||
| end | ||
|
|
||
| default : begin | ||
| mem_out = 16'hbbbb; | ||
| end | ||
| endcase; | ||
|
|
||
| //wb operation. Loaded with bbbb for debuging purposes | ||
| case (wb_packet.opcode) | ||
|
|
||
| op_add : begin | ||
| wb_out = wb_data; | ||
| end | ||
|
|
||
| op_and : begin | ||
| wb_out = wb_data; | ||
| end | ||
|
|
||
| op_br : begin | ||
| wb_out = wb_data; | ||
| end | ||
|
|
||
| op_jmp : begin | ||
| wb_out = wb_data; | ||
| end | ||
|
|
||
| op_jsr : begin | ||
| wb_out = wb_packet.pc; | ||
| end | ||
|
|
||
| op_ldb : begin | ||
| wb_out = wb_data; | ||
| end | ||
|
|
||
| op_ldi : begin | ||
| wb_out = wb_data; | ||
| end | ||
|
|
||
| op_ldr : begin | ||
| wb_out = wb_data; | ||
| end | ||
|
|
||
| op_lea : begin | ||
| wb_out = wb_data; | ||
| end | ||
|
|
||
| op_not : begin | ||
| wb_out = wb_data; | ||
| end | ||
|
|
||
| op_rti : begin | ||
| wb_out = wb_data; | ||
| end | ||
|
|
||
| op_shf : begin | ||
| wb_out = wb_data; | ||
| end | ||
|
|
||
| op_stb : begin | ||
| wb_out = wb_data; | ||
| end | ||
|
|
||
| op_sti : begin | ||
| wb_out = wb_data; | ||
| end | ||
|
|
||
| op_str : begin | ||
| wb_out = wb_data; | ||
| end | ||
|
|
||
| op_trap : begin | ||
| wb_out = wb_packet.pc; | ||
| end | ||
|
|
||
| default : begin | ||
| wb_out = wb_data; | ||
| end | ||
| endcase; | ||
|
|
||
| end | ||
|
|
||
|
|
||
| endmodule: forwarding_selector | ||
|
|
| @@ -0,0 +1,39 @@ | ||
| import lc3b_types::*; | ||
| module lru_l2 | ||
| ( | ||
| input clk, | ||
| input load, | ||
| input tag0_hit, | ||
| input tag1_hit, | ||
| input lc3b_set_l2 set, | ||
| output logic lru_out | ||
| ); | ||
|
|
||
| /* L2 cache LRU contains total of 32 sets */ | ||
| logic lru_bits[31:0]; | ||
|
|
||
| initial | ||
| begin | ||
| for(int i = 0; i < $size(lru_bits); i++) | ||
| begin | ||
| lru_bits[i] = 0; | ||
| end | ||
| end | ||
|
|
||
| always_ff @ (posedge clk) | ||
| begin | ||
| if(load == 1) | ||
| begin | ||
| if(tag0_hit) | ||
| lru_bits[set] = 1; | ||
| else if (tag1_hit) | ||
| lru_bits[set] = 0; | ||
| end | ||
| end | ||
|
|
||
| always_comb | ||
| begin | ||
| lru_out = lru_bits[set]; | ||
| end | ||
|
|
||
| endmodule : lru_l2 |
| @@ -0,0 +1,43 @@ | ||
| import lc3b_types::*; | ||
|
|
||
| module operand_selector | ||
| ( | ||
| input logic [1:0] curr_case, | ||
| input mem_in, | ||
| input wb_in, | ||
|
|
||
| output lc3b_word opA, | ||
| output lc3b_word opB | ||
| ); | ||
|
|
||
| /* Logic about routing the mem data and the wb data. Case comes from hazard detection*/ | ||
| always_comb | ||
| begin | ||
|
|
||
| case (curr_case) | ||
|
|
||
| 2'b00 : begin | ||
| opA = mem_in; | ||
| opB = mem_in; | ||
| end | ||
|
|
||
| 2'b01 : begin | ||
| opA = mem_in; | ||
| opB = wb_in; | ||
| end | ||
|
|
||
| 2'b10 : begin | ||
| opA = wb_in; | ||
| opB = mem_in; | ||
| end | ||
|
|
||
| 2'b11 : begin | ||
| opA = wb_in; | ||
| opB = wb_in; | ||
| end | ||
|
|
||
| endcase | ||
|
|
||
| end | ||
|
|
||
| endmodule: operand_selector |