223 DGM_tb.sv
@@ -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;

/* internal signals */
/*lc3b_word if_memaddr, if_mem_rdata, mem_memaddr, mem_mem_rdata, mem_mem_wdata;
logic [1:0] if_mem_byte_enable, mem_mem_byte_enable;
logic if_mem_resp, if_memread, mem_mem_resp, mem_memread, mem_memwrite;
*/

/*
logic IF_read, IF_write, MEM_read, MEM_write, l2i_resp, l2d_resp;
lc3b_word IF_address, MEM_address;
lc3b_burst l2i_rdata,IF_wdata, l2d_rdata, MEM_wdata ;
*/


DGM top(

.clk(clk),
.l2_resp(resp),
.l2_rdata(rdata),
.l2_address(address),
.l2_read(read),
.l2_write(write),
.l2_wdata(wdata)

);

/*
DGM top(
.clk(clk),
.l2i_resp(l2i_resp),
.l2i_rdata(l2i_rdata),
.IF_address(IF_address),
.IF_wdata(IF_wdata),
.IF_read(IF_read),
.IF_write(IF_write),
.l2d_resp(l2d_resp),
.l2d_rdata(l2d_rdata),
.MEM_address(MEM_address),
.MEM_wdata(MEM_wdata),
.MEM_read(MEM_read),
.MEM_write(MEM_write)
);
*/

/*
physical_memory IF_mem(
.clk(clk),
.read(IF_read),
.write(IF_write),
.address(IF_address),
.wdata(IF_wdata),
.resp(l2i_resp),
.rdata(l2i_rdata)
);
physical_memory MEM_mem(
.clk(clk),
.read(MEM_read),
.write(MEM_write),
.address(MEM_address),
.wdata(MEM_wdata),
.resp(l2d_resp),
.rdata(l2d_rdata)
);
*/


/*
magic_memory_dp memory
(
.clk(clk),
// Port A
.read_a(a_mem_read),
.write_a(a_mem_write),
.wmask_a(a_mem_byte_enable),
.address_a(a_mem_address),
.wdata_a(a_mem_wdata),
.resp_a(a_mem_resp),
.rdata_a(a_mem_rdata),
// Port B
.read_b(b_mem_read),
.write_b(b_mem_write),
.wmask_b(b_mem_byte_enable),
.address_b(b_mem_address),
.wdata_b(b_mem_wdata),
.resp_b(b_mem_resp),
.rdata_b(b_mem_rdata)
);*/

physical_memory the_memory(
.clk(clk),
.read(read),
.write(write),
.address(address),
.wdata(wdata),
.resp(resp),
.rdata(rdata)
);

endmodule : DGM_tb
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


3 LRU.sv
@@ -9,7 +9,8 @@ module lru
output logic lru_out
);

logic lru_bits[7:0];
/* lru bits changed to 16 bits for increasing cache size */
logic lru_bits[15:0];

initial
begin
16 WB.sv
@@ -6,6 +6,7 @@ module WB(
input lc3b_word mem_in, alu_in,
input lc3b_word br_addr,
input lc3b_ipacket ipacket,
input logic stall,

/* data output */
output lc3b_word br_addr_out,
@@ -15,10 +16,11 @@ module WB(
output logic[1:0] pcmux_sel,
output lc3b_word wbdata,
output logic regfile_mux_sel,
output logic load_regfile,

//somthing new added here
output logic br_sig,

output logic load_regfile,

//somthing new added here
output logic br_sig,

output logic pip_flush
);
@@ -33,8 +35,9 @@ assign br_addr_out = br_addr;
assign wbpc = ipacket.pc;
assign wbdr = ipacket.dr_sr;
assign wbdrmux_sel = ipacket.drmux_sel;

assign br_sig = br_taken;


assign br_sig = br_taken;

/* GenCC module */
gencc genccmodule(
@@ -71,6 +74,7 @@ cccomp cccomp_module
flush_gen pipe_flush(
.opcode(ipacket.opcode),
.branch_enable(br_taken),
.stall(stall),
.flush(pip_flush)
);

@@ -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
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
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









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

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
241 cache.sv
@@ -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
























/**
* 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 @@
import lc3b_types::*;

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)
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
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[6: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[6: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[6: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[6:4]),
.outbit0(dirty_bit0),
.outbit1(dirty_bit1)
);

/* Tag Array */
tag_comp TAG_COMP
(
.tag(mem_address[15:7]),
.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:7]),
.set(mem_address[6: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[6:4]),
.addrgen_out(pmem_address)
);

assign pmem_wdata = cache_out;

endmodule : cache_datapath
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)
);

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)
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
);

