📄 leg_icache.v
字号:
/////////////////////////////////////////////////////////////////////
//// ////
//// LEG cpu core ////
//// ////
//// This file is part of the LEG FPGA SOC project ////
//// ////
//// ////
//// To Do: ////
//// - make it smaller and faster ////
//// - rewrite the register file and data path ////
//// Author(s): ////
//// - Alex Li, Alexli8055@hotmail.com ////
//// ////
/////////////////////////////////////////////////////////////////////
//// ////
//// Copyright (C) 2006-2007 Li datou ////
//// Alexli8055@hotmail.com ////
//// ////
//// ////
//// This source file may be used and distributed freely without ////
//// restriction provided that this copyright statement is not ////
//// removed from the file and any derivative work contains the ////
//// original copyright notice and the associated disclaimer. ////
//// ////
//// ARM, the ARM Powered logo, Thumb, and StrongARM are ////
//// registerd trademarks of ARM Limited, this core is simply ////
//// build for fun, please do not use for commerical propose ////
//// ////
//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY ////
//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED ////
//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ////
//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR ////
//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ////
//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ////
//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ////
//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR ////
//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF ////
//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ////
//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ////
//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ////
//// POSSIBILITY OF SUCH DAMAGE. ////
//// ////
/////////////////////////////////////////////////////////////////////
//// ////
//// Date of Creation: 2006.11.28 ////
//// ////
//// Version: 0.0.1 ////
//// ////
//// Description ////
//// leg core instruction cache module. ////
//// ////
//// ////
/////////////////////////////////////////////////////////////////////
//// ////
//// Change log: ////
//// ////
/////////////////////////////////////////////////////////////////////
`include "leg_define.v"
//very simple data cache, need to be refined further
module leg_icache(
//to cpu
i_address,
i_dataout,
i_read,
i_wait,
//to coprocessor
ic_control,
//to mem bus
ADR_O,
DAT_I,
STB_O,
CYC_O,
ACK_I,
SEL_O,
TGD_I,
TGD_O,
WE_O,
//system
clk,
rst
);
parameter IDLE = 4'b0001;
parameter HIT_DETECT = 4'b0010;
parameter RELOAD_1 = 4'b0100;
parameter RELOAD_2 = 4'b1000;
//total 4kB inst cache, implemented in 8 m4k
input [31:0] i_address;
output [31:0] i_dataout;
output i_wait;
input i_read;
input ic_control;
//wishbone master interface
output [31:0] ADR_O;
input [31:0] DAT_I; //system data bus is 32 bit
output [3:0] SEL_O;
output STB_O;
output CYC_O;
input ACK_I;
input [3:0] TGD_I; //DQM IN
output [3:0] TGD_O; //DQM OUT
output WE_O;
input clk;
input rst;
reg i_read_d;
reg [3:0] i_cache_state;
reg [31:0] i_addr_d;
//reg [8:0] i_mem_waddr;
wire i_tag_hit;
reg [1:0] send_counter;
reg [1:0] receive_counter;
reg mem_read;
wire receive_valid;
wire i_wait;
//
wire [09:0] i_cache_mem_raddr;
wire [31:0] i_cache_mem_rdata;
wire [09:0] i_cache_mem_waddr;
wire [31:0] i_cache_mem_wdata;
wire i_cache_mem_we;
wire [07:0] i_cache_tag_raddr;
wire [19:0] i_cache_tag_rdata;
wire [07:0] i_cache_tag_waddr;
wire [19:0] i_cache_tag_wdata;
wire i_cache_tag_we;
//total 4k i cache memory
//32 bit address
//31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
//---------------------tag field-----------------------------|--------tag addr--------|line addr|------
//hit or miss
assign i_tag_hit = (i_addr_d[31:12] == i_cache_tag_rdata) ? 1'b1 : 1'b0;
assign i_cache_mem_wdata = DAT_I;
assign i_cache_mem_waddr = {i_addr_d[11:04],receive_counter};
assign i_cache_mem_raddr = (i_cache_state == RELOAD_2)? i_addr_d[11:02] : i_address[11:02];
assign receive_valid = (TGD_I == 4'b1111)? 1'b1 : 1'b0;
assign i_cache_mem_we = receive_valid;
assign i_cache_tag_raddr = i_address[11:04];
assign i_cache_tag_waddr = i_addr_d[11:04];
assign i_cache_tag_we = (i_cache_state == RELOAD_1 && i_read_d)? 1'b1 : 1'b0;
assign i_cache_tag_wdata = i_addr_d[31:12];
//if the received data is the one that cpu need, foward to cpu directly
wire received_foward;
assign received_foward = (receive_valid && i_addr_d[03:02] == receive_counter) ? 1'b1 : 1'b0;
assign i_dataout = i_cache_mem_rdata;
//assign i_dataout = (received_foward)? DAT_I : i_cache_mem_rdata;
assign i_wait = ((i_tag_hit == 1'b0 && i_cache_state == HIT_DETECT) || i_cache_state == RELOAD_1 || i_cache_state == RELOAD_2) ? 1'b1 : 1'b0;
//assign i_wait = ((!i_tag_hit && i_cache_state == HIT_DETECT) || (i_cache_state == RELOAD_1 && !received_foward) || (i_cache_state == RELOAD_2 && !received_foward))? 1'b1 : 1'b0;
//wishbone if
assign ADR_O = {i_addr_d[31:04],send_counter,2'b00};
assign CYC_O = (i_cache_state == RELOAD_1)? 1'b1 : 1'b0;
assign STB_O = (i_cache_state == RELOAD_1)? 1'b1 : 1'b0;
assign SEL_O = 4'b1111; //i cache always expects a word from memory
assign WE_O = 1'b0; //always read ,no write operation
always@(posedge clk or posedge rst)
begin
if (rst) begin
i_read_d <= 1'h0;
end
else begin
if (!i_wait)
i_read_d <= i_read;
end
end
//keep the input address
always@(posedge clk or posedge rst)
begin
if (rst) begin
i_addr_d <= 32'h0;
end
else begin
if (!i_wait)
i_addr_d <= i_address;
end
end
//i cache fsm
always@(posedge clk or posedge rst)
begin
if (rst) begin
i_cache_state <= IDLE;
send_counter <= 2'b00;
receive_counter <= 2'b00;
mem_read <= 1'b0;
end
else begin
case(i_cache_state)
IDLE: begin
if (i_read) begin
i_cache_state <= HIT_DETECT;
end
end
HIT_DETECT: begin
if (!i_tag_hit && i_read_d) begin //hit miss
i_cache_state <= RELOAD_1;
mem_read <= 1'b1;
send_counter <= 2'b00;
receive_counter <= 2'b00;
end
end
RELOAD_1: begin
//send 4 memory request, burst
if (send_counter == 2'b11) begin
i_cache_state <= RELOAD_2;
mem_read <= 1'b0;
end
else
send_counter <= send_counter + 2'b01;
//get received data, if can
if (receive_valid)
receive_counter <= receive_counter + 2'b01;
end
RELOAD_2: begin
if (receive_counter == 2'b11) begin
i_cache_state <= HIT_DETECT;
send_counter <= 2'b00;
receive_counter <= 2'b00;
end
else if (receive_valid)
receive_counter <= receive_counter + 2'b01;
end
//other case
default: begin
i_cache_state <= IDLE;
send_counter <= 2'b00;
receive_counter <= 2'b00;
mem_read <= 1'b0;
end
endcase
end
end
//cache memory instance
leg_dpram_syn i_cache_mem(
.raddr(i_cache_mem_raddr),
.rdata(i_cache_mem_rdata),
.waddr(i_cache_mem_waddr),
.wdata(i_cache_mem_wdata),
.re(1'b1),
.we(i_cache_mem_we),
.clk(clk),
.rst(rst)
);
defparam i_cache_mem.AW = 10; //1024 WORD, TOTAL 4K BYTES, 8 m4k
defparam i_cache_mem.DW = 32; //32 bit inst
//cache tag instance
//no flag at this simple implementation
leg_dpram_syn i_cache_tag(
.raddr(i_cache_tag_raddr),
.rdata(i_cache_tag_rdata),
.waddr(i_cache_tag_waddr),
.wdata(i_cache_tag_wdata),
.re(1'b1),
.we(i_cache_tag_we),
.clk(clk),
.rst(rst)
);
defparam i_cache_tag.AW = 8; //256 WORD, TOTAL 512 ENTRY
defparam i_cache_tag.DW = 20; //20 bit, total 2 m4k
endmodule
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -