cache控制器
//直接相联cache,cache大小为32块,主存大小为1024块,1块=4字,1字=32bit
//主存地址为12位,其中[1:0]是块内偏移,[6:2]是索引,[11:7]是Tag
//cache V+D+Tag+Data=1+1+5+128=135
module cache(
input clk,
input rst,
//cpu<->cache
input [11:0]cpu_req_addr,
input cpu_req_rw,
input cpu_req_valid,
input [31:0]cpu_data_write,
output reg [31:0]cpu_data_read,
output reg cpu_ready,
//cache<->memory
output reg [11:0]mem_req_addr,
output reg mem_req_rw,
output reg mem_req_valid,
output reg [127:0]mem_data_write,
input [127:0]mem_data_read,
input mem_ready
);
parameter V = 134;
parameter D = 133;
parameter TagMSB = 132;
parameter TagLSB = 128;
parameter BlockMSB = 127;
parameter BlockLSB = 0 ;
parameter IDLE=0;
parameter CompareTag=1;
parameter Allocate=2;
parameter WriteBack=3;
reg [134:0] cache_data[0:31]; //134:V,133:D,[132:128]:TAG,[127:0]DATA
reg [1:0]state,next_state;
reg hit;
wire [4:0]cpu_req_index;
wire [4:0]cpu_req_tag;
wire [1:0]cpu_req_offset;
assign cpu_req_offset=cpu_req_addr[1:0];
assign cpu_req_index=cpu_req_addr[6:2];
assign cpu_req_tag=cpu_req_addr[11:7];
integer i;
//初始化cache
initial
begin
for(i=0;i<32;i=i+1)
cache_data[i]=135'd0;
end
always@(posedge clk,posedge rst)
if(rst)
state<=IDLE;
else
state<=next_state;
//
always@(*)
case(state)
IDLE:if(cpu_req_valid)
next_state=CompareTag;
else
next_state=IDLE;
CompareTag:if(hit)
next_state=IDLE;
else if(cache_data[cpu_req_index][V:D]==2'b11) //if the block is valid and dirty then go to WriteBack
next_state=WriteBack;
else
next_state=Allocate;
Allocate:if(mem_ready)
next_state=CompareTag;
else
next_state=Allocate;
WriteBack:if(mem_ready)
next_state=Allocate;
else
next_state=WriteBack;
default:next_state=IDLE;
endcase
always@(*)
if(state==CompareTag)
if(cache_data[cpu_req_index][134]&&cache_data[cpu_req_index][TagMSB:TagLSB]==cpu_req_tag)
hit=1'b1;
else
hit=1'b0;
always@(posedge clk)
if(state==Allocate) //read new block from memory to cache
if(!mem_ready)
begin
mem_req_addr<={
cpu_req_addr[11:2],2'b00};
mem_req_rw<=1'b0;
mem_req_valid<=1'b1;
end
else
begin
mem_req_valid<=1'b0;
cache_data[cpu_req_index][BlockMSB:BlockLSB]<=mem_data_read;
cache_data[cpu_req_index][V:D]<=2'b10;
cache_data[cpu_req_index][TagMSB:TagLSB]<=cpu_req_tag;
end
else if(state==WriteBack) //write dirty block to memory
if(!mem_ready)
begin
mem_req_addr<={
cache_data[cpu_req_index][TagMSB:TagLSB],cpu_req_index,2'b00};
mem_req_rw<=1'b1;
mem_data_write<=cache_data[cpu_req_index][BlockMSB:BlockLSB];
mem_req_valid<=1'b1;
end
else
begin
mem_req_valid<=1'b0;
end
else
begin
mem_req_valid=1'b0;
end
always@(posedge clk)
if(state==CompareTag&&hit)
if(cpu_req_rw==1'b0) //read hit
begin
cpu_ready<=1'b1;
cpu_data_read<=cache_data[cpu_req_index][cpu_req_offset*32 +:32];
end
else //write hit,置脏位为1
begin
cpu_ready<=1'b1;
cache_data[cpu_req_index][cpu_req_offset*32 +:32]=cpu_data_write;
cache_data[cpu_req_index][D]=1'b1;
end
else
cpu_ready<=1'b0;
endmodule
主存文件mem.v
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2020/08/20 14:24:27
// Design Name:
// Module Name: mem
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module mem(
input clk,
input rst,
input [11:0]mem_req_addr, //[1:0]块内地址
input mem_req_rw,
input mem_req_valid,
input [127:0]mem_data_write,
output reg [127:0]mem_data_read,
output reg mem_ready
);
reg [31:0] mem [0:4095]; //4096个字,1024个块
integer i;
initial
begin
for(i=0;i<4096;i=i+1)
mem[i]=32'd0;
end
always@(posedge clk,posedge rst)
if(rst)
mem_ready<=1'b0;
else if(mem_req_valid&&mem_req_rw==1'b1&&!mem_ready) //write
begin
mem[mem_req_addr+3]=mem_data_write[127:96];
mem[mem_req_addr+2]=mem_data_write[95:64];
mem[mem_req_addr+1]=mem_data_write[63:32];
mem[mem_req_addr]=mem_data_write[31:0];
mem_ready<=1'b1;
end
else if(mem_req_valid&&mem_req_rw==1'b0&&!mem_ready) //read
begin
mem_data_read={
mem[mem_req_addr+3],mem[mem_req_addr+2],mem[mem_req_addr+1],mem[mem_req_addr]};
mem_ready<=1'b1;
end
else if(mem_req_valid&&mem_ready)
mem_ready<=1'b0;
endmodule
仿真文件
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2020/08/20 15:25:17
// Design Name:
// Module Name: test
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module test(
);
parameter WriteMiss=0;
parameter WriteHit=1;
parameter ReadHit=2;
parameter ReadMiss=3;
parameter WriteDirtyMiss=4;
parameter ReadDirtyMiss=5;
reg clk;
reg rst;
reg [3:0]state,next_state;
reg [11:0]cpu_req_addr;
reg cpu_req_rw;
reg cpu_req_valid;
reg [31:0]cpu_data_write;
wire [31:0]cpu_data_read;
wire cpu_ready;
wire [11:0]mem_req_addr;
wire mem_req_rw;
wire mem_req_valid;
wire [127:0]mem_data_write;
wire [127:0]mem_data_read;
wire mem_ready;
initial
begin
clk=0;
forever
#5 clk=~clk;
end
initial
begin
rst=1;
#10
rst=0;
end
always@(posedge clk,posedge rst)
if(rst)
state<=WriteMiss;
else
state<=next_state;
always@(*)
case(state)
WriteMiss:if(cpu_ready)
begin
next_state=WriteHit;
cpu_req_valid=1'b0;
end
else
next_state=WriteMiss;
WriteHit:if(cpu_ready)
begin
next_state=ReadMiss;
cpu_req_valid=1'b0;
end
else
next_state=WriteHit;
ReadMiss:if(cpu_ready)
begin
next_state=ReadHit;
cpu_req_valid=1'b0;
end
else
next_state=ReadMiss;
ReadHit:if(cpu_ready)
begin
next_state=WriteDirtyMiss;
cpu_req_valid=1'b0;
end
else
next_state=ReadHit;
WriteDirtyMiss:if(cpu_ready)
begin
next_state=ReadDirtyMiss;
cpu_req_valid=1'b0;
end
else
next_state=WriteDirtyMiss;
ReadDirtyMiss:next_state=ReadDirtyMiss;
default:next_state=WriteMiss;
endcase
always@(posedge clk,posedge rst)
if(rst)
begin
cpu_req_rw<=1'b0;
cpu_req_addr<=21'd0;
cpu_req_valid<=1'b0;
cpu_data_write<=32'd0;
end
else
case(state)
WriteMiss:begin
cpu_req_rw<=1'b1;
cpu_req_addr<=12'd0;
cpu_data_write<=32'd8;
cpu_req_valid<=1'b1;
end
WriteHit:begin
cpu_req_rw<=1'b1;
cpu_req_addr<=12'd0;
cpu_data_write<=32'd9;
cpu_req_valid<=1'b1;
end
ReadMiss:begin
cpu_req_rw<=1'b0;
cpu_req_addr<=12'd4;
cpu_data_write<=cpu_data_write;
cpu_req_valid<=1'b1;
end
ReadHit:begin
cpu_req_rw<=1'b0;
cpu_req_addr<=12'd0;
cpu_data_write<=cpu_data_write;
cpu_req_valid<=1'b1;
end
WriteDirtyMiss:begin
cpu_req_valid<=1'b1;
cpu_req_rw<=1'b1;
cpu_data_write<=32'd6;
cpu_req_addr<=32'd128;
end
ReadDirtyMiss:begin
cpu_req_valid<=1'b1;
cpu_req_rw<=1'b0;
cpu_req_addr<=32'd0;
cpu_data_write<=cpu_data_write;
end
default:begin
cpu_req_rw<=1'b1;
cpu_req_addr<=12'd0;
cpu_data_write<=32'd8;
cpu_req_valid<=1'b0;
end
endcase
cache U1(.clk(clk),
.rst(rst),
.cpu_req_addr(cpu_req_addr),
.cpu_req_rw(cpu_req_rw),
.cpu_req_valid(cpu_req_valid),
.cpu_data_write(cpu_data_write),
.cpu_data_read(cpu_data_read),
.cpu_ready(cpu_ready),
//***********************//
.mem_req_addr(mem_req_addr),
.mem_req_rw(mem_req_rw),
.mem_req_valid(mem_req_valid),
.mem_data_write(mem_data_write),
.mem_data_read(mem_data_read),
.mem_ready(mem_ready));
mem U2(.clk(clk),
.rst(rst),
.mem_req_addr(mem_req_addr),
.mem_req_rw(mem_req_rw),
.mem_req_valid(mem_req_valid),
.mem_data_write(mem_data_write),
.mem_data_read(mem_data_read),
.mem_ready(mem_ready));
endmodule