[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 "sram.svh"
|
||||
`include "ICache.svh"
|
||||
`include "AXI.svh"
|
||||
|
||||
module ICache (
|
||||
input clk,
|
||||
@ -148,7 +149,7 @@ module ICache (
|
||||
|
||||
// Next Status Generator:
|
||||
always_comb begin
|
||||
nextStatus = ICIdle; // avoid latch
|
||||
nextStatus = status; // avoid latch
|
||||
case (status)
|
||||
ICIdle: begin // -> IDLE or LOOKUP
|
||||
if (sram.req) nextStatus = ICLookup;
|
||||
|
@ -1,10 +1,9 @@
|
||||
`ifndef AXI_SVH
|
||||
`define AXI_SVH
|
||||
`include "constants.svh"
|
||||
|
||||
typedef struct packed {
|
||||
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 [2:0] arsize; // Burst size
|
||||
logic [1:0] arburst; // Burst type
|
||||
@ -19,13 +18,13 @@ typedef struct packed {
|
||||
typedef struct packed {
|
||||
logic arready; // Read address ready
|
||||
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 rlast; // Read last
|
||||
logic rvalid; // Read valid
|
||||
} AXIReadData_t; // slave
|
||||
|
||||
interface AXIRead;
|
||||
interface AXIRead_i;
|
||||
AXIReadAddr_t AXIReadAddr;
|
||||
AXIReadData_t AXIReadData;
|
||||
|
||||
@ -36,7 +35,7 @@ endinterface //AXIRead
|
||||
|
||||
typedef struct packed {
|
||||
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 [2:0] awsize; // Burst size
|
||||
logic [1:0] awburst; // Burst type
|
||||
@ -46,7 +45,7 @@ typedef struct packed {
|
||||
logic awvalid; // Write address valid
|
||||
|
||||
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 wlast; // Write last
|
||||
logic wvalid; // Write valid
|
||||
@ -63,7 +62,7 @@ typedef struct packed {
|
||||
logic bvalid; // Write response valid
|
||||
} AXIWriteData_t; // slave
|
||||
|
||||
interface AXIWrite;
|
||||
interface AXIWrite_i;
|
||||
AXIWriteAddr_t AXIWriteAddr;
|
||||
AXIWriteData_t AXIWriteData;
|
||||
|
||||
@ -71,4 +70,11 @@ interface AXIWrite;
|
||||
modport slave(input AXIWriteAddr, output AXIWriteData);
|
||||
endinterface //AXIWrite
|
||||
|
||||
typedef enum bit [2:0] {
|
||||
ASIdle,
|
||||
ASReadInst,
|
||||
ASReadData
|
||||
|
||||
} AXIStatus_t;
|
||||
|
||||
`endif
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
`include "ICache.svh"
|
||||
`include "sram.svh"
|
||||
`include "AXI.svh"
|
||||
|
||||
module happy ();
|
||||
logic clk, rst;
|
||||
@ -10,33 +11,30 @@ module happy ();
|
||||
integer counter = 0;
|
||||
/* verilator lint_on UNOPTFLAT */
|
||||
|
||||
integer i;
|
||||
|
||||
sramro_i fake ();
|
||||
AXIRead_i fakeAR ();
|
||||
AXIWrite_i fakeAW ();
|
||||
HandShake fakeHS ();
|
||||
|
||||
ICache ICache (
|
||||
.clk (clk),
|
||||
.rst (rst),
|
||||
.sram(fake.slave)
|
||||
.sram(fake.master)
|
||||
);
|
||||
|
||||
AXI AXI (
|
||||
.AXIRead(fakeAR.slave),
|
||||
.ICReq (fakeHS.prev),
|
||||
.ICResp (fakeHS.next)
|
||||
);
|
||||
|
||||
initial begin
|
||||
$dumpfile("test.vcd");
|
||||
$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.req = 1;
|
||||
fake.addr = 32'b0100000;
|
||||
end
|
||||
|
||||
integer i;
|
||||
always_latch begin
|
||||
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;
|
||||
|
||||
initial begin
|
||||
$dumpfile("logs/vlt_dump.vcd");
|
||||
$dumpvars();
|
||||
fake_sram.req = 1;
|
||||
fake_sram.addr = 32'b0100000;
|
||||
end
|
||||
|
||||
integer counter = 0;
|
||||
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
|
||||
counter = counter + 1;
|
||||
if (counter >= 16) $finish;
|
||||
|
Loading…
Reference in New Issue
Block a user