cache代码
`timescale 1ns / 1ps
//cache共32块,分为16组,每组2块,即两路组相联,1块=4字,1字=4字节
//主存共1024块,4096个字
//主存地址共12位,[1:0]为块内偏移,[5:2]为组地址,[11:6]为Tag
//V、D、Tag、Data=1+1+6+128=136
module cache(
input clk,
input rst,
//cpu<->cache
input [11:0]cpu_req_addr,
input cpu_req_valid,
input cpu_req_rw,
input [31:0]cpu_data_write,
output reg [31:0]cpu_data_read,
output reg cpu_ready,
//cache<->main 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 IDLE=0;
parameter CompareTag=1;
parameter Allocate=2;
parameter WriteBack=3;
parameter V=135;
parameter D=134;
parameter TagMSB=133;
parameter TagLSB=128;
parameter BlockMSB=127;
parameter BlockLSB=0;
reg [135:0] cache_data [0:31];
reg [1:0]state,next_state;
reg hit;
reg hit1,hit2;
reg way; //若hit,则way无意义,若miss,则way表示分配的那一路
wire [3:0]cpu_req_index;
wire [5: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[5:2];
assign cpu_req_tag=cpu_req_addr[11:6];
integer i;
//初始化cache
initial
begin
for(i=0;i<32;i=i+1)
cache_data[i]=136'd0;
end
//
always@(posedge clk,posedge rst)
if(rst)
state<=IDLE;
else
state<=next_state;
//state change
always@(*)
case(state)
IDLE:if(cpu_req_valid)
next_state=CompareTag;
else
next_state=IDLE;
CompareTag:if(hit) //若hit
next_state=IDLE;
else if(cache_data[2*cpu_req_index+way][V:D]==2'b11) //被分配的块有效且脏,则先写回主存
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
//hit1
always@(*)
if(state==CompareTag)
if(cache_data[2*cpu_req_index][V]==1'b1&&cache_data[2*cpu_req_index][TagMSB:TagLSB]==cpu_req_tag)
hit1=1'b1;
else
hit1=1'b0;
else
hit1=1'b0;
//hit2
always@(*)
if(state==CompareTag)
if(cache_data[2*cpu_req_index+1][V]==1'b1&&cache_data[2*cpu_req_index+1][TagMSB:TagLSB]==cpu_req_tag)
hit2=1'b1;
else
hit2=1'b0;
else
hit2=1'b0;
//hit
always@(*)
if(state==CompareTag)
hit=hit1||hit2;
else
hit=1'b0;
//way cache miss 时分配的块在组内的位置
always@(*)
if((state==CompareTag)&&(hit==1'b0)) //未命中
case({
cache_data[2*cpu_req_index][V],cache_data[2*cpu_req_index+1][V]})
2'b01:way=1'b0; //第0路可用
2'b10:way=1'b1; //第1路可用
2'b00:way=1'b0; //第0、1路均可用
2'b11:way=1'b0; //第0、1路均不可用,默认替换第0路
default:way=1'b0;
endcase
//CompareTag
always@(posedge clk)
if(state==CompareTag&&hit)
if(cpu_req_rw==1'b0) //read hit
begin
cpu_ready<=1'b1;
if(hit1)
cpu_data_read<=cache_data[2*cpu_req_index][32*cpu_req_offset +:32];
else
cpu_data_read<=cache_data[2*cpu_req_index+1][32*cpu_req_offset +:32];
end
else //write hit
begin
cpu_ready<=1'b1;
if(hit1)
begin
cache_data[2*cpu_req_index][32*cpu_req_offset +:32]<=cpu_data_write;
cache_data[2*cpu_req_index][D]<=1'b1;
end
else
begin
cache_data[2*cpu_req_index+1][32*cpu_req_offset +:32]<=cpu_data_write;
cache_data[2*cpu_req_index+1][D]<=1'b1;
end
end
else
cpu_ready<=1'b0;
//Allocate and WriteBack
always@(posedge clk)
if(state==Allocate) //load new block from memory to cache
if(!mem_ready)
begin
mem_req_valid<=1'b1;
mem_req_addr<={
cpu_req_addr[11:2],2'b00};
mem_req_rw<=1'b0;
end
else
begin
mem_req_valid<=1'b0;
cache_data[2*cpu_req_index+way]<={
2'b10,cpu_req_tag,mem_data_read};
end
else if(state==WriteBack) //write dirty old block to memory
if(!mem_ready)
begin
mem_req_valid<=1'b1;
mem_req_addr<={
cache_data[2*cpu_req_index+way][TagMSB:TagLSB],cpu_req_index,2'b00};
mem_data_write<=cache_data[2*cpu_req_index+way][BlockMSB:BlockLSB];
mem_req_rw<=1'b1;
end
else
begin
mem_req_valid<=1'b0;
end
else
mem_req_valid<=1'b0;
endmodule
mem代码
`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 Write1=0;
parameter Write2=1;
parameter Write3=2;
parameter Write4=3;
parameter Read1=4;
parameter Read2=5;
parameter Read3=6;
parameter Read4=7;
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<=Write1;
else
state<=next_state;
always@(*)
case(state)
Write1:if(cpu_ready)
begin
next_state=Write2;
cpu_req_valid=1'b0;
end
else
next_state=Write1;
Write2:if(cpu_ready)
begin
next_state=Write3;
cpu_req_valid=1'b0;
end
else
next_state=Write2;
Write3:if(cpu_ready)
begin
next_state=Write4;
cpu_req_valid=1'b0;
end
else
next_state=Write3;
Write4:if(cpu_ready)
begin
next_state=Read1;
cpu_req_valid=1'b0;
end
else
next_state=Write4;
Read1:if(cpu_ready)
begin
next_state=Read2;
cpu_req_valid=1'b0;
end
else
next_state=Read1;
Read2:if(cpu_ready)
begin
next_state=Read3;
cpu_req_valid=1'b0;
end
else
next_state=Read2;
Read3:if(cpu_ready)
begin
next_state=Read4;
cpu_req_valid=1'b0;
end
else
next_state=Read3;
Read4:next_state=Read4;
default:next_state=Write1;
endcase
always@(posedge clk,posedge rst)
if(rst)
begin
cpu_req_valid<=1'b0;
cpu_req_rw<=1'b0;
cpu_req_addr<=12'd0;
cpu_data_write<=32'd0;
end
else
case(state)
Write1:begin
cpu_req_valid<=1'b1;
cpu_req_rw<=1'b1;
cpu_req_addr<=12'd0;
cpu_data_write<=32'd8;
end
Write2:begin
cpu_req_valid<=1'b1;
cpu_req_rw<=1'b1;
cpu_req_addr<=12'd64;
cpu_data_write<=32'd9;
end
Write3:begin
cpu_req_valid<=1'b1;
cpu_req_rw<=1'b1;
cpu_req_addr<=12'd128;
cpu_data_write<=32'd6;
end
Write4:begin
cpu_req_valid<=1'b1;
cpu_req_rw<=1'b1;
cpu_req_addr<=12'd65;
cpu_data_write<=32'd7;
end
Read1:begin
cpu_req_valid<=1'b1;
cpu_req_rw<=1'b0;
cpu_req_addr<=12'd0;
end
Read2:begin
cpu_req_valid<=1'b1;
cpu_req_rw<=1'b0;
cpu_req_addr<=12'd4;
end
Read3:begin
cpu_req_valid<=1'b1;
cpu_req_rw<=1'b0;
cpu_req_addr<=12'd68;
end
Read4:begin
cpu_req_valid<=1'b1;
cpu_req_rw<=1'b0;
cpu_req_addr<=12'd65;
end
default:begin
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