[AXI] ICache Read
This commit is contained in:
parent
2d3b15752c
commit
781a9bfc93
17
.vscode/c_cpp_properties.json
vendored
Normal file
17
.vscode/c_cpp_properties.json
vendored
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "Linux",
|
||||||
|
"includePath": [
|
||||||
|
"${workspaceFolder}/**",
|
||||||
|
"/usr/share/verilator/include"
|
||||||
|
],
|
||||||
|
"defines": [],
|
||||||
|
"compilerPath": "/usr/sbin/clang",
|
||||||
|
"cStandard": "c17",
|
||||||
|
"cppStandard": "c++14",
|
||||||
|
"intelliSenseMode": "linux-clang-x64"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"version": 4
|
||||||
|
}
|
178
src/AXI/AXI.sv
Normal file
178
src/AXI/AXI.sv
Normal file
@ -0,0 +1,178 @@
|
|||||||
|
`include "AXI.svh"
|
||||||
|
`include "defines.svh"
|
||||||
|
|
||||||
|
module AXI (
|
||||||
|
input logic clk,
|
||||||
|
input logic rst,
|
||||||
|
|
||||||
|
// AXI Read
|
||||||
|
AXIRead_i.master AXIRead,
|
||||||
|
|
||||||
|
// ICache
|
||||||
|
HandShake.prev ICReq,
|
||||||
|
input logic [31:0] ICacheAddress,
|
||||||
|
output logic ICacheLineOK, // ICache无条件接收
|
||||||
|
output logic [127:0] ICacheLine
|
||||||
|
|
||||||
|
// TODO: DCache
|
||||||
|
);
|
||||||
|
|
||||||
|
AXIStatus_t status, nextStatus;
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
status = ASIdle;
|
||||||
|
end
|
||||||
|
|
||||||
|
/*
|
||||||
|
----- ICache -----
|
||||||
|
ReadAddr:
|
||||||
|
- ID: Read 0
|
||||||
|
=> arid = 4'b0
|
||||||
|
- One transaction for a whole cache line -> 128bits
|
||||||
|
=> arlen = 4'b0011 -> 4*4bytes
|
||||||
|
=> arsize = 3'b010 -> 4bytes
|
||||||
|
=> arburst = 2'b10 -> WRAP (Cache line?)
|
||||||
|
- No AXI Cache
|
||||||
|
=> arcache = 4'b0000
|
||||||
|
- Protect: Instruction(1) Secure(0) Privileged(1)/Normal(0)
|
||||||
|
=> arport = 3'b10?
|
||||||
|
- Atomic: default
|
||||||
|
=> arlock = 2'b00
|
||||||
|
- Dynamic
|
||||||
|
=> araddr = read address
|
||||||
|
=> arvalid = address and control information valid
|
||||||
|
=> rready = master ready
|
||||||
|
ReadData:
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
logic [31:0] IReadAddr;
|
||||||
|
logic [ 1:0] IRespCounter;
|
||||||
|
logic IReadReqPending;
|
||||||
|
logic IReadAllowReq;
|
||||||
|
logic IReadRespOK;
|
||||||
|
logic [31:0] ICacheLineHelper[4];
|
||||||
|
|
||||||
|
assign ICReq.allowin = IReadAllowReq;
|
||||||
|
assign ICacheLineOK = IReadRespOK;
|
||||||
|
assign ICacheLine[31:0] = ICacheLineHelper[0];
|
||||||
|
assign ICacheLine[63:32] = ICacheLineHelper[1];
|
||||||
|
assign ICacheLine[95:64] = ICacheLineHelper[2];
|
||||||
|
assign ICacheLine[127:96] = ICacheLineHelper[3];
|
||||||
|
|
||||||
|
// icache burst read handler
|
||||||
|
always_ff @(posedge clk) begin
|
||||||
|
if (rst) IRespCounter <= 0;
|
||||||
|
else if (status == ASReadInst) begin
|
||||||
|
if (AXIRead.AXIReadData.rvalid) begin
|
||||||
|
// TODO: 这里忽略了rid + rresp校验, 希望不要出错 :)
|
||||||
|
ICacheLineHelper[IRespCounter] <= AXIRead.AXIReadData.rdata;
|
||||||
|
IRespCounter <= IRespCounter + 1;
|
||||||
|
end
|
||||||
|
end else IRespCounter <= 0; // avoid latch -> reset zero when not used
|
||||||
|
end
|
||||||
|
|
||||||
|
// read status switch
|
||||||
|
always_comb begin
|
||||||
|
IReadAddr = 32'b0;
|
||||||
|
IReadReqPending = 0'b0;
|
||||||
|
nextStatus = status;
|
||||||
|
|
||||||
|
case (status)
|
||||||
|
|
||||||
|
// 处理读请求
|
||||||
|
ASIdle: begin
|
||||||
|
// TODO DCache仲裁
|
||||||
|
|
||||||
|
// ICache读请求
|
||||||
|
if (ICReq.readygo & ICReq.allowin) begin
|
||||||
|
// wrap to the beginning of the cache line
|
||||||
|
IReadAddr = ICacheAddress & 32'hFFFF_FFF0; // recored read addr
|
||||||
|
IReadReqPending = 1'b1;
|
||||||
|
nextStatus = ASReadInst;
|
||||||
|
end else nextStatus = ASIdle; // 没有请求
|
||||||
|
end
|
||||||
|
|
||||||
|
// 处理ICache读过程
|
||||||
|
ASReadInst: begin
|
||||||
|
if (IReadRespOK) begin
|
||||||
|
// 不和ICache握手, 直接返回
|
||||||
|
nextStatus = ASIdle;
|
||||||
|
IReadReqPending = 1'b0;
|
||||||
|
end else nextStatus = ASReadInst; // 没有读完
|
||||||
|
end
|
||||||
|
|
||||||
|
default: begin
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
|
||||||
|
// next status
|
||||||
|
always_ff @(posedge clk) begin
|
||||||
|
status <= nextStatus;
|
||||||
|
end
|
||||||
|
|
||||||
|
// AXI read control + ICache handshake
|
||||||
|
always_comb begin
|
||||||
|
// 八成不会动的东西
|
||||||
|
AXIRead.AXIReadAddr.arcache = 4'b0;
|
||||||
|
AXIRead.AXIReadAddr.arlock = 2'b0;
|
||||||
|
|
||||||
|
// TODO 是否严格处理DCache按字寻址处理
|
||||||
|
AXIRead.AXIReadAddr.arlen = 4'b0011;
|
||||||
|
AXIRead.AXIReadAddr.arsize = 3'b010;
|
||||||
|
AXIRead.AXIReadAddr.arburst = 2'b10;
|
||||||
|
|
||||||
|
// 据情况修改的东西
|
||||||
|
AXIRead.AXIReadAddr.arid = 4'b0; // ICache(0) DCache(1)
|
||||||
|
AXIRead.AXIReadAddr.arport = 3'b101; // ICache(101) DCache(001)
|
||||||
|
AXIRead.AXIReadAddr.araddr = 32'b0;
|
||||||
|
AXIRead.AXIReadAddr.arvalid = 1'b0;
|
||||||
|
AXIRead.AXIReadAddr.rready = 1'b0;
|
||||||
|
|
||||||
|
// 状态量
|
||||||
|
IReadRespOK = 1'b0; // ICache 读返回默认无效
|
||||||
|
|
||||||
|
case (status)
|
||||||
|
// 处理读请求
|
||||||
|
ASIdle: begin // TODO: 处理 DCache读请求 + 写请求仲裁
|
||||||
|
if (IReadReqPending) begin
|
||||||
|
// ICache 读请求
|
||||||
|
if (AXIRead.AXIReadData.arready) begin // TODO: slave 准备好是否提取到外层?
|
||||||
|
AXIRead.AXIReadAddr.arid = 4'b0;
|
||||||
|
AXIRead.AXIReadAddr.arport = 3'b101;
|
||||||
|
AXIRead.AXIReadAddr.araddr = IReadAddr;
|
||||||
|
AXIRead.AXIReadAddr.arvalid = 1'b1;
|
||||||
|
AXIRead.AXIReadAddr.rready = 1'b1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
// 处理ICache读请求
|
||||||
|
ASReadInst: begin
|
||||||
|
// (ICache 读逻辑单独实现 -> 独立的counter逻辑)
|
||||||
|
if (AXIRead.AXIReadData.rlast) begin
|
||||||
|
// TODO: 是否有必要检查 rvalid
|
||||||
|
IReadRespOK = 1'b1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
// 处理DCache读请求
|
||||||
|
ASReadData: begin
|
||||||
|
// TODO
|
||||||
|
end
|
||||||
|
|
||||||
|
// TODO: latch killer :)
|
||||||
|
default: begin
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
endmodule
|
@ -1,6 +1,7 @@
|
|||||||
`include "defines.svh"
|
`include "defines.svh"
|
||||||
`include "sram.svh"
|
`include "sram.svh"
|
||||||
`include "ICache.svh"
|
`include "ICache.svh"
|
||||||
|
`include "AXI.svh"
|
||||||
|
|
||||||
module ICache (
|
module ICache (
|
||||||
input clk,
|
input clk,
|
||||||
@ -148,7 +149,7 @@ module ICache (
|
|||||||
|
|
||||||
// Next Status Generator:
|
// Next Status Generator:
|
||||||
always_comb begin
|
always_comb begin
|
||||||
nextStatus = ICIdle; // avoid latch
|
nextStatus = status; // avoid latch
|
||||||
case (status)
|
case (status)
|
||||||
ICIdle: begin // -> IDLE or LOOKUP
|
ICIdle: begin // -> IDLE or LOOKUP
|
||||||
if (sram.req) nextStatus = ICLookup;
|
if (sram.req) nextStatus = ICLookup;
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
`ifndef AXI_SVH
|
`ifndef AXI_SVH
|
||||||
`define AXI_SVH
|
`define AXI_SVH
|
||||||
`include "constants.svh"
|
|
||||||
|
|
||||||
typedef struct packed {
|
typedef struct packed {
|
||||||
logic [3:0] arid; // Read address ID
|
logic [3:0] arid; // Read address ID
|
||||||
logic [`WIDTH-1:0] araddr; // Read address
|
logic [31:0] araddr; // Read address
|
||||||
logic [3:0] arlen; // Burst length
|
logic [3:0] arlen; // Burst length
|
||||||
logic [2:0] arsize; // Burst size
|
logic [2:0] arsize; // Burst size
|
||||||
logic [1:0] arburst; // Burst type
|
logic [1:0] arburst; // Burst type
|
||||||
@ -19,13 +18,13 @@ typedef struct packed {
|
|||||||
typedef struct packed {
|
typedef struct packed {
|
||||||
logic arready; // Read address ready
|
logic arready; // Read address ready
|
||||||
logic [3:0] rid; // Read ID tag
|
logic [3:0] rid; // Read ID tag
|
||||||
logic [`WIDTH-1:0] rdata; // Read data
|
logic [31:0] rdata; // Read data
|
||||||
logic [1:0] rresp; // Read response
|
logic [1:0] rresp; // Read response
|
||||||
logic rlast; // Read last
|
logic rlast; // Read last
|
||||||
logic rvalid; // Read valid
|
logic rvalid; // Read valid
|
||||||
} AXIReadData_t; // slave
|
} AXIReadData_t; // slave
|
||||||
|
|
||||||
interface AXIRead;
|
interface AXIRead_i;
|
||||||
AXIReadAddr_t AXIReadAddr;
|
AXIReadAddr_t AXIReadAddr;
|
||||||
AXIReadData_t AXIReadData;
|
AXIReadData_t AXIReadData;
|
||||||
|
|
||||||
@ -36,7 +35,7 @@ endinterface //AXIRead
|
|||||||
|
|
||||||
typedef struct packed {
|
typedef struct packed {
|
||||||
logic [3:0] awid; // Write address ID
|
logic [3:0] awid; // Write address ID
|
||||||
logic [`WIDTH-1:0] awaddr; // Write address
|
logic [31:0] awaddr; // Write address
|
||||||
logic [3:0] awlen; // Burst length
|
logic [3:0] awlen; // Burst length
|
||||||
logic [2:0] awsize; // Burst size
|
logic [2:0] awsize; // Burst size
|
||||||
logic [1:0] awburst; // Burst type
|
logic [1:0] awburst; // Burst type
|
||||||
@ -46,7 +45,7 @@ typedef struct packed {
|
|||||||
logic awvalid; // Write address valid
|
logic awvalid; // Write address valid
|
||||||
|
|
||||||
logic [3:0] wid; // Write ID tag
|
logic [3:0] wid; // Write ID tag
|
||||||
logic [`WIDTH-1:0] wdata; // Write data
|
logic [31:0] wdata; // Write data
|
||||||
logic [3:0] wstrb; // Write strobes
|
logic [3:0] wstrb; // Write strobes
|
||||||
logic wlast; // Write last
|
logic wlast; // Write last
|
||||||
logic wvalid; // Write valid
|
logic wvalid; // Write valid
|
||||||
@ -63,7 +62,7 @@ typedef struct packed {
|
|||||||
logic bvalid; // Write response valid
|
logic bvalid; // Write response valid
|
||||||
} AXIWriteData_t; // slave
|
} AXIWriteData_t; // slave
|
||||||
|
|
||||||
interface AXIWrite;
|
interface AXIWrite_i;
|
||||||
AXIWriteAddr_t AXIWriteAddr;
|
AXIWriteAddr_t AXIWriteAddr;
|
||||||
AXIWriteData_t AXIWriteData;
|
AXIWriteData_t AXIWriteData;
|
||||||
|
|
||||||
@ -71,4 +70,11 @@ interface AXIWrite;
|
|||||||
modport slave(input AXIWriteAddr, output AXIWriteData);
|
modport slave(input AXIWriteAddr, output AXIWriteData);
|
||||||
endinterface //AXIWrite
|
endinterface //AXIWrite
|
||||||
|
|
||||||
|
typedef enum bit [2:0] {
|
||||||
|
ASIdle,
|
||||||
|
ASReadInst,
|
||||||
|
ASReadData
|
||||||
|
|
||||||
|
} AXIStatus_t;
|
||||||
|
|
||||||
`endif
|
`endif
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
`include "ICache.svh"
|
`include "ICache.svh"
|
||||||
`include "sram.svh"
|
`include "sram.svh"
|
||||||
|
`include "AXI.svh"
|
||||||
|
|
||||||
module happy ();
|
module happy ();
|
||||||
logic clk, rst;
|
logic clk, rst;
|
||||||
@ -10,33 +11,30 @@ module happy ();
|
|||||||
integer counter = 0;
|
integer counter = 0;
|
||||||
/* verilator lint_on UNOPTFLAT */
|
/* verilator lint_on UNOPTFLAT */
|
||||||
|
|
||||||
integer i;
|
|
||||||
|
|
||||||
sramro_i fake ();
|
sramro_i fake ();
|
||||||
|
AXIRead_i fakeAR ();
|
||||||
|
AXIWrite_i fakeAW ();
|
||||||
|
HandShake fakeHS ();
|
||||||
|
|
||||||
ICache ICache (
|
ICache ICache (
|
||||||
.clk (clk),
|
.clk (clk),
|
||||||
.rst (rst),
|
.rst (rst),
|
||||||
.sram(fake.slave)
|
.sram(fake.master)
|
||||||
|
);
|
||||||
|
|
||||||
|
AXI AXI (
|
||||||
|
.AXIRead(fakeAR.slave),
|
||||||
|
.ICReq (fakeHS.prev),
|
||||||
|
.ICResp (fakeHS.next)
|
||||||
);
|
);
|
||||||
|
|
||||||
initial begin
|
initial begin
|
||||||
$dumpfile("test.vcd");
|
fake.req = 1;
|
||||||
$dumpvars(0, testbench);
|
|
||||||
|
|
||||||
$dumpvars(1, fake.req);
|
|
||||||
$dumpvars(1, fake.addr);
|
|
||||||
$dumpvars(1, fake.addr_ok);
|
|
||||||
$dumpvars(1, fake.data_ok);
|
|
||||||
$dumpvars(1, fake.rdata0);
|
|
||||||
$dumpvars(1, fake.rdata1);
|
|
||||||
|
|
||||||
rst = 0;
|
|
||||||
clk = 1;
|
|
||||||
|
|
||||||
fake.req = 1;
|
|
||||||
fake.addr = 32'b0100000;
|
fake.addr = 32'b0100000;
|
||||||
end
|
end
|
||||||
|
|
||||||
|
integer i;
|
||||||
always_latch begin
|
always_latch begin
|
||||||
clk = ~clk;
|
clk = ~clk;
|
||||||
|
|
||||||
|
@ -1,3 +1,13 @@
|
|||||||
verilator -I/home/paul/loongson/MIPS/src/AXI/ -I/home/paul/loongson/MIPS/src/Cache/ -I/home/paul/loongson/MIPS/src/Core/ -I/home/paul/loongson/MIPS/src/CP0/ -I/home/paul/loongson/MIPS/src/include/ -I/home/paul/loongson/MIPS/src/testbench/happy/ +1800-2017ext+sv --cc --exe --build sim_main.cpp testbench.sv
|
verilator -I/home/paul/loongson/MIPS/src/AXI/ \
|
||||||
|
-I/home/paul/loongson/MIPS/src/Cache/ \
|
||||||
|
-I/home/paul/loongson/MIPS/src/Core/ \
|
||||||
|
-I/home/paul/loongson/MIPS/src/CP0/ \
|
||||||
|
-I/home/paul/loongson/MIPS/src/include/ \
|
||||||
|
-I/home/paul/loongson/MIPS/src/testbench/happy/ \
|
||||||
|
+1800-2017ext+sv \
|
||||||
|
--cc --trace --exe --build \
|
||||||
|
sim_main.cpp testbench.sv
|
||||||
|
|
||||||
./obj_dir/Vtestbench
|
./obj_dir/Vtestbench +trace
|
||||||
|
|
||||||
|
gtkwave ./logs/vlt_dump.vcd
|
||||||
|
@ -27,13 +27,15 @@ module testbench (
|
|||||||
assign rdata1 = fake_sram.rdata1;
|
assign rdata1 = fake_sram.rdata1;
|
||||||
|
|
||||||
initial begin
|
initial begin
|
||||||
|
$dumpfile("logs/vlt_dump.vcd");
|
||||||
|
$dumpvars();
|
||||||
fake_sram.req = 1;
|
fake_sram.req = 1;
|
||||||
fake_sram.addr = 32'b0100000;
|
fake_sram.addr = 32'b0100000;
|
||||||
end
|
end
|
||||||
|
|
||||||
integer counter = 0;
|
integer counter = 0;
|
||||||
always_ff @(posedge clk) begin
|
always_ff @(posedge clk) begin
|
||||||
fake_sram.addr = fake_sram.addr + 1;
|
if (fake_sram.data_ok) fake_sram.addr = fake_sram.addr + 1;
|
||||||
if (clk == 1'b1) begin
|
if (clk == 1'b1) begin
|
||||||
counter = counter + 1;
|
counter = counter + 1;
|
||||||
if (counter >= 16) $finish;
|
if (counter >= 16) $finish;
|
||||||
|
Loading…
Reference in New Issue
Block a user