Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,20 @@ test_%:
MODULE=test.test_$* vvp -M $$(cocotb-config --prefix)/cocotb/libs -m libcocotbvpi_icarus build/sim.vvp

compile:
mkdir -p build
make compile_alu
sv2v -I src/* -w build/gpu.v
sv2v src/cache.sv src/controller.sv src/core.sv src/decoder.sv src/dispatcher.sv src/fetcher.sv src/gpu.sv src/lsu.sv src/lsu_cached.sv src/pc.sv src/registers.sv src/scheduler.sv -w build/gpu.v
echo "" >> build/gpu.v
cat build/alu.v >> build/gpu.v
echo '`timescale 1ns/1ns' > build/temp.v
cat build/gpu.v >> build/temp.v
mv build/temp.v build/gpu.v

compile_%:
mkdir -p build
sv2v -w build/$*.v src/$*.sv

# TODO: Get gtkwave visualizaiton

show_%: %.vcd %.gtkw
gtkwave $^
gtkwave $^
136 changes: 136 additions & 0 deletions src/cache.sv
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
`default_nettype none
`timescale 1ns/1ns

// CACHE
// > Simple direct-mapped cache for data memory
// > Sits between LSU and memory controller
// > Stores recently accessed data to reduce global memory traffic
module cache #(
parameter CACHE_LINES = 64,
parameter ADDR_BITS = 8,
parameter DATA_BITS = 8,
parameter INDEX_BITS = 6, // log2(CACHE_LINES)
parameter TAG_BITS = 2 // ADDR_BITS - INDEX_BITS
) (
input wire clk,
input wire reset,
input wire enable,

// Interface from LSU
input wire read_request,
input wire write_request,
input wire [ADDR_BITS-1:0] address,
input wire [DATA_BITS-1:0] write_data,

// Interface to LSU
output reg read_ready,
output reg write_ready,
output reg [DATA_BITS-1:0] read_data,

// Interface to Memory Controller
output reg mem_read_valid,
output reg [ADDR_BITS-1:0] mem_read_address,
input wire mem_read_ready,
input wire [DATA_BITS-1:0] mem_read_data,
output reg mem_write_valid,
output reg [ADDR_BITS-1:0] mem_write_address,
output reg [DATA_BITS-1:0] mem_write_data,
input wire mem_write_ready
);
// State machine states
localparam IDLE = 2'b00;
localparam MEM_READ_WAIT = 2'b01;
localparam MEM_WRITE_WAIT = 2'b10;

// Cache storage
reg [DATA_BITS-1:0] cache_data [CACHE_LINES-1:0];
reg [TAG_BITS-1:0] cache_tags [CACHE_LINES-1:0];
reg cache_valid [CACHE_LINES-1:0];

// Extract index and tag from address
wire [INDEX_BITS-1:0] index = address[INDEX_BITS-1:0];
wire [TAG_BITS-1:0] tag = address[ADDR_BITS-1:INDEX_BITS];

// Cache hit detection
wire cache_hit = cache_valid[index] && (cache_tags[index] == tag);

// State register
reg [1:0] cache_state;

// Loop variable
integer i;

always @(posedge clk) begin
if (reset) begin
cache_state <= IDLE;
read_ready <= 0;
write_ready <= 0;
read_data <= 0;
mem_read_valid <= 0;
mem_read_address <= 0;
mem_write_valid <= 0;
mem_write_address <= 0;
mem_write_data <= 0;

// Initialize cache as invalid
for (i = 0; i < CACHE_LINES; i = i + 1) begin
cache_valid[i] <= 0;
cache_tags[i] <= 0;
cache_data[i] <= 0;
end
end else if (enable) begin
case (cache_state)
IDLE: begin
read_ready <= 0;
write_ready <= 0;

if (read_request) begin
if (cache_hit) begin
// Cache hit - return data immediately
read_data <= cache_data[index];
read_ready <= 1;
end else begin
// Cache miss - request from memory
mem_read_valid <= 1;
mem_read_address <= address;
cache_state <= MEM_READ_WAIT;
end
end else if (write_request) begin
// Write-through: update cache and write to memory
cache_data[index] <= write_data;
cache_tags[index] <= tag;
cache_valid[index] <= 1;

mem_write_valid <= 1;
mem_write_address <= address;
mem_write_data <= write_data;
cache_state <= MEM_WRITE_WAIT;
end
end

MEM_READ_WAIT: begin
if (mem_read_ready) begin
// Store data in cache
cache_data[index] <= mem_read_data;
cache_tags[index] <= tag;
cache_valid[index] <= 1;

// Return data to LSU
read_data <= mem_read_data;
read_ready <= 1;
mem_read_valid <= 0;
cache_state <= IDLE;
end
end

MEM_WRITE_WAIT: begin
if (mem_write_ready) begin
write_ready <= 1;
mem_write_valid <= 0;
cache_state <= IDLE;
end
end
endcase
end
end
endmodule
4 changes: 2 additions & 2 deletions src/core.sv
Original file line number Diff line number Diff line change
Expand Up @@ -144,8 +144,8 @@ module core #(
.rt(rt[i]),
.alu_out(alu_out[i])
);

// LSU
// LSU with Cache
lsu lsu_instance (
.clk(clk),
.reset(reset),
Expand Down
147 changes: 147 additions & 0 deletions src/lsu_cached.sv
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
`default_nettype none
`timescale 1ns/1ns

// LOAD-STORE UNIT WITH CACHE
// > Handles asynchronous memory load and store operations through cache
// > Each thread in each core has its own LSU with cache
// > LDR, STR instructions are executed here
module lsu_cached (
input wire clk,
input wire reset,
input wire enable,

// State
input reg [2:0] core_state,

// Memory Control Signals
input reg decoded_mem_read_enable,
input reg decoded_mem_write_enable,

// Registers
input reg [7:0] rs,
input reg [7:0] rt,

// Data Memory (through controller)
output reg mem_read_valid,
output reg [7:0] mem_read_address,
input reg mem_read_ready,
input reg [7:0] mem_read_data,
output reg mem_write_valid,
output reg [7:0] mem_write_address,
output reg [7:0] mem_write_data,
input reg mem_write_ready,

// LSU Outputs
output reg [1:0] lsu_state,
output reg [7:0] lsu_out
);
localparam IDLE = 2'b00, REQUESTING = 2'b01, WAITING = 2'b10, DONE = 2'b11;

// Cache signals
reg cache_read_request;
reg cache_write_request;
reg [7:0] cache_address;
reg [7:0] cache_write_data;
wire cache_read_ready;
wire cache_write_ready;
wire [7:0] cache_read_data;

// Instantiate cache
cache #(
.CACHE_LINES(64),
.ADDR_BITS(8),
.DATA_BITS(8),
.INDEX_BITS(6),
.TAG_BITS(2)
) cache_inst (
.clk(clk),
.reset(reset),
.enable(enable),

// LSU interface
.read_request(cache_read_request),
.write_request(cache_write_request),
.address(cache_address),
.write_data(cache_write_data),
.read_ready(cache_read_ready),
.write_ready(cache_write_ready),
.read_data(cache_read_data),

// Memory controller interface
.mem_read_valid(mem_read_valid),
.mem_read_address(mem_read_address),
.mem_read_ready(mem_read_ready),
.mem_read_data(mem_read_data),
.mem_write_valid(mem_write_valid),
.mem_write_address(mem_write_address),
.mem_write_data(mem_write_data),
.mem_write_ready(mem_write_ready)
);

always @(posedge clk) begin
if (reset) begin
lsu_state <= IDLE;
lsu_out <= 0;
cache_read_request <= 0;
cache_write_request <= 0;
cache_address <= 0;
cache_write_data <= 0;
end else if (enable) begin
// Handle memory read (LDR instruction)
if (decoded_mem_read_enable) begin
case (lsu_state)
IDLE: begin
if (core_state == 3'b011) begin // REQUEST state
lsu_state <= REQUESTING;
end
end
REQUESTING: begin
cache_read_request <= 1;
cache_address <= rs;
lsu_state <= WAITING;
end
WAITING: begin
if (cache_read_ready) begin
cache_read_request <= 0;
lsu_out <= cache_read_data;
lsu_state <= DONE;
end
end
DONE: begin
if (core_state == 3'b110) begin // UPDATE state
lsu_state <= IDLE;
end
end
endcase
end

// Handle memory write (STR instruction)
if (decoded_mem_write_enable) begin
case (lsu_state)
IDLE: begin
if (core_state == 3'b011) begin // REQUEST state
lsu_state <= REQUESTING;
end
end
REQUESTING: begin
cache_write_request <= 1;
cache_address <= rs;
cache_write_data <= rt;
lsu_state <= WAITING;
end
WAITING: begin
if (cache_write_ready) begin
cache_write_request <= 0;
lsu_state <= DONE;
end
end
DONE: begin
if (core_state == 3'b110) begin // UPDATE state
lsu_state <= IDLE;
end
end
endcase
end
end
end
endmodule
Loading