lc3b_burst way0 [7:0] /* synthesis ramstyle = "logic" */;
lc3b_burst way1 [7: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
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
@@ -6,13 +6,19 @@ module exe_stage
input lc3b_word SEXT,
input lc3b_word sr1,
input lc3b_word sr2,
input logic [1:0] opAmux_sel,
input logic [1:0] opBmux_sel,
input logic [1:0] opSrmux_sel,
input lc3b_word mem_data_forward,
input lc3b_word wb_data_forward,

output lc3b_word alu_out,
output lc3b_word bradd_out,
output lc3b_word sr_store
);

lc3b_word alumux_out, braddmux_out;
lc3b_word opA,opB;

/* BR Add Mux */
mux4 braddmux
@@ -39,8 +45,8 @@ adder bradd
alu alu
(
.aluop(ipacket.aluop),
.a(sr1),
.b(alumux_out),
.a(opA),
.b(opB),

.f(alu_out)
);
@@ -55,6 +61,40 @@ mux2 #(.width(16)) alumux
.f(alumux_out)
);

assign sr_store = sr2;
/* opA mux */
mux4 #(.width(16)) opAmux
(
.sel(opAmux_sel),
.a(sr1),
.b(mem_data_forward),
.c(wb_data_forward),
.d(16'b0),

.f(opA)
);

/* opB mux */
mux4 #(.width(16)) opBmux
(
.sel(opBmux_sel),
.a(alumux_out),
.b(mem_data_forward),
.c(wb_data_forward),
.d(16'b0),

.f(opB)
);

/* SR forwarding */
mux4 #(.width(16)) opSrmux
(
.sel(opSrmux_sel),
.a(sr2),
.b(mem_data_forward),
.c(wb_data_forward),
.d(16'b0),

.f(sr_store)
);

endmodule : exe_stage
@@ -3,29 +3,33 @@ import lc3b_types::*;
module flush_gen(
input [3:0] opcode,
input branch_enable,
input stall,

output logic flush
);

always_comb
begin
flush = 0;
case(opcode)
op_br :
begin
if(branch_enable)
if(~stall)
begin
case(opcode)
op_br :
begin
flush = 1;
if(branch_enable)
begin
flush = 1;
end
end
end
op_jmp :
flush = 1;
op_jsr :
flush = 1;
op_trap :
flush = 1;
default : ;
endcase
op_jmp :
flush = 1;
op_jsr :
flush = 1;
op_trap :
flush = 1;
default : ;
endcase
end
end

endmodule : flush_gen
@@ -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

@@ -1,3 +1,5 @@
import lc3b_types::*;

module hazard_detection
(
/* If signals */
@@ -14,11 +16,30 @@ module hazard_detection

/*Sti Ldi*/
input sti_ldi_sig,

/*Packets for hazard detection*/
input lc3b_ipacket exe_packet,
input lc3b_ipacket mem_packet,
input lc3b_ipacket wb_packet,

/* Stall Signals */
output logic pc_stall,
output logic if_id_stall,
output logic id_ie_stall,
output logic ie_mem_stall,
output logic mem_wb_stall
output logic mem_wb_stall,

/* bubble signals */
output logic if_id_bubble,
output logic id_ie_bubble,
output logic ie_mem_bubble,
output logic mem_wb_bubble,

/* Forwarding signals*/
output logic [1:0] opAmux_sel,
output logic [1:0] opBmux_sel,
output logic [1:0] opSrmux_sel

);

always_comb
@@ -29,20 +50,22 @@ begin
id_ie_stall = 1'b0;
ie_mem_stall = 1'b0;
mem_wb_stall = 1'b0;
if_id_bubble = 1'b0;
id_ie_bubble = 1'b0;
ie_mem_bubble = 1'b0;
mem_wb_bubble = 1'b0;

/*TODO If statements like this may be to slow*/

/* Instruction Cache Miss */
if(if_mem_resp == 1'b0 && if_memread)
if(if_mem_resp == 1'b0 && if_memread && br_taken == 1'b0)
begin
pc_stall = 1'b1;
if_id_stall = 1'b1;
id_ie_stall = 1'b1;
ie_mem_stall = 1'b1;
mem_wb_stall = 1'b1;
//bubble = 1'b1;
end

/* Data Cache Miss */
if(mem_mem_resp == 1'b0 && (mem_memwrite || mem_memread))
begin
@@ -64,5 +87,85 @@ begin

end

/* Case selecting logic*/
always_comb
begin
opAmux_sel = 2'b0;
opBmux_sel = 2'b0;
opSrmux_sel = 2'b0;


/* opA logic */
//tests if the operation in exe stage might need operands to be forwarded to opA
if (exe_packet.opA == 1'b1 )
begin

//tests if there is a dependency in the mem stage. That data is the most recent that can be forwarded
if( (exe_packet.sr1 == mem_packet.dr_sr) && (mem_packet.forward == 1'b1) )
begin
opAmux_sel = 2'b01;
end
//tests to see if the dependency is in the wb stage.
else if ((exe_packet.sr1 == wb_packet.dr_sr) && (wb_packet.forward == 1'b1) )
begin
opAmux_sel = 2'b10;
end

//do not forward
else
begin
opAmux_sel = 2'b00;
end
end

/* opB logic */
//tests if the operation in exe stage might need operands to be forwarded
if (exe_packet.opB == 1'b1 )
begin

//tests if there is a dependency in the mem stage. That data is the most recent that can be forwarded
if( (exe_packet.sr2 == mem_packet.dr_sr) && (mem_packet.forward == 1'b1) )
begin
opBmux_sel = 2'b01;
end
//tests to see if the dependency is in the wb stage.
else if ( (exe_packet.sr2 == wb_packet.dr_sr) && (wb_packet.forward == 1'b1) )
begin
opBmux_sel = 2'b10;
end

//do not forward
else
begin
opBmux_sel = 2'b00;
end
end


/* Sr store logic*/
//tests if the operation is a store
if (exe_packet.mem_write == 1'b1 )
begin

//tests if there is a dependency in the mem stage. That data is the most recent that can be forwarded
if( (exe_packet.dr_sr == mem_packet.dr_sr) && (mem_packet.forward == 1'b1) )
begin
opSrmux_sel = 2'b01;
end
//tests to see if the dependency is in the wb stage.
else if ( (exe_packet.dr_sr == wb_packet.dr_sr) && (wb_packet.forward == 1'b1) )
begin
opSrmux_sel = 2'b10;
end

//do not forward
else
begin
opSrmux_sel = 2'b00;
end
end

end


endmodule : hazard_detection
@@ -65,6 +65,7 @@ begin
end

/* Logic to reload address for LDI/STI */
//else if(dmem_resp) before merge
else if(dmem_resp && hold_reg == 1'b1 && (ipacket.opcode == op_ldi || ipacket.opcode == op_sti))
begin
alu_reg = meat_mem_rdata;
@@ -21,6 +21,11 @@ begin
ipacket.sr2 = inst[2:0];
ipacket.nzp = inst[11:9];

/* Forwarding */
ipacket.forward = 0;
ipacket.opA = 0;
ipacket.opB = 0;

/* IF */

/* ID */
@@ -55,6 +60,12 @@ begin
ipacket.load_cc = 1'b1;
ipacket.cc_mux_sel = 2'b0;
ipacket.load_regfile = 1'b1;
ipacket.forward = 1'b1;
ipacket.opA = 1'b1;
if(inst[5] == 1'b0)
begin
ipacket.opB = 1'b1;
end
end

op_and : begin
@@ -63,10 +74,18 @@ begin
ipacket.load_cc = 1'b1;
ipacket.cc_mux_sel = 2'b0;
ipacket.load_regfile = 1'b1;
ipacket.forward = 1'b1;
ipacket.opA = 1'b1;
if(inst[5] == 1'b0)
begin
ipacket.opB = 1'b1;
end

end

op_jmp : begin
ipacket.pcmux_sel = 2'b01;
ipacket.opA = 1'b1;
end

op_jsr : begin
@@ -75,6 +94,8 @@ begin
ipacket.regfile_mux_sel = 1'b1;
ipacket.cc_mux_sel = 2'b0;
ipacket.pcmux_sel = 2'b01;
ipacket.opA = 1'b1;
ipacket.forward = 1'b1;

if(inst[11])
begin
@@ -91,6 +112,8 @@ begin
ipacket.cc_mux_sel = 2'b01;
ipacket.aluop = alu_add;
ipacket.mem_read = 1'b1;
ipacket.forward = 1'b1;
ipacket.opA = 1'b1;
end

op_ldi : begin
@@ -100,6 +123,8 @@ begin
ipacket.cc_mux_sel = 2'b01;
ipacket.aluop = alu_add;
ipacket.mem_read = 1'b1;
ipacket.forward = 1'b1;
ipacket.opA = 1'b1;
end

op_ldr : begin
@@ -109,28 +134,34 @@ begin
ipacket.cc_mux_sel = 2'b01;
ipacket.aluop = alu_add;
ipacket.mem_read = 1'b1;

ipacket.forward = 1'b1;
ipacket.opA = 1'b1;
end

op_lea : begin
ipacket.load_regfile = 1'b1;
ipacket.wdatamux_sel = 1'b1;
ipacket.cc_mux_sel = 2'b10;
ipacket.load_cc = 1'b1;
ipacket.forward = 1'b1;
end

op_not : begin
ipacket.aluop = alu_not;
ipacket.load_cc = 1'b1;
ipacket.cc_mux_sel = 2'b0;
ipacket.load_regfile = 1'b1;
ipacket.forward = 1'b1;
ipacket.opA = 1'b1;
end

op_shf : begin
ipacket.load_cc = 1'b1;
ipacket.load_regfile = 1'b1;
ipacket.cc_mux_sel = 2'b0;
ipacket.alumux_sel = 1'b1;
ipacket.forward = 1'b1;
ipacket.opA = 1'b1;
case(inst[5:4])
2'b00 :
ipacket.aluop = alu_sll;
@@ -150,14 +181,16 @@ begin
ipacket.mem_write = 1'b1;
ipacket.datamux_sel = 1'b1;
ipacket.sr2_mux_sel = 1'b1;
end
ipacket.opA = 1'b1;

end
op_sti : begin
ipacket.alumux_sel = 1'b1;
ipacket.aluop = alu_add;
ipacket.mem_write = 1'b1;
ipacket.datamux_sel = 1'b1;
ipacket.sr2_mux_sel = 1'b1;
ipacket.sr2_mux_sel = 1'b1;
ipacket.opA = 1'b1;
end

op_str:begin
@@ -166,6 +199,7 @@ begin
ipacket.mem_write=1'b1;
ipacket.datamux_sel = 1'b1;
ipacket.sr2_mux_sel = 1'b1;
ipacket.opA = 1'b1;
end

op_trap : begin
@@ -177,6 +211,8 @@ begin
ipacket.pcmux_sel = 2'b01;
ipacket.mem_read = 1'b1;
ipacket.drmux_sel = 1'b1;
ipacket.dr_sr = 3'b111;
ipacket.forward = 1'b1;
end

default: begin
@@ -12,10 +12,12 @@ typedef logic [7:0] lc3b_vect8;

//types for cache
typedef logic [127:0]lc3b_burst;
typedef logic [8:0] lc3b_tag;
typedef logic [7:0] lc3b_tag; //change the tag bit into 8 bits to increment the cache size
typedef logic [6:0] lc3b_tag_l2; //the level 2 cache tag only have 7 bits

typedef logic [3:0] lc3b_cache_offset;
typedef logic [2:0] lc3b_set;
typedef logic [3:0] lc3b_set; //change the set bit into 4 bits to cover total of 16 sets in the cache
typedef logic [4:0] lc3b_set_l2; //total of 5 bits to cover 32 sets in l2 cache
typedef logic [2:0] lc3b_reg;
typedef logic [2:0] lc3b_nzp;
typedef logic [1:0] lc3b_mem_wmask;
@@ -59,6 +61,11 @@ typedef struct packed {
lc3b_reg sr2;
lc3b_nzp nzp;

/* Hazard detection */
logic forward; //the instruction has a register that it is going to update
logic opA; //The instruction has an data in sr1 that could have data forwarded to it
logic opB; //The instruction has an data in sr1 that could have data forwarded to it

/* IF */

/* ID */
@@ -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
@@ -32,7 +32,14 @@ end
/* Store data from MEM Stage */
always_ff @(posedge clk)
begin
if(~stall) //case not stalling
if(flush)
begin
address = 16'h0;
memdata = 16'h0;
aludata = 16'h0;
packet = 1'b0;
end
else if(~stall) //case not stalling
begin
address = br_address;
memdata = mem_data;
@@ -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