Commit 077dcdfd authored by jinbao chen's avatar jinbao chen
Browse files

lab3

parent e04f8301
......@@ -10,18 +10,18 @@
// Description: IF-ID Segment Register
//////////////////////////////////////////////////////////////////////////////////
//功能说明
//IDSegReg是IF-ID段寄存器,同时包含了个同步读写的Bram(此处你可以调用我们提供的InstructionRam
//它将会自动综合为block memory,你也可以替代的调用xilinx的bram ip核)
//同步读memory 相当 异步读memory 的输出外接D触发器,要时钟上升沿才能读取数据
//此时如果再过段寄存器缓存,那么需要两个时钟上升沿才能将数据传递到Ex
//因此在段寄存器模块中调用该同步memory,直接将输出传到ID段组合
//调用mem模块后输出为RD_raw,过assign RD = stall_ff ? RD_old : (clear_ff ? 32'b0 : RD_raw );
//从实现RD段寄存器stall和clear功能
//IDSegReg是IF-ID段寄存器,同时包含了?个同步读写的Bram(此处你可以调用我们提供的InstructionRam?
//它将会自动综合为block memory,你也可以替代?的调用xilinx的bram ip核)?
//同步读memory 相当? 异步读memory 的输出外接D触发器,?要时钟上升沿才能读取数据?
//此时如果再?过段寄存器缓存,那么需要两个时钟上升沿才能将数据传递到Ex?
//因此在段寄存器模块中调用该同步memory,直接将输出传?到ID段组合?
//调用mem模块后输出为RD_raw,?过assign RD = stall_ff ? RD_old : (clear_ff ? 32'b0 : RD_raw );
//从?实现RD段寄存器stall和clear功能
//实验要求
//补全IDSegReg模块,需补全的片段截取如
//补全IDSegReg模块,需补全的片段截取如?
//InstructionRam InstructionRamInst (
// .clk (), //请完善代
// .addra (), //请完善代
// .clk (), //请完善代?
// .addra (), //请完善代?
// .douta ( RD_raw ),
// .web ( |WE2 ),
// .addrb ( A2[31:2] ),
......@@ -55,8 +55,8 @@ module IDSegReg(
wire [31:0] RD_raw;
/* InstructionRam InstructionRamInst (
.clk (clk), //请完善代
.addra (A[31:2]), //请完善代
.clk (clk), //请完善代?
.addra (A[31:2]), //请完善代?
.douta ( RD_raw ),
.web ( |WE2 ),
.addrb ( A2[31:2] ),
......
......@@ -10,21 +10,21 @@
// Description: Write Back Segment Register
//////////////////////////////////////////////////////////////////////////////////
//功能说明
//WBSegReg是Write Back段寄存器
//WBSegReg是Write Back段寄存器?
//类似于IDSegReg.V中对Bram的调用和拓展,它同时包含了一个同步读写的Bram
//(此处你可以调用我们提供的InstructionRam,它将会自动综合为block memory,你也可以替代的调用xilinx的bram ip核)
//同步读memory 相当 异步读memory 的输出外接D触发器,要时钟上升沿才能读取数据
//此时如果再过段寄存器缓存,那么需要两个时钟上升沿才能将数据传递到Ex
//因此在段寄存器模块中调用该同步memory,直接将输出传到WB段组合
//调用mem模块后输出为RD_raw,过assign RD = stall_ff ? RD_old : (clear_ff ? 32'b0 : RD_raw );
//从实现RD段寄存器stall和clear功能
//(此处你可以调用我们提供的InstructionRam,它将会自动综合为block memory,你也可以替代?的调用xilinx的bram ip核)?
//同步读memory 相当? 异步读memory 的输出外接D触发器,?要时钟上升沿才能读取数据?
//此时如果再?过段寄存器缓存,那么需要两个时钟上升沿才能将数据传递到Ex?
//因此在段寄存器模块中调用该同步memory,直接将输出传?到WB段组合?
//调用mem模块后输出为RD_raw,?过assign RD = stall_ff ? RD_old : (clear_ff ? 32'b0 : RD_raw );
//从?实现RD段寄存器stall和clear功能
//实验要求
//你需要补全WBSegReg模块,需补全的片段截取如
//你需要补全WBSegReg模块,需补全的片段截取如?
//DataRam DataRamInst (
// .clk (???), //请完善代
// .wea (???), //请完善代
// .addra (???), //请完善代
// .dina (???), //请完善代
// .clk (???), //请完善代?
// .wea (???), //请完善代?
// .addra (???), //请完善代?
// .dina (???), //请完善代?
// .douta ( RD_raw ),
// .web ( WE2 ),
// .addrb ( A2[31:2] ),
......@@ -34,7 +34,7 @@
//注意事项
//输入到DataRam的addra是字地址,一个字32bit
//请配合DataExt模块实现非字对齐字节load
//请过补全代码实现非字对齐store
//请?过补全代码实现非字对齐store
module WBSegReg(
......@@ -99,10 +99,10 @@ module WBSegReg(
wire [31:0] RD_raw;
/* DataRam DataRamInst (
.clk (clk), //请完善代
.wea (WE << A[1:0]), //请完善代
.addra (A[31:2]), //请完善代
.dina (WD << {A[1:0],3'b0}), //请完善代
.clk (clk), //请完善代?
.wea (WE << A[1:0]), //请完善代?
.addra (A[31:2]), //请完善代?
.dina (WD << {A[1:0],3'b0}), //请完善代?
.douta ( RD_raw ),
.web ( WE2 ),
.addrb ( A2[31:2] ),
......@@ -148,7 +148,7 @@ always@(posedge clk or posedge rst) begin
end
end
cache_fifo DataCacheInst (
cache_lru DataCacheInst (
.clk (clk),
.rst (rst),
.miss (DCacheMiss),
......@@ -171,7 +171,7 @@ end
begin
stall_ff<=~en;
clear_ff<=clear;
RD_old<=RD_raw;
RD_old<=RD;
end
assign RD = stall_ff ? RD_old : (clear_ff ? 32'b0 : RD_raw );
......
// asm file name: QuickSort.S
// asm file name: .\QuickSort.S
module InstructionCache(
input wire clk,
input wire write_en,
......@@ -19,7 +19,7 @@ module InstructionCache(
initial begin
data = 32'h0;
debug_data = 32'h0;
inst_cache[ 0] = 32'h01004693;
inst_cache[ 0] = 32'h10004693;
inst_cache[ 1] = 32'h00001137;
inst_cache[ 2] = 32'h00004533;
inst_cache[ 3] = 32'h000045b3;
......
module cache_fifo #(
parameter LINE_ADDR_LEN = 3, // line内地????长度,决定了每个line具有2^3个word
parameter SET_ADDR_LEN = 3, // 组地????长度,决定了????共有2^3=8????
parameter TAG_ADDR_LEN = 6, // tag长度
parameter WAY_CNT = 5 // 组相连度,决定了每组中有多少路line,这里是直接映射型cache,因此该参数没用????
parameter LINE_ADDR_LEN = 3, // line内地?????长度,决定了每个line具有2^3个word
parameter SET_ADDR_LEN = 4, // 组地?????长度,决定了?????共有2^3=8?????
parameter TAG_ADDR_LEN = 5, // tag长度
parameter WAY_CNT = 12 // 组相连度,决定了每组中有多少路line,这里是直接映射型cache,因此该参数没用?????
)(
input clk, rst,
output miss, // 对CPU发出的miss信号
input [31:0] addr, // 读写请求地址
input rd_req, // 读请求信????
output reg [31:0] rd_data, // 读出的数据,????次读????个word
input wr_req, // 写请求信????
input [31:0] wr_data // 要写入的数据,一次写????个word
input rd_req, // 读请求信?????
output reg [31:0] rd_data, // 读出的数据,?????次读?????个word
input wr_req, // 写请求信?????
input [31:0] wr_data // 要写入的数据,一次写?????个word
);
localparam MEM_ADDR_LEN = TAG_ADDR_LEN + SET_ADDR_LEN ; // 计算主存地址长度 MEM_ADDR_LEN,主存大????=2^MEM_ADDR_LEN个line
localparam UNUSED_ADDR_LEN = 32 - TAG_ADDR_LEN - SET_ADDR_LEN - LINE_ADDR_LEN - 2 ; // 计算未使用的地址的长????
localparam MEM_ADDR_LEN = TAG_ADDR_LEN + SET_ADDR_LEN ; // 计算主存地址长度 MEM_ADDR_LEN,主存大?????=2^MEM_ADDR_LEN个line
localparam UNUSED_ADDR_LEN = 32 - TAG_ADDR_LEN - SET_ADDR_LEN - LINE_ADDR_LEN - 2 ; // 计算未使用的地址的长?????
localparam LINE_SIZE = 1 << LINE_ADDR_LEN ; // 计算 line ???? word 的数量,???? 2^LINE_ADDR_LEN 个word ???? line
localparam SET_SIZE = 1 << SET_ADDR_LEN ; // 计算????共有多少组,???? 2^SET_ADDR_LEN 个组
localparam LINE_SIZE = 1 << LINE_ADDR_LEN ; // 计算 line ????? word 的数量,????? 2^LINE_ADDR_LEN 个word ????? line
localparam SET_SIZE = 1 << SET_ADDR_LEN ; // 计算?????共有多少组,????? 2^SET_ADDR_LEN 个组
reg [ 31:0] cache_mem [SET_SIZE][WAY_CNT][LINE_SIZE]; // SET_SIZE个line,每个line有LINE_SIZE个word
reg [TAG_ADDR_LEN-1:0] cache_tags [SET_SIZE][WAY_CNT]; // SET_SIZE个TAG
reg valid [SET_SIZE][WAY_CNT]; // SET_SIZE个valid(有效????)
reg valid [SET_SIZE][WAY_CNT]; // SET_SIZE个valid(有效?????)
reg dirty [SET_SIZE][WAY_CNT]; // SET_SIZE个dirty(脏位)
reg [ WAY_CNT:0] cache_fifo [SET_SIZE];
reg [ WAY_CNT:0] way_length [SET_SIZE];
reg [ WAY_CNT:0] swap_out;
wire [ 2-1:0] word_addr; // 将输入地????addr拆分成这5个部????
wire [ 2-1:0] word_addr; // 将输入地?????addr拆分成这5个部?????
wire [ LINE_ADDR_LEN-1:0] line_addr;
wire [ SET_ADDR_LEN-1:0] set_addr;
wire [ TAG_ADDR_LEN-1:0] tag_addr;
......@@ -37,8 +37,8 @@ wire [UNUSED_ADDR_LEN-1:0] unused_addr;
wire [ WAY_CNT:0] fifo_pos;
wire [ WAY_CNT:0] queue_len;
enum {IDLE, SWAP_OUT, SWAP_IN, SWAP_IN_OK} cache_stat; // cache 状�?�机的状态定????
// IDLE代表就绪,SWAP_OUT代表正在换出,SWAP_IN代表正在换入,SWAP_IN_OK代表换入后进行一周期的写入cache操作????
enum {IDLE, SWAP_OUT, SWAP_IN, SWAP_IN_OK} cache_stat; // cache 状�?�机的状态定?????
// IDLE代表就绪,SWAP_OUT代表正在换出,SWAP_IN代表正在换入,SWAP_IN_OK代表换入后进行一周期的写入cache操作?????
reg [ SET_ADDR_LEN-1:0] mem_rd_set_addr = 0;
reg [ TAG_ADDR_LEN-1:0] mem_rd_tag_addr = 0;
......@@ -95,11 +95,11 @@ always @ (posedge clk or posedge rst) begin // ?? cache ???
if(rd_req) begin // 如果cache命中,并且是读请求,
rd_data <= cache_mem[set_addr][hit_pos][line_addr]; //则直接从cache中取出要读的数据
end else if(wr_req) begin // 如果cache命中,并且是写请求,
cache_mem[set_addr][hit_pos][line_addr] <= wr_data; // 则直接向cache中写入数????
dirty[set_addr][hit_pos] <= 1'b1; // 写数据的同时置脏????
cache_mem[set_addr][hit_pos][line_addr] <= wr_data; // 则直接向cache中写入数?????
dirty[set_addr][hit_pos] <= 1'b1; // 写数据的同时置脏?????
end
end else begin
if(wr_req | rd_req) begin // 如果 cache 未命中,并且有读写请求,则需要进行换????
if(wr_req | rd_req) begin // 如果 cache 未命中,并且有读写请求,则需要进行换?????
swap_out <= fifo_pos;
cache_fifo[set_addr] <= (fifo_pos + 1) % WAY_CNT;
if(queue_len < WAY_CNT)begin
......@@ -110,7 +110,7 @@ always @ (posedge clk or posedge rst) begin // ?? cache ???
cache_stat <= SWAP_OUT;
mem_wr_addr <= {cache_tags[set_addr][fifo_pos], set_addr};
mem_wr_line <= cache_mem[set_addr][fifo_pos];
end else begin // 反之,不????要换出,直接换入
end else begin // 反之,不?????要换出,直接换入
cache_stat <= SWAP_IN;
end
end
......@@ -128,13 +128,7 @@ always @ (posedge clk or posedge rst) begin // ?? cache ???
cache_stat <= SWAP_IN_OK;
end
end
SWAP_IN_OK: begin // 上一个周期换入成功,这周期将主存读出的line写入cache,并更新tag,置高valid,置低dirty
/* if(mem_fifo_len < WAY_CNT) begin//FIXME:fifo_len
for(integer i=0; i<LINE_SIZE; i++) cache_mem[mem_rd_set_addr][mem_fifo_len][i] <= mem_rd_line[i];
way_length[mem_rd_set_addr] <= mem_fifo_len + 1;
end */
/* else */
SWAP_IN_OK: begin // 上一个周期换入成功,这周期将主存读出的line写入cache,并更新tag,置高valid,置低dirty
for(integer i=0; i<LINE_SIZE; i++) cache_mem[mem_rd_set_addr][swap_out][i] <= mem_rd_line[i];
cache_tags[mem_rd_set_addr][swap_out] <= mem_rd_tag_addr;
valid [mem_rd_set_addr][swap_out] <= 1'b1;
......@@ -149,9 +143,9 @@ wire mem_rd_req = (cache_stat == SWAP_IN );
wire mem_wr_req = (cache_stat == SWAP_OUT);
wire [ MEM_ADDR_LEN-1 :0] mem_addr = mem_rd_req ? mem_rd_addr : ( mem_wr_req ? mem_wr_addr : 0);
assign miss = (rd_req | wr_req) & ~(cache_hit && cache_stat==IDLE) ; // ???? 有读写请求时,如果cache不处于就????(IDLE)状�?�,或�?�未命中,则miss=1
assign miss = (rd_req | wr_req) & ~(cache_hit && cache_stat==IDLE) ; // ????? 有读写请求时,如果cache不处于就?????(IDLE)状�?�,或�?�未命中,则miss=1
main_mem #( // 主存,每次读写以line 为单????
main_mem #( // 主存,每次读写以line 为单?????
.LINE_ADDR_LEN ( LINE_ADDR_LEN ),
.ADDR_LEN ( MEM_ADDR_LEN )
) main_mem_instance (
......
module cache_lru #(
parameter LINE_ADDR_LEN = 3, // line内地???长度,决定了每个line具有2^3个word
parameter SET_ADDR_LEN = 3, // 组地???长度,决定了???共有2^3=8???
parameter TAG_ADDR_LEN = 6, // tag长度
parameter WAY_CNT = 5 // 组相连度,决定了每组中有多少路line,这里是直接映射型cache,因此该参数没用???
parameter LINE_ADDR_LEN = 3, // line内地????长度,决定了每个line具有2^3个word
parameter SET_ADDR_LEN = 4, // 组地????长度,决定了????共有2^3=8????
parameter TAG_ADDR_LEN = 5, // tag长度
parameter WAY_CNT = 4 // 组相连度,决定了每组中有多少路line,这里是直接映射型cache,因此该参数没用????
)(
input clk, rst,
output miss, // 对CPU发出的miss信号
input [31:0] addr, // 读写请求地址
input rd_req, // 读请求信???
output reg [31:0] rd_data, // 读出的数据,???次读???个word
input wr_req, // 写请求信???
input [31:0] wr_data // 要写入的数据,一次写???个word
input rd_req, // 读请求信????
output reg [31:0] rd_data, // 读出的数据,????次读????个word
input wr_req, // 写请求信????
input [31:0] wr_data // 要写入的数据,一次写????个word
);
localparam MEM_ADDR_LEN = TAG_ADDR_LEN + SET_ADDR_LEN ; // 计算主存地址长度 MEM_ADDR_LEN,主存大???=2^MEM_ADDR_LEN个line
localparam UNUSED_ADDR_LEN = 32 - TAG_ADDR_LEN - SET_ADDR_LEN - LINE_ADDR_LEN - 2 ; // 计算未使用的地址的长???
localparam MEM_ADDR_LEN = TAG_ADDR_LEN + SET_ADDR_LEN ; // 计算主存地址长度 MEM_ADDR_LEN,主存大????=2^MEM_ADDR_LEN个line
localparam UNUSED_ADDR_LEN = 32 - TAG_ADDR_LEN - SET_ADDR_LEN - LINE_ADDR_LEN - 2 ; // 计算未使用的地址的长????
localparam LINE_SIZE = 1 << LINE_ADDR_LEN ; // 计算 line ??? word 的数量,??? 2^LINE_ADDR_LEN 个word ??? line
localparam SET_SIZE = 1 << SET_ADDR_LEN ; // 计算???共有多少组,??? 2^SET_ADDR_LEN 个组
localparam LINE_SIZE = 1 << LINE_ADDR_LEN ; // 计算 line ???? word 的数量,???? 2^LINE_ADDR_LEN 个word ???? line
localparam SET_SIZE = 1 << SET_ADDR_LEN ; // 计算????共有多少组,???? 2^SET_ADDR_LEN 个组
reg [ 31:0] cache_mem [SET_SIZE][WAY_CNT][LINE_SIZE]; // SET_SIZE个line,每个line有LINE_SIZE个word
reg [TAG_ADDR_LEN-1:0] cache_tags [SET_SIZE][WAY_CNT]; // SET_SIZE个TAG
reg valid [SET_SIZE][WAY_CNT]; // SET_SIZE个valid(有效???)
reg valid [SET_SIZE][WAY_CNT]; // SET_SIZE个valid(有效????)
reg dirty [SET_SIZE][WAY_CNT]; // SET_SIZE个dirty(脏位)
reg [ WAY_CNT:0] lru_stack [SET_SIZE][WAY_CNT];
reg [ WAY_CNT:0] way_length [SET_SIZE];
wire [ 2-1:0] word_addr; // 将输入地???addr拆分成这5个部???
wire [ 2-1:0] word_addr; // 将输入地????addr拆分成这5个部????
wire [ LINE_ADDR_LEN-1:0] line_addr;
wire [ SET_ADDR_LEN-1:0] set_addr;
wire [ TAG_ADDR_LEN-1:0] tag_addr;
......@@ -36,8 +36,8 @@ wire [UNUSED_ADDR_LEN-1:0] unused_addr;
wire [ WAY_CNT:0] lru_pos;
wire [ WAY_CNT:0] stack_len;
enum {IDLE, SWAP_OUT, SWAP_IN, SWAP_IN_OK} cache_stat; // cache 状�?�机的状态定???
// IDLE代表就绪,SWAP_OUT代表正在换出,SWAP_IN代表正在换入,SWAP_IN_OK代表换入后进行一周期的写入cache操作???
enum {IDLE, SWAP_OUT, SWAP_IN, SWAP_IN_OK} cache_stat; // cache 状�?�机的状态定????
// IDLE代表就绪,SWAP_OUT代表正在换出,SWAP_IN代表正在换入,SWAP_IN_OK代表换入后进行一周期的写入cache操作????
reg [ SET_ADDR_LEN-1:0] mem_rd_set_addr = 0;
reg [ TAG_ADDR_LEN-1:0] mem_rd_tag_addr = 0;
......@@ -48,7 +48,7 @@ reg [ MEM_ADDR_LEN-1:0] mem_wr_addr = 0;
reg [31:0] mem_wr_line [LINE_SIZE];
wire [31:0] mem_rd_line [LINE_SIZE];
wire mem_gnt; // 主存响应读写的握手信???
wire mem_gnt; // 主存响应读写的握手信????
assign {unused_addr, tag_addr, set_addr, line_addr, word_addr} = addr; // 拆分 32bit ADDR
......@@ -57,10 +57,10 @@ assign lru_pos = lru_stack[set_addr][WAY_CNT-1];
reg cache_hit = 1'b0;
reg [WAY_CNT:0] hit_pos = 0; //hit pos in set
reg [WAY_CNT:0] stack_pt;
reg [WAY_CNT:0] stack_pos;
reg [WAY_CNT:0] swap_out;
always @ (*) begin // 判断 输入的address 是否??? cache 中命???
always @ (*) begin // 判断 输入的address 是否???? cache 中命????
for(integer i = 0;i < WAY_CNT;i++) begin
if(valid[set_addr][i] && cache_tags[set_addr][i] == tag_addr) begin
cache_hit = 1'b1;
......@@ -74,9 +74,9 @@ always @ (*) begin // 判断 输入的address 是否
end
always @(*) begin
for(integer i=0;i<WAY_CNT;i++)begin//find stack pt
for(integer i=0;i<WAY_CNT;i++)begin//find stack_pos
if(lru_stack[set_addr][i]==hit_pos)begin
stack_pt <= i;
stack_pos <= i;
break;
end
end
......@@ -103,7 +103,7 @@ always @ (posedge clk or posedge rst) begin // ?? cache ???
IDLE: begin
if(cache_hit) begin
if(rd_req||wr_req)begin
for(integer i = 0; i < stack_pt; i++)begin
for(integer i = 0; i < stack_pos; i++)begin
lru_stack[set_addr][i+1] <= lru_stack[set_addr][i];
end
lru_stack[set_addr][0] <= hit_pos;
......@@ -111,11 +111,11 @@ always @ (posedge clk or posedge rst) begin // ?? cache ???
if(rd_req) begin // 如果cache命中,并且是读请求,
rd_data <= cache_mem[set_addr][hit_pos][line_addr]; //则直接从cache中取出要读的数据
end else if(wr_req) begin // 如果cache命中,并且是写请求,
cache_mem[set_addr][hit_pos][line_addr] <= wr_data; // 则直接向cache中写入数???
cache_mem[set_addr][hit_pos][line_addr] <= wr_data; // 则直接向cache中写入数????
dirty[set_addr][hit_pos] <= 1'b1;
end
end else begin
if(wr_req | rd_req) begin // 如果 cache 未命中,并且有读写请求,则需要进行换???
if(wr_req | rd_req) begin // 如果 cache 未命中,并且有读写请求,则需要进行换????
if(stack_len < WAY_CNT)begin
cache_stat <= SWAP_IN;
way_length[set_addr] <= stack_len + 1;
......@@ -127,7 +127,7 @@ always @ (posedge clk or posedge rst) begin // ?? cache ???
cache_stat <= SWAP_OUT;
mem_wr_addr <= {cache_tags[set_addr][lru_pos], set_addr};
mem_wr_line <= cache_mem[set_addr][lru_pos];
end else begin // 反之,不???要换出,直接换入
end else begin // 反之,不????要换出,直接换入
cache_stat <= SWAP_IN;
end
end
......@@ -160,9 +160,9 @@ wire mem_rd_req = (cache_stat == SWAP_IN );
wire mem_wr_req = (cache_stat == SWAP_OUT);
wire [ MEM_ADDR_LEN-1 :0] mem_addr = mem_rd_req ? mem_rd_addr : ( mem_wr_req ? mem_wr_addr : 0);
assign miss = (rd_req | wr_req) & ~(cache_hit && cache_stat==IDLE) ; // ??? 有读写请求时,如果cache不处于就???(IDLE)状�?�,或�?�未命中,则miss=1
assign miss = (rd_req | wr_req) & ~(cache_hit && cache_stat==IDLE) ; // ???? 有读写请求时,如果cache不处于就????(IDLE)状�?�,或�?�未命中,则miss=1
main_mem #( // 主存,每次读写以line 为单???
main_mem #( // 主存,每次读写以line 为单????
.LINE_ADDR_LEN ( LINE_ADDR_LEN ),
.ADDR_LEN ( MEM_ADDR_LEN )
) main_mem_instance (
......
......@@ -21,7 +21,7 @@ reg [(ADDR_LEN + LINE_ADDR_LEN) - 1 : 0] mem_addr = 0;
reg [31:0] mem_wr_data = 0;
wire [31:0] mem_rd_data;
memMM #(
mem #(
.ADDR_LEN ( ADDR_LEN + LINE_ADDR_LEN )
) mem_inst (
.clk ( clk ),
......
No preview for this file type
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment