[Modified] Switch soc_top&board to axi&xc7a200t

This commit is contained in:
2023-07-20 21:40:21 +08:00
parent 104518d875
commit a755aae99e
43 changed files with 5798 additions and 105625 deletions

99
lacpu/rtl/mycpu/alu.v Normal file
View File

@@ -0,0 +1,99 @@
module alu(
input [11:0] alu_op ,
input [31:0] alu_src1 ,
input [31:0] alu_src2 ,
output [31:0] alu_result
);
wire op_add;
wire op_sub;
wire op_lui;
wire op_slt;
wire op_sltu;
wire op_and;
wire op_or;
wire op_nor;
wire op_xor;
wire op_sll;
wire op_srl;
wire op_sra;
assign op_add = alu_op[ 0];
assign op_sub = alu_op[ 1];
assign op_slt = alu_op[ 2];
assign op_sltu = alu_op[ 3];
assign op_and = alu_op[ 4];
assign op_nor = alu_op[ 5];
assign op_or = alu_op[ 6];
assign op_xor = alu_op[ 7];
assign op_sll = alu_op[ 8];
assign op_srl = alu_op[ 9];
assign op_sra = alu_op[10];
assign op_lui = alu_op[11];
wire [31:0] add_sub_result;
wire [31:0] slt_result;
wire [31:0] sltu_result;
wire [31:0] and_result;
wire [31:0] nor_result;
wire [31:0] or_result;
wire [31:0] xor_result;
wire [31:0] lui_result;
wire [31:0] sll_result;
wire [63:0] sr64_result;
wire [31:0] sr_result;
// 32-bit adder
wire [31:0] adder_a;
wire [31:0] adder_b;
wire adder_cin;
wire [31:0] adder_result;
wire adder_cout;
assign adder_a = alu_src1;
assign adder_b = (op_sub | op_slt | op_sltu) ? ~alu_src2 : alu_src2;
assign adder_cin = (op_sub | op_slt | op_sltu) ? 1'b1 : 1'b0;
assign {adder_cout, adder_result} = adder_a + adder_b + adder_cin;
// ADD, SUB result
assign add_sub_result = adder_result;
// SLT result
assign slt_result[31:1] = 31'b0;
assign slt_result[0] = (alu_src1[31] & ~alu_src2[31])
| ((alu_src1[31] ~^ alu_src2[31]) & adder_result[31]);
// SLTU result
assign sltu_result[31:1] = 31'b0;
assign sltu_result[0] = ~adder_cout;
// bitwise operation
assign and_result = alu_src1 & alu_src2;
assign or_result = alu_src1 | alu_src2;
assign nor_result = ~or_result;
assign xor_result = alu_src1 ^ alu_src2;
assign lui_result = alu_src2;
// SLL result
assign sll_result = alu_src1 << alu_src2[4:0];
// SRL, SRA result
assign sr64_result = {{32{op_sra & alu_src1[31]}}, alu_src1[31:0]} >> alu_src2[4:0];
assign sr_result = sr64_result[31:0];
// final result mux
assign alu_result = ({32{op_add|op_sub}} & add_sub_result)
| ({32{op_slt }} & slt_result)
| ({32{op_sltu }} & sltu_result)
| ({32{op_and }} & and_result)
| ({32{op_nor }} & nor_result)
| ({32{op_or }} & or_result)
| ({32{op_xor }} & xor_result)
| ({32{op_lui }} & lui_result)
| ({32{op_sll }} & sll_result)
| ({32{op_srl|op_sra}} & sr_result);
endmodule

428
lacpu/rtl/mycpu/axi_ctrl.v Normal file
View File

@@ -0,0 +1,428 @@
`default_nettype wire
module axi_ctrl_v5
#(
parameter TAG_WD = 21,
parameter INDEX_WD = 64,
parameter CACHELINE_WD = 512,
parameter STAGE_WD = 12
)
(
input clk,
input reset,
// icache interface
input icache_re, // miss
input [31 :0] icache_raddr, // miss_addr
output reg [CACHELINE_WD -1:0] icache_cacheline_new,
input icache_we, // we_back
input [31 :0] icache_waddr, // waddr
input [CACHELINE_WD -1:0] icache_cacheline_old, // wback
output reg icache_refresh,
// dcache interface
input dcache_re, // miss
input [31 :0] dcache_raddr, // miss_addr
output reg [CACHELINE_WD -1:0] dcache_cacheline_new,
input dcache_we, // we_back
input [31 :0] dcache_waddr, // waddr
input [CACHELINE_WD -1:0] dcache_cacheline_old, // wback
output reg dcache_refresh, // fin
// uncache interface
input uncache_en,
input [3 :0] uncache_we,
input [31 :0] uncache_addr,
input [31 :0] uncache_wdata,
output reg [31 :0] uncache_rdata,
output reg uncache_refresh,
//总线侧接口
//读地址通道信号
output reg [3 :0] arid, //读地址ID用来标志一组写信号
output reg [31:0] araddr, //读地址给出一次写突发传输的读地址
output reg [3 :0] arlen, //突发长度给出突发传输的次数
output reg [2 :0] arsize, //突发大小给出每次突发传输的字节数
output reg [1 :0] arburst, //突发类型
output reg [1 :0] arlock, //总线锁信号可提供操作的原子性
output reg [3 :0] arcache, //内存类型表明一次传输是怎样通过系统的
output reg [2 :0] arprot, //保护类型表明一次传输的特权级及安全等级
output reg arvalid, //有效信号表明此通道的地址控制信号有效
input arready, //表明""可以接收地址和对应的控制信号
//读数据通道信号
input [3 :0] rid, //读ID tag
input [31:0] rdata, //读数据
input [1 :0] rresp, //读响应表明读传输的状态
input rlast, //表明读突发的最后一次传输
input rvalid, //表明此通道信号有效
output reg rready, //表明主机能够接收读数据和响应信息
//写地址通道信号
output reg [3 :0] awid, //写地址ID用来标志一组写信号
output reg [31:0] awaddr, //写地址给出一次写突发传输的写地址
output reg [3 :0] awlen, //突发长度给出突发传输的次数
output reg [2 :0] awsize, //突发大小给出每次突发传输的字节数
output reg [1 :0] awburst, //突发类型
output reg [1 :0] awlock, //总线锁信号可提供操作的原子性
output reg [3 :0] awcache, //内存类型表明一次传输是怎样通过系统的
output reg [2 :0] awprot, //保护类型表明一次传输的特权级及安全等级
output reg awvalid, //有效信号表明此通道的地址控制信号有效
input awready, //表明""可以接收地址和对应的控制信号
//写数据通道信号
output reg [3 :0] wid, //一次写传输的ID tag
output reg [31:0] wdata, //写数据
output reg [3 :0] wstrb, //写数据有效的字节线用来表明哪8bits数据是有效的
output reg wlast, //表明此次传输是最后一个突发传输
output reg wvalid, //写有效表明此次写有效
input wready, //表明从机可以接收写数据
//写响应通道信号
input [3 :0] bid, //写响应ID tag
input [1 :0] bresp, //写响应表明写传输的状态 00为正常当然可以不理会
input bvalid, //写响应有效
output reg bready //表明主机能够接收写响应
);
reg [CACHELINE_WD -1:0] icache_rdata_buffer;
reg [CACHELINE_WD -1:0] icache_wdata_buffer;
reg [CACHELINE_WD -1:0] dcache_rdata_buffer;
reg [CACHELINE_WD -1:0] dcache_wdata_buffer;
reg [31 :0] icache_raddr_buffer;
reg [31 :0] icache_waddr_buffer;
reg [31 :0] dcache_raddr_buffer;
reg [31 :0] dcache_waddr_buffer;
reg [3 :0] icache_offset;
reg [3 :0] dcache_offset;
reg [3 :0] dcache_offset_w;
reg icache_re_buffer;
reg dcache_re_buffer;
reg icache_we_buffer;
reg dcache_we_buffer;
reg uncache_en_buffer;
reg [3 :0] uncache_we_buffer;
reg [31 :0] uncache_addr_buffer;
reg [31 :0] uncache_wdata_buffer;
reg [31 :0] uncache_rdata_buffer;
reg [STAGE_WD -1:0] stage;
reg [STAGE_WD -1:0] stage_w;
always @(posedge clk) begin
if(reset) begin
arid <= 4'b0000;
araddr <= 32'b0;
arlen <= 4'b0000;
arsize <= 3'b010;
arburst <= 2'b01;
arlock <= 2'b00;
arcache <= 4'b0000;
arprot <= 3'b000;
arvalid <= 1'b0;
rready <= 1'b0;
stage <= {{(STAGE_WD-1){1'b0}}, 1'b1};
icache_refresh <= 0;
dcache_refresh <= 0;
icache_cacheline_new <= 0;
dcache_cacheline_new <= 0;
uncache_refresh <= 1'b0;
uncache_rdata <= 32'b0;
end
else begin
case (1'b1)
stage[0]: begin
icache_refresh <= 1'b0;
dcache_refresh <= 1'b0;
uncache_refresh <= 1'b0;
icache_re_buffer <= icache_re;
icache_raddr_buffer <= icache_raddr;
icache_we_buffer <= icache_we;
icache_waddr_buffer <= icache_waddr;
dcache_re_buffer <= dcache_re;
dcache_raddr_buffer <= dcache_raddr;
dcache_we_buffer <= dcache_we;
dcache_waddr_buffer <= dcache_waddr;
uncache_en_buffer <= uncache_en;
uncache_we_buffer <= uncache_we;
uncache_addr_buffer <= uncache_addr;
uncache_wdata_buffer <= uncache_wdata;
if (dcache_we|(uncache_en&((|uncache_we)))) begin
stage <= stage << 1;
end
else if (icache_re|dcache_re|(uncache_en&~(|uncache_we))) begin
stage <= stage << 2;
end
end
stage[1]: begin
icache_wdata_buffer <= icache_cacheline_old;
dcache_wdata_buffer <= dcache_cacheline_old;
if (icache_re_buffer|dcache_re_buffer|(uncache_en_buffer&~(|uncache_we_buffer))) begin
stage <= stage << 1;
end
else begin
stage <= {1'b0,1'b1,10'b0};
end
end
stage[2]:begin
if (icache_re_buffer) begin
arid <= 4'b0;
araddr <= icache_raddr_buffer;
arlen <= 4'hf;
arsize <= 3'b010;
arvalid <= 1'b1;
stage <= stage << 1;
end
else begin
stage <= stage << 3;
end
end
stage[3]:begin
if (arready) begin
arvalid <= 1'b0;
araddr <= 32'b0;
rready <= 1'b1;
icache_offset <= 4'd0;
stage <= stage << 1;
end
end
stage[4]:begin
if (!rlast&rvalid) begin
icache_rdata_buffer[icache_offset*32+:32] <= rdata;
icache_offset <= icache_offset + 1'b1;
end
else if(rlast&rvalid) begin
icache_rdata_buffer[icache_offset*32+:32] <= rdata;
rready <= 1'b0;
stage <= stage << 1;
end
end
stage[5]:begin
if (dcache_re_buffer) begin
arid <= 4'b1;
araddr <= dcache_raddr_buffer;
arlen <= 4'hf;
arsize <= 3'b010;
arvalid <= 1'b1;
stage <= stage << 1;
end
else if (uncache_en_buffer&~(|uncache_we_buffer)) begin
arid <= 4'b1;
araddr <= uncache_addr_buffer;
arlen <= 4'b0;
arsize <= 3'b010;
arvalid <= 1'b1;
stage <= stage << 3;
end
else begin
stage <= {1'b0,1'b1,10'b0};
end
end
stage[6]:begin
if (arready) begin
arvalid <= 1'b0;
araddr <= 32'b0;
rready <= 1'b1;
dcache_offset <= 4'd0;
stage <= stage << 1;
end
end
stage[7]:begin
if (!rlast&rvalid) begin
dcache_rdata_buffer[dcache_offset*32+:32] <= rdata;
dcache_offset <= dcache_offset + 1'b1;
end
else if (rlast&rvalid) begin
dcache_rdata_buffer[dcache_offset*32+:32] <= rdata;
rready <= 1'b0;
stage <= {1'b0,1'b1,10'b0};
end
end
stage[8]:begin
if (arready) begin
arvalid <= 1'b0;
araddr <= 32'b0;
rready <= 1'b1;
stage <= stage << 1;
end
end
stage[9]:begin
if (rvalid) begin
uncache_rdata_buffer <= rdata;
rready <= 1'b0;
stage <= {1'b0,1'b1,10'b0};
end
end
stage[10]:begin
if (stage_w[10]|stage_w[0]) begin
stage <= stage << 1;
end
end
stage[11]:begin
if (icache_re_buffer) begin
icache_refresh <= 1'b1;
icache_cacheline_new <= icache_rdata_buffer;
end
if (dcache_re_buffer) begin
dcache_refresh <= 1'b1;
dcache_cacheline_new <= dcache_rdata_buffer;
end
if (uncache_en_buffer) begin
uncache_refresh <= 1'b1;
uncache_rdata <= uncache_rdata_buffer;
end
stage <= 0;
end
default:begin
stage <= {{(STAGE_WD-1){1'b0}}, 1'b1};
icache_refresh <= 1'b0;
dcache_refresh <= 1'b0;
uncache_refresh <= 1'b0;
end
endcase
end
end
always @ (posedge clk) begin
if (reset) begin
awid <= 4'b0001;
awaddr <= 32'b0;
awlen <= 4'b0000;
awsize <= 3'b010;
awburst <= 2'b01;
awlock <= 2'b00;
awcache <= 4'b0000;
awprot <= 3'b000;
awvalid <= 1'b0;
wid <= 4'b0001;
wdata <= 32'b0;
wstrb <= 4'b0000;
wlast <= 1'b0;
wvalid <= 1'b0;
bready <= 1'b0;
stage_w <= {{(STAGE_WD-1){1'b0}}, 1'b1};
end
else begin
case (1'b1)
stage_w[0]:begin
if (stage[1]) begin
if (dcache_we_buffer) begin
awid <= 4'b1;
awaddr <= dcache_waddr_buffer;
awlen <= 4'hf;
awsize <= 3'b010;
awvalid <= 1'b1;
wstrb <= 4'b1111;
wlast <= 1'b0;
bready <= 1'b1;
dcache_offset_w <= 4'b0;
stage_w <= stage_w << 1;
end
else if (|uncache_we_buffer) begin // write
awid <= 4'b1;
awaddr <= uncache_addr_buffer;
awlen <= 4'b0;
case (uncache_we_buffer)
4'b0001,4'b0010,4'b0100,4'b1000:begin
awsize <= 3'b000;
wstrb <= uncache_we_buffer;
end
4'b0011,4'b1100:begin
awsize <= 3'b001;
wstrb <= uncache_we_buffer;
end
4'b1111:begin
awsize <= 3'b010;
wstrb <= uncache_we_buffer;
end
default:begin
awsize <= 3'b010;
wstrb <= uncache_we_buffer;
end
endcase
awvalid <= 1'b1;
wlast <= 1'b0;
bready <= 1'b1;
stage_w <= stage_w << 4;
end
end
end
stage_w[1]:begin
if (awready) begin
awvalid <= 1'b0;
awaddr <= 32'b0;
wdata <= dcache_wdata_buffer[dcache_offset_w*32+:32];
wvalid <= 1'b1;
wlast <= dcache_offset_w == 4'b1111 ? 1'b1 : 1'b0;
dcache_offset_w <= dcache_offset_w + 1'b1;
if (dcache_offset_w == 4'b1111) begin
stage_w <= stage_w << 1;
end
end
end
stage_w[2]:begin
if (wready) begin
wdata <= 32'b0;
wvalid <= 1'b0;
wlast <= 1'b0;
stage_w <= stage_w << 1;
end
end
stage_w[3]:begin
if (bvalid) begin
bready <= 1'b0;
stage_w <= {1'b0,1'b1,{10{1'b0}}};
end
end
stage_w[4]:begin
if (awready) begin
awvalid <= 1'b0;
awaddr <= 32'b0;
wdata <= uncache_wdata_buffer;
wvalid <= 1'b1;
wlast <= 1'b1;
stage_w <= stage_w << 1;
end
end
stage_w[5]:begin
if (wready) begin
wdata <= 32'b0;
wvalid <= 1'b0;
wlast <= 1'b0;
stage_w <= stage_w << 1;
end
end
stage_w[6]:begin
if (bvalid) begin
bready <= 1'b0;
stage_w <= {1'b0,1'b1,{10{1'b0}}};
end
end
stage_w[10]:begin
if (stage[11]) begin
stage_w <= {{(STAGE_WD-1){1'b0}}, 1'b1};
end
end
default:begin
stage_w <= {{(STAGE_WD-1){1'b0}}, 1'b1};
end
endcase
end
end
endmodule

56
lacpu/rtl/mycpu/bru.v Normal file
View File

@@ -0,0 +1,56 @@
module bru(
input [31:0] pc,
input [31:0] rj_value,
input [31:0] rkd_value,
input [31:0] imm,
input [ 8:0] branch_op,
output br_taken,
output [31:0] br_target
);
wire inst_jirl;
wire inst_b;
wire inst_bl;
wire inst_beq;
wire inst_bne;
wire inst_blt;
wire inst_bge;
wire inst_bltu;
wire inst_bgeu;
wire rj_eq_rd;
wire rj_lt_rd;
wire rj_ltu_rd;
assign {inst_beq,
inst_bne,
inst_blt,
inst_bge,
inst_bltu,
inst_bgeu,
inst_jirl,
inst_bl,
inst_b
} = branch_op;
assign rj_eq_rd = (rj_value == rkd_value);
assign rj_ltu_rd = (rj_value < rkd_value);
assign rj_lt_rd = (rj_value[31] && ~rkd_value[31]) ? 1'b1 :
(~rj_value[31] && rkd_value[31]) ? 1'b0 :
rj_ltu_rd;
assign br_taken = ( inst_beq && rj_eq_rd
|| inst_bne && !rj_eq_rd
|| inst_blt && rj_lt_rd
|| inst_bge && !rj_lt_rd
|| inst_bltu && rj_ltu_rd
|| inst_bgeu && !rj_ltu_rd
|| inst_jirl
|| inst_bl
|| inst_b
);
assign br_target = ({32{inst_beq|inst_bne|inst_bl|inst_b|inst_blt|inst_bge|inst_bltu|inst_bgeu}} & (pc + imm))
| ({32{inst_jirl}} & (rj_value + imm));
endmodule

View File

@@ -0,0 +1,792 @@
`default_nettype wire
module cache_data_v5
#(
parameter CACHELINE_WD = 512,
parameter TAG_WD = 21,
parameter HIT_WD = 2
)
(
input clk,
input reset,
input write_back,
input [ 1:0] hit,
input lru,
input cached,
// sram_port
input sram_en,
input [ 3:0] sram_we,
input [31:0] sram_addr,
input [31:0] sram_wdata,
output [31:0] sram_rdata,
input refresh,
input [CACHELINE_WD -1:0] cacheline_new,
output [CACHELINE_WD -1:0] cacheline_old
);
wire [31 :0] rdata_way0 [15:0];
wire [31 :0] rdata_way1 [15:0];
wire [TAG_WD -2:0] tag;
wire [5 :0] index;
wire [5 :0] offset;
reg [HIT_WD -1:0] hit_r;
reg lru_r;
reg cached_r;
assign {tag,
index,
offset
} = sram_addr;
wire [15:0] bank_sel;
reg [15:0] bank_sel_r;
decoder_4_16 u_decoder_4_16(
.in (offset[5:2] ),
.out (bank_sel )
);
always @ (posedge clk) begin
if (reset) begin
hit_r <= 2'b0;
lru_r <= 1'b0;
cached_r <= 1'b1;
bank_sel_r <= 16'b0;
end
else begin
hit_r <= hit;
lru_r <= lru;
cached_r <= cached;
bank_sel_r <= bank_sel;
end
end
// data_bram_way0 begin
data_bram_bank bank0_way0(
.clka (clk ),
.ena (cached&refresh|sram_en&bank_sel[0]&hit[0]|write_back ), // 1
.wea (refresh?lru?4'b0000:4'b1111:write_back?4'b0000:sram_we), // 4
.addra (index ), // 7
.dina (refresh?cacheline_new[31:0]:sram_wdata ), // 32
.douta (rdata_way0[0] ) // 32
);
data_bram_bank bank1_way0(
.clka (clk ),
.ena (cached&refresh|sram_en&bank_sel[1]&hit[0]|write_back ), // 1
.wea (refresh?lru?4'b0000:4'b1111:write_back?4'b0000:sram_we), // 4
.addra (index ), // 7
.dina (refresh?cacheline_new[63:32]:sram_wdata ), // 32
.douta (rdata_way0[1] ) // 32
);
data_bram_bank bank2_way0(
.clka (clk ),
.ena (cached&refresh|sram_en&bank_sel[2]&hit[0]|write_back ), // 1
.wea (refresh?lru?4'b0000:4'b1111:write_back?4'b0000:sram_we), // 4
.addra (index ), // 7
.dina (refresh?cacheline_new[95:64]:sram_wdata ), // 32
.douta (rdata_way0[2] ) // 32
);
data_bram_bank bank3_way0(
.clka (clk ),
.ena (cached&refresh|sram_en&bank_sel[3]&hit[0]|write_back ), // 1
.wea (refresh?lru?4'b0000:4'b1111:write_back?4'b0000:sram_we), // 4
.addra (index ), // 7
.dina (refresh?cacheline_new[127:96]:sram_wdata ), // 32
.douta (rdata_way0[3] ) // 32
);
data_bram_bank bank4_way0(
.clka (clk ),
.ena (cached&refresh|sram_en&bank_sel[4]&hit[0]|write_back ), // 1
.wea (refresh?lru?4'b0000:4'b1111:write_back?4'b0000:sram_we), // 4
.addra (index ), // 7
.dina (refresh?cacheline_new[159:128]:sram_wdata ), // 32
.douta (rdata_way0[4] ) // 32
);
data_bram_bank bank5_way0(
.clka (clk ),
.ena (cached&refresh|sram_en&bank_sel[5]&hit[0]|write_back ), // 1
.wea (refresh?lru?4'b0000:4'b1111:write_back?4'b0000:sram_we), // 4
.addra (index ), // 7
.dina (refresh?cacheline_new[191:160]:sram_wdata ), // 32
.douta (rdata_way0[5] ) // 32
);
data_bram_bank bank6_way0(
.clka (clk ),
.ena (cached&refresh|sram_en&bank_sel[6]&hit[0]|write_back ), // 1
.wea (refresh?lru?4'b0000:4'b1111:write_back?4'b0000:sram_we), // 4
.addra (index ), // 7
.dina (refresh?cacheline_new[223:192]:sram_wdata ), // 32
.douta (rdata_way0[6] ) // 32
);
data_bram_bank bank7_way0(
.clka (clk ),
.ena (cached&refresh|sram_en&bank_sel[7]&hit[0]|write_back ), // 1
.wea (refresh?lru?4'b0000:4'b1111:write_back?4'b0000:sram_we), // 4
.addra (index ), // 7
.dina (refresh?cacheline_new[255:224]:sram_wdata ), // 32
.douta (rdata_way0[7] ) // 32
);
data_bram_bank bank8_way0(
.clka (clk ),
.ena (cached&refresh|sram_en&bank_sel[8]&hit[0]|write_back ), // 1
.wea (refresh?lru?4'b0000:4'b1111:write_back?4'b0000:sram_we), // 4
.addra (index ), // 7
.dina (refresh?cacheline_new[287:256]:sram_wdata ), // 32
.douta (rdata_way0[8] ) // 32
);
data_bram_bank bank9_way0(
.clka (clk ),
.ena (cached&refresh|sram_en&bank_sel[9]&hit[0]|write_back ), // 1
.wea (refresh?lru?4'b0000:4'b1111:write_back?4'b0000:sram_we), // 4
.addra (index ), // 7
.dina (refresh?cacheline_new[319:288]:sram_wdata ), // 32
.douta (rdata_way0[9] ) // 32
);
data_bram_bank bank10_way0(
.clka (clk ),
.ena (cached&refresh|sram_en&bank_sel[10]&hit[0]|write_back ), // 1
.wea (refresh?lru?4'b0000:4'b1111:write_back?4'b0000:sram_we), // 4
.addra (index ), // 7
.dina (refresh?cacheline_new[351:320]:sram_wdata ), // 32
.douta (rdata_way0[10] ) // 32
);
data_bram_bank bank11_way0(
.clka (clk ),
.ena (cached&refresh|sram_en&bank_sel[11]&hit[0]|write_back ), // 1
.wea (refresh?lru?4'b0000:4'b1111:write_back?4'b0000:sram_we), // 4
.addra (index ), // 7
.dina (refresh?cacheline_new[383:352]:sram_wdata ), // 32
.douta (rdata_way0[11] ) // 32
);
data_bram_bank bank12_way0(
.clka (clk ),
.ena (cached&refresh|sram_en&bank_sel[12]&hit[0]|write_back ), // 1
.wea (refresh?lru?4'b0000:4'b1111:write_back?4'b0000:sram_we), // 4
.addra (index ), // 7
.dina (refresh?cacheline_new[415:384]:sram_wdata ), // 32
.douta (rdata_way0[12] ) // 32
);
data_bram_bank bank13_way0(
.clka (clk ),
.ena (cached&refresh|sram_en&bank_sel[13]&hit[0]|write_back ), // 1
.wea (refresh?lru?4'b0000:4'b1111:write_back?4'b0000:sram_we), // 4
.addra (index ), // 7
.dina (refresh?cacheline_new[447:416]:sram_wdata ), // 32
.douta (rdata_way0[13] ) // 32
);
data_bram_bank bank14_way0(
.clka (clk ),
.ena (cached&refresh|sram_en&bank_sel[14]&hit[0]|write_back ), // 1
.wea (refresh?lru?4'b0000:4'b1111:write_back?4'b0000:sram_we), // 4
.addra (index ), // 7
.dina (refresh?cacheline_new[479:448]:sram_wdata ), // 32
.douta (rdata_way0[14] ) // 32
);
data_bram_bank bank15_way0(
.clka (clk ),
.ena (cached&refresh|sram_en&bank_sel[15]&hit[0]|write_back ), // 1
.wea (refresh?lru?4'b0000:4'b1111:write_back?4'b0000:sram_we), // 4
.addra (index ), // 7
.dina (refresh?cacheline_new[511:480]:sram_wdata ), // 32
.douta (rdata_way0[15] ) // 32
);
// data_bram_way0 end
// data_bram_way1 begin
data_bram_bank bank0_way1(
.clka (clk ),
.ena (cached&refresh|sram_en&bank_sel[0]&hit[1]|write_back ), // 1
.wea (refresh?lru?4'b1111:4'b0000:write_back?4'b0000:sram_we), // 4
.addra (index ), // 7
.dina (refresh?cacheline_new[31:0]:sram_wdata ), // 32
.douta (rdata_way1[0] ) // 32
);
data_bram_bank bank1_way1(
.clka (clk ),
.ena (cached&refresh|sram_en&bank_sel[1]&hit[1]|write_back ), // 1
.wea (refresh?lru?4'b1111:4'b0000:write_back?4'b0000:sram_we), // 4
.addra (index ), // 7
.dina (refresh?cacheline_new[63:32]:sram_wdata ), // 32
.douta (rdata_way1[1] ) // 32
);
data_bram_bank bank2_way1(
.clka (clk ),
.ena (cached&refresh|sram_en&bank_sel[2]&hit[1]|write_back ), // 1
.wea (refresh?lru?4'b1111:4'b0000:write_back?4'b0000:sram_we), // 4
.addra (index ), // 7
.dina (refresh?cacheline_new[95:64]:sram_wdata ), // 32
.douta (rdata_way1[2] ) // 32
);
data_bram_bank bank3_way1(
.clka (clk ),
.ena (cached&refresh|sram_en&bank_sel[3]&hit[1]|write_back ), // 1
.wea (refresh?lru?4'b1111:4'b0000:write_back?4'b0000:sram_we), // 4
.addra (index ), // 7
.dina (refresh?cacheline_new[127:96]:sram_wdata ), // 32
.douta (rdata_way1[3] ) // 32
);
data_bram_bank bank4_way1(
.clka (clk ),
.ena (cached&refresh|sram_en&bank_sel[4]&hit[1]|write_back ), // 1
.wea (refresh?lru?4'b1111:4'b0000:write_back?4'b0000:sram_we), // 4
.addra (index ), // 7
.dina (refresh?cacheline_new[159:128]:sram_wdata ), // 32
.douta (rdata_way1[4] ) // 32
);
data_bram_bank bank5_way1(
.clka (clk ),
.ena (cached&refresh|sram_en&bank_sel[5]&hit[1]|write_back ), // 1
.wea (refresh?lru?4'b1111:4'b0000:write_back?4'b0000:sram_we), // 4
.addra (index ), // 7
.dina (refresh?cacheline_new[191:160]:sram_wdata ), // 32
.douta (rdata_way1[5] ) // 32
);
data_bram_bank bank6_way1(
.clka (clk ),
.ena (cached&refresh|sram_en&bank_sel[6]&hit[1]|write_back ), // 1
.wea (refresh?lru?4'b1111:4'b0000:write_back?4'b0000:sram_we), // 4
.addra (index ), // 7
.dina (refresh?cacheline_new[223:192]:sram_wdata ), // 32
.douta (rdata_way1[6] ) // 32
);
data_bram_bank bank7_way1(
.clka (clk ),
.ena (cached&refresh|sram_en&bank_sel[7]&hit[1]|write_back ), // 1
.wea (refresh?lru?4'b1111:4'b0000:write_back?4'b0000:sram_we), // 4
.addra (index ), // 7
.dina (refresh?cacheline_new[255:224]:sram_wdata ), // 32
.douta (rdata_way1[7] ) // 32
);
data_bram_bank bank8_way1(
.clka (clk ),
.ena (cached&refresh|sram_en&bank_sel[8]&hit[1]|write_back ), // 1
.wea (refresh?lru?4'b1111:4'b0000:write_back?4'b0000:sram_we), // 4
.addra (index ), // 7
.dina (refresh?cacheline_new[287:256]:sram_wdata ), // 32
.douta (rdata_way1[8] ) // 32
);
data_bram_bank bank9_way1(
.clka (clk ),
.ena (cached&refresh|sram_en&bank_sel[9]&hit[1]|write_back ), // 1
.wea (refresh?lru?4'b1111:4'b0000:write_back?4'b0000:sram_we), // 4
.addra (index ), // 7
.dina (refresh?cacheline_new[319:288]:sram_wdata ), // 32
.douta (rdata_way1[9] ) // 32
);
data_bram_bank bank10_way1(
.clka (clk ),
.ena (cached&refresh|sram_en&bank_sel[10]&hit[1]|write_back ), // 1
.wea (refresh?lru?4'b1111:4'b0000:write_back?4'b0000:sram_we), // 4
.addra (index ), // 7
.dina (refresh?cacheline_new[351:320]:sram_wdata ), // 32
.douta (rdata_way1[10] ) // 32
);
data_bram_bank bank11_way1(
.clka (clk ),
.ena (cached&refresh|sram_en&bank_sel[11]&hit[1]|write_back ), // 1
.wea (refresh?lru?4'b1111:4'b0000:write_back?4'b0000:sram_we), // 4
.addra (index ), // 7
.dina (refresh?cacheline_new[383:352]:sram_wdata ), // 32
.douta (rdata_way1[11] ) // 32
);
data_bram_bank bank12_way1(
.clka (clk ),
.ena (cached&refresh|sram_en&bank_sel[12]&hit[1]|write_back ), // 1
.wea (refresh?lru?4'b1111:4'b0000:write_back?4'b0000:sram_we), // 4
.addra (index ), // 7
.dina (refresh?cacheline_new[415:384]:sram_wdata ), // 32
.douta (rdata_way1[12] ) // 32
);
data_bram_bank bank13_way1(
.clka (clk ),
.ena (cached&refresh|sram_en&bank_sel[13]&hit[1]|write_back ), // 1
.wea (refresh?lru?4'b1111:4'b0000:write_back?4'b0000:sram_we), // 4
.addra (index ), // 7
.dina (refresh?cacheline_new[447:416]:sram_wdata ), // 32
.douta (rdata_way1[13] ) // 32
);
data_bram_bank bank14_way1(
.clka (clk ),
.ena (cached&refresh|sram_en&bank_sel[14]&hit[1]|write_back ), // 1
.wea (refresh?lru?4'b1111:4'b0000:write_back?4'b0000:sram_we), // 4
.addra (index ), // 7
.dina (refresh?cacheline_new[479:448]:sram_wdata ), // 32
.douta (rdata_way1[14] ) // 32
);
data_bram_bank bank15_way1(
.clka (clk ),
.ena (cached&refresh|sram_en&bank_sel[15]&hit[1]|write_back ), // 1
.wea (refresh?lru?4'b1111:4'b0000:write_back?4'b0000:sram_we), // 4
.addra (index ), // 7
.dina (refresh?cacheline_new[511:480]:sram_wdata ), // 32
.douta (rdata_way1[15] ) // 32
);
// data_bram_way1 end
wire [31:0] sram_rdata_way0,sram_rdata_way1;
assign sram_rdata_way0 = ~cached_r ? 32'b0 :
bank_sel_r[ 0] ? rdata_way0[ 0] :
bank_sel_r[ 1] ? rdata_way0[ 1] :
bank_sel_r[ 2] ? rdata_way0[ 2] :
bank_sel_r[ 3] ? rdata_way0[ 3] :
bank_sel_r[ 4] ? rdata_way0[ 4] :
bank_sel_r[ 5] ? rdata_way0[ 5] :
bank_sel_r[ 6] ? rdata_way0[ 6] :
bank_sel_r[ 7] ? rdata_way0[ 7] :
bank_sel_r[ 8] ? rdata_way0[ 8] :
bank_sel_r[ 9] ? rdata_way0[ 9] :
bank_sel_r[10] ? rdata_way0[10] :
bank_sel_r[11] ? rdata_way0[11] :
bank_sel_r[12] ? rdata_way0[12] :
bank_sel_r[13] ? rdata_way0[13] :
bank_sel_r[14] ? rdata_way0[14] :
bank_sel_r[15] ? rdata_way0[15] : 32'b0;
assign sram_rdata_way1 = ~cached_r ? 32'b0 :
bank_sel_r[ 0] ? rdata_way1[ 0] :
bank_sel_r[ 1] ? rdata_way1[ 1] :
bank_sel_r[ 2] ? rdata_way1[ 2] :
bank_sel_r[ 3] ? rdata_way1[ 3] :
bank_sel_r[ 4] ? rdata_way1[ 4] :
bank_sel_r[ 5] ? rdata_way1[ 5] :
bank_sel_r[ 6] ? rdata_way1[ 6] :
bank_sel_r[ 7] ? rdata_way1[ 7] :
bank_sel_r[ 8] ? rdata_way1[ 8] :
bank_sel_r[ 9] ? rdata_way1[ 9] :
bank_sel_r[10] ? rdata_way1[10] :
bank_sel_r[11] ? rdata_way1[11] :
bank_sel_r[12] ? rdata_way1[12] :
bank_sel_r[13] ? rdata_way1[13] :
bank_sel_r[14] ? rdata_way1[14] :
bank_sel_r[15] ? rdata_way1[15] : 32'b0;
assign sram_rdata = hit_r[0] ? sram_rdata_way0 :
hit_r[1] ? sram_rdata_way1 : 32'b0;
wire [CACHELINE_WD-1:0] cacheline_old_way0, cacheline_old_way1;
assign cacheline_old_way0 = {rdata_way0[15],
rdata_way0[14],
rdata_way0[13],
rdata_way0[12],
rdata_way0[11],
rdata_way0[10],
rdata_way0[ 9],
rdata_way0[ 8],
rdata_way0[ 7],
rdata_way0[ 6],
rdata_way0[ 5],
rdata_way0[ 4],
rdata_way0[ 3],
rdata_way0[ 2],
rdata_way0[ 1],
rdata_way0[ 0]
};
assign cacheline_old_way1 = {rdata_way1[15],
rdata_way1[14],
rdata_way1[13],
rdata_way1[12],
rdata_way1[11],
rdata_way1[10],
rdata_way1[ 9],
rdata_way1[ 8],
rdata_way1[ 7],
rdata_way1[ 6],
rdata_way1[ 5],
rdata_way1[ 4],
rdata_way1[ 3],
rdata_way1[ 2],
rdata_way1[ 1],
rdata_way1[ 0]
};
assign cacheline_old = lru_r ? cacheline_old_way1 : cacheline_old_way0;
endmodule
module cache_data_v6
#(
parameter CACHELINE_WD = 512,
parameter TAG_WD = 21,
parameter HIT_WD = 2
)
(
input clk,
input reset,
input write_back,
input [ 1:0] hit,
input lru,
input cached,
// sram_port
input sram_en,
input [ 3:0] sram_we,
input [31:0] sram_addr,
input [31:0] sram_wdata,
output [63:0] sram_rdata,
// axi
input refresh,
input [CACHELINE_WD -1:0] cacheline_new,
output [CACHELINE_WD -1:0] cacheline_old
);
wire [31 :0] rdata_way0 [15:0];
wire [31 :0] rdata_way1 [15:0];
wire [TAG_WD -2:0] tag;
wire [5 :0] index;
wire [5 :0] offset;
reg [HIT_WD- 1:0] hit_r;
reg lru_r;
reg cached_r;
assign {tag,
index,
offset
} = sram_addr;
wire [15:0] bank_sel;
reg [15:0] bank_sel_r;
decoder_4_16 u_decoder_4_16(
.in (offset[5:2] ),
.out (bank_sel )
);
always @ (posedge clk) begin
if (reset) begin
hit_r <= 2'b0;
lru_r <= 1'b0;
cached_r <= 1'b1;
bank_sel_r <= 16'b0;
end
else begin
hit_r <= hit;
lru_r <= lru;
cached_r <= cached;
bank_sel_r <= bank_sel;
end
end
// data_bram_way0 begin
data_bram_bank bank0_way0(
.clka (clk ),
.ena (cached&refresh|sram_en&bank_sel[0]&hit[0]|write_back ), // 1
.wea (refresh?lru?4'b0000:4'b1111:write_back?4'b0000:sram_we), // 4
.addra (index ), // 7
.dina (refresh?cacheline_new[31:0]:sram_wdata ), // 32
.douta (rdata_way0[0] ) // 32
);
data_bram_bank bank1_way0(
.clka (clk ),
.ena (cached&refresh|sram_en&bank_sel[0]&hit[0]|write_back ), // 1
.wea (refresh?lru?4'b0000:4'b1111:write_back?4'b0000:sram_we), // 4
.addra (index ), // 7
.dina (refresh?cacheline_new[63:32]:sram_wdata ), // 32
.douta (rdata_way0[1] ) // 32
);
data_bram_bank bank2_way0(
.clka (clk ),
.ena (cached&refresh|sram_en&bank_sel[2]&hit[0]|write_back ), // 1
.wea (refresh?lru?4'b0000:4'b1111:write_back?4'b0000:sram_we), // 4
.addra (index ), // 7
.dina (refresh?cacheline_new[95:64]:sram_wdata ), // 32
.douta (rdata_way0[2] ) // 32
);
data_bram_bank bank3_way0(
.clka (clk ),
.ena (cached&refresh|sram_en&bank_sel[2]&hit[0]|write_back ), // 1
.wea (refresh?lru?4'b0000:4'b1111:write_back?4'b0000:sram_we), // 4
.addra (index ), // 7
.dina (refresh?cacheline_new[127:96]:sram_wdata ), // 32
.douta (rdata_way0[3] ) // 32
);
data_bram_bank bank4_way0(
.clka (clk ),
.ena (cached&refresh|sram_en&bank_sel[4]&hit[0]|write_back ), // 1
.wea (refresh?lru?4'b0000:4'b1111:write_back?4'b0000:sram_we), // 4
.addra (index ), // 7
.dina (refresh?cacheline_new[159:128]:sram_wdata ), // 32
.douta (rdata_way0[4] ) // 32
);
data_bram_bank bank5_way0(
.clka (clk ),
.ena (cached&refresh|sram_en&bank_sel[4]&hit[0]|write_back ), // 1
.wea (refresh?lru?4'b0000:4'b1111:write_back?4'b0000:sram_we), // 4
.addra (index ), // 7
.dina (refresh?cacheline_new[191:160]:sram_wdata ), // 32
.douta (rdata_way0[5] ) // 32
);
data_bram_bank bank6_way0(
.clka (clk ),
.ena (cached&refresh|sram_en&bank_sel[6]&hit[0]|write_back ), // 1
.wea (refresh?lru?4'b0000:4'b1111:write_back?4'b0000:sram_we), // 4
.addra (index ), // 7
.dina (refresh?cacheline_new[223:192]:sram_wdata ), // 32
.douta (rdata_way0[6] ) // 32
);
data_bram_bank bank7_way0(
.clka (clk ),
.ena (cached&refresh|sram_en&bank_sel[6]&hit[0]|write_back ), // 1
.wea (refresh?lru?4'b0000:4'b1111:write_back?4'b0000:sram_we), // 4
.addra (index ), // 7
.dina (refresh?cacheline_new[255:224]:sram_wdata ), // 32
.douta (rdata_way0[7] ) // 32
);
data_bram_bank bank8_way0(
.clka (clk ),
.ena (cached&refresh|sram_en&bank_sel[8]&hit[0]|write_back ), // 1
.wea (refresh?lru?4'b0000:4'b1111:write_back?4'b0000:sram_we), // 4
.addra (index ), // 7
.dina (refresh?cacheline_new[287:256]:sram_wdata ), // 32
.douta (rdata_way0[8] ) // 32
);
data_bram_bank bank9_way0(
.clka (clk ),
.ena (cached&refresh|sram_en&bank_sel[8]&hit[0]|write_back ), // 1
.wea (refresh?lru?4'b0000:4'b1111:write_back?4'b0000:sram_we), // 4
.addra (index ), // 7
.dina (refresh?cacheline_new[319:288]:sram_wdata ), // 32
.douta (rdata_way0[9] ) // 32
);
data_bram_bank bank10_way0(
.clka (clk ),
.ena (cached&refresh|sram_en&bank_sel[10]&hit[0]|write_back ), // 1
.wea (refresh?lru?4'b0000:4'b1111:write_back?4'b0000:sram_we), // 4
.addra (index ), // 7
.dina (refresh?cacheline_new[351:320]:sram_wdata ), // 32
.douta (rdata_way0[10] ) // 32
);
data_bram_bank bank11_way0(
.clka (clk ),
.ena (cached&refresh|sram_en&bank_sel[10]&hit[0]|write_back ), // 1
.wea (refresh?lru?4'b0000:4'b1111:write_back?4'b0000:sram_we), // 4
.addra (index ), // 7
.dina (refresh?cacheline_new[383:352]:sram_wdata ), // 32
.douta (rdata_way0[11] ) // 32
);
data_bram_bank bank12_way0(
.clka (clk ),
.ena (cached&refresh|sram_en&bank_sel[12]&hit[0]|write_back ), // 1
.wea (refresh?lru?4'b0000:4'b1111:write_back?4'b0000:sram_we), // 4
.addra (index ), // 7
.dina (refresh?cacheline_new[415:384]:sram_wdata ), // 32
.douta (rdata_way0[12] ) // 32
);
data_bram_bank bank13_way0(
.clka (clk ),
.ena (cached&refresh|sram_en&bank_sel[12]&hit[0]|write_back ), // 1
.wea (refresh?lru?4'b0000:4'b1111:write_back?4'b0000:sram_we), // 4
.addra (index ), // 7
.dina (refresh?cacheline_new[447:416]:sram_wdata ), // 32
.douta (rdata_way0[13] ) // 32
);
data_bram_bank bank14_way0(
.clka (clk ),
.ena (cached&refresh|sram_en&bank_sel[14]&hit[0]|write_back ), // 1
.wea (refresh?lru?4'b0000:4'b1111:write_back?4'b0000:sram_we), // 4
.addra (index ), // 7
.dina (refresh?cacheline_new[479:448]:sram_wdata ), // 32
.douta (rdata_way0[14] ) // 32
);
data_bram_bank bank15_way0(
.clka (clk ),
.ena (cached&refresh|sram_en&bank_sel[14]&hit[0]|write_back ), // 1
.wea (refresh?lru?4'b0000:4'b1111:write_back?4'b0000:sram_we), // 4
.addra (index ), // 7
.dina (refresh?cacheline_new[511:480]:sram_wdata ), // 32
.douta (rdata_way0[15] ) // 32
);
// data_bram_way0 end
// data_bram_way1 begin
data_bram_bank bank0_way1(
.clka (clk ),
.ena (cached&refresh|sram_en&bank_sel[0]&hit[1]|write_back ), // 1
.wea (refresh?lru?4'b1111:4'b0000:write_back?4'b0000:sram_we), // 4
.addra (index ), // 7
.dina (refresh?cacheline_new[31:0]:sram_wdata ), // 32
.douta (rdata_way1[0] ) // 32
);
data_bram_bank bank1_way1(
.clka (clk ),
.ena (cached&refresh|sram_en&bank_sel[0]&hit[1]|write_back ), // 1
.wea (refresh?lru?4'b1111:4'b0000:write_back?4'b0000:sram_we), // 4
.addra (index ), // 7
.dina (refresh?cacheline_new[63:32]:sram_wdata ), // 32
.douta (rdata_way1[1] ) // 32
);
data_bram_bank bank2_way1(
.clka (clk ),
.ena (cached&refresh|sram_en&bank_sel[2]&hit[1]|write_back ), // 1
.wea (refresh?lru?4'b1111:4'b0000:write_back?4'b0000:sram_we), // 4
.addra (index ), // 7
.dina (refresh?cacheline_new[95:64]:sram_wdata ), // 32
.douta (rdata_way1[2] ) // 32
);
data_bram_bank bank3_way1(
.clka (clk ),
.ena (cached&refresh|sram_en&bank_sel[2]&hit[1]|write_back ), // 1
.wea (refresh?lru?4'b1111:4'b0000:write_back?4'b0000:sram_we), // 4
.addra (index ), // 7
.dina (refresh?cacheline_new[127:96]:sram_wdata ), // 32
.douta (rdata_way1[3] ) // 32
);
data_bram_bank bank4_way1(
.clka (clk ),
.ena (cached&refresh|sram_en&bank_sel[4]&hit[1]|write_back ), // 1
.wea (refresh?lru?4'b1111:4'b0000:write_back?4'b0000:sram_we), // 4
.addra (index ), // 7
.dina (refresh?cacheline_new[159:128]:sram_wdata ), // 32
.douta (rdata_way1[4] ) // 32
);
data_bram_bank bank5_way1(
.clka (clk ),
.ena (cached&refresh|sram_en&bank_sel[4]&hit[1]|write_back ), // 1
.wea (refresh?lru?4'b1111:4'b0000:write_back?4'b0000:sram_we), // 4
.addra (index ), // 7
.dina (refresh?cacheline_new[191:160]:sram_wdata ), // 32
.douta (rdata_way1[5] ) // 32
);
data_bram_bank bank6_way1(
.clka (clk ),
.ena (cached&refresh|sram_en&bank_sel[6]&hit[1]|write_back ), // 1
.wea (refresh?lru?4'b1111:4'b0000:write_back?4'b0000:sram_we), // 4
.addra (index ), // 7
.dina (refresh?cacheline_new[223:192]:sram_wdata ), // 32
.douta (rdata_way1[6] ) // 32
);
data_bram_bank bank7_way1(
.clka (clk ),
.ena (cached&refresh|sram_en&bank_sel[6]&hit[1]|write_back ), // 1
.wea (refresh?lru?4'b1111:4'b0000:write_back?4'b0000:sram_we), // 4
.addra (index ), // 7
.dina (refresh?cacheline_new[255:224]:sram_wdata ), // 32
.douta (rdata_way1[7] ) // 32
);
data_bram_bank bank8_way1(
.clka (clk ),
.ena (cached&refresh|sram_en&bank_sel[8]&hit[1]|write_back ), // 1
.wea (refresh?lru?4'b1111:4'b0000:write_back?4'b0000:sram_we), // 4
.addra (index ), // 7
.dina (refresh?cacheline_new[287:256]:sram_wdata ), // 32
.douta (rdata_way1[8] ) // 32
);
data_bram_bank bank9_way1(
.clka (clk ),
.ena (cached&refresh|sram_en&bank_sel[8]&hit[1]|write_back ), // 1
.wea (refresh?lru?4'b1111:4'b0000:write_back?4'b0000:sram_we), // 4
.addra (index ), // 7
.dina (refresh?cacheline_new[319:288]:sram_wdata ), // 32
.douta (rdata_way1[9] ) // 32
);
data_bram_bank bank10_way1(
.clka (clk ),
.ena (cached&refresh|sram_en&bank_sel[10]&hit[1]|write_back ), // 1
.wea (refresh?lru?4'b1111:4'b0000:write_back?4'b0000:sram_we), // 4
.addra (index ), // 7
.dina (refresh?cacheline_new[351:320]:sram_wdata ), // 32
.douta (rdata_way1[10] ) // 32
);
data_bram_bank bank11_way1(
.clka (clk ),
.ena (cached&refresh|sram_en&bank_sel[10]&hit[1]|write_back ), // 1
.wea (refresh?lru?4'b1111:4'b0000:write_back?4'b0000:sram_we), // 4
.addra (index ), // 7
.dina (refresh?cacheline_new[383:352]:sram_wdata ), // 32
.douta (rdata_way1[11] ) // 32
);
data_bram_bank bank12_way1(
.clka (clk ),
.ena (cached&refresh|sram_en&bank_sel[12]&hit[1]|write_back ), // 1
.wea (refresh?lru?4'b1111:4'b0000:write_back?4'b0000:sram_we), // 4
.addra (index ), // 7
.dina (refresh?cacheline_new[415:384]:sram_wdata ), // 32
.douta (rdata_way1[12] ) // 32
);
data_bram_bank bank13_way1(
.clka (clk ),
.ena (cached&refresh|sram_en&bank_sel[12]&hit[1]|write_back ), // 1
.wea (refresh?lru?4'b1111:4'b0000:write_back?4'b0000:sram_we), // 4
.addra (index ), // 7
.dina (refresh?cacheline_new[447:416]:sram_wdata ), // 32
.douta (rdata_way1[13] ) // 32
);
data_bram_bank bank14_way1(
.clka (clk ),
.ena (cached&refresh|sram_en&bank_sel[14]&hit[1]|write_back ), // 1
.wea (refresh?lru?4'b1111:4'b0000:write_back?4'b0000:sram_we), // 4
.addra (index ), // 7
.dina (refresh?cacheline_new[479:448]:sram_wdata ), // 32
.douta (rdata_way1[14] ) // 32
);
data_bram_bank bank15_way1(
.clka (clk ),
.ena (cached&refresh|sram_en&bank_sel[14]&hit[1]|write_back ), // 1
.wea (refresh?lru?4'b1111:4'b0000:write_back?4'b0000:sram_we), // 4
.addra (index ), // 7
.dina (refresh?cacheline_new[511:480]:sram_wdata ), // 32
.douta (rdata_way1[15] ) // 32
);
// data_bram_way1 end
wire [63:0] sram_rdata_way0,sram_rdata_way1;
assign sram_rdata_way0 = ~cached_r ? 64'b0 :
bank_sel_r[ 0] ? {rdata_way0[ 1],rdata_way0[ 0]} :
bank_sel_r[ 2] ? {rdata_way0[ 3],rdata_way0[ 2]} :
bank_sel_r[ 4] ? {rdata_way0[ 5],rdata_way0[ 4]} :
bank_sel_r[ 6] ? {rdata_way0[ 7],rdata_way0[ 6]} :
bank_sel_r[ 8] ? {rdata_way0[ 9],rdata_way0[ 8]} :
bank_sel_r[10] ? {rdata_way0[11],rdata_way0[10]} :
bank_sel_r[12] ? {rdata_way0[13],rdata_way0[12]} :
bank_sel_r[14] ? {rdata_way0[15],rdata_way0[14]} : 64'b0;
assign sram_rdata_way1 = ~cached_r ? 64'b0 :
bank_sel_r[ 0] ? {rdata_way1[ 1],rdata_way1[ 0]} :
bank_sel_r[ 2] ? {rdata_way1[ 3],rdata_way1[ 2]} :
bank_sel_r[ 4] ? {rdata_way1[ 5],rdata_way1[ 4]} :
bank_sel_r[ 6] ? {rdata_way1[ 7],rdata_way1[ 6]} :
bank_sel_r[ 8] ? {rdata_way1[ 9],rdata_way1[ 8]} :
bank_sel_r[10] ? {rdata_way1[11],rdata_way1[10]} :
bank_sel_r[12] ? {rdata_way1[13],rdata_way1[12]} :
bank_sel_r[14] ? {rdata_way1[15],rdata_way1[14]} : 64'b0;
assign sram_rdata = hit_r[0] ? sram_rdata_way0 :
hit_r[1] ? sram_rdata_way1 : 64'b0;
wire [CACHELINE_WD -1:0] cacheline_old_way0, cacheline_old_way1;
assign cacheline_old_way0 = {
rdata_way0[15],
rdata_way0[14],
rdata_way0[13],
rdata_way0[12],
rdata_way0[11],
rdata_way0[10],
rdata_way0[ 9],
rdata_way0[ 8],
rdata_way0[ 7],
rdata_way0[ 6],
rdata_way0[ 5],
rdata_way0[ 4],
rdata_way0[ 3],
rdata_way0[ 2],
rdata_way0[ 1],
rdata_way0[ 0]
};
assign cacheline_old_way1 = {
rdata_way1[15],
rdata_way1[14],
rdata_way1[13],
rdata_way1[12],
rdata_way1[11],
rdata_way1[10],
rdata_way1[ 9],
rdata_way1[ 8],
rdata_way1[ 7],
rdata_way1[ 6],
rdata_way1[ 5],
rdata_way1[ 4],
rdata_way1[ 3],
rdata_way1[ 2],
rdata_way1[ 1],
rdata_way1[ 0]
};
assign cacheline_old = lru_r ? cacheline_old_way1 : cacheline_old_way0;
endmodule

242
lacpu/rtl/mycpu/cache_tag.v Normal file
View File

@@ -0,0 +1,242 @@
`default_nettype wire
module cache_tag_v5
#(
parameter HIT_WD = 2,
parameter TAG_WD = 21,
parameter INDEX_WD = 64
)
(
input clk,
input reset,
input flush,
output stallreq,
input cached,
input sram_en,
input [ 3:0] sram_we,
input [31:0] sram_addr,
input refresh,
output miss,
output [31:0] axi_raddr,
output write_back,
output [31:0] axi_waddr,
output [ 1:0] hit,
output lru
);
reg [TAG_WD -1:0] tag_way0 [INDEX_WD -1:0];
reg [TAG_WD -1:0] tag_way1 [INDEX_WD -1:0];
reg [INDEX_WD -1:0] lru_r;
wire [TAG_WD -2:0] tag;
wire [5:0] index;
wire [5:0] offset;
wire cached_v;
wire hit_way0;
wire hit_way1;
wire [31:0] axi_waddr_way0;
wire [31:0] axi_waddr_way1;
wire write_back_way0;
wire write_back_way1;
assign cached_v = cached;
assign {tag,
index,
offset
} = sram_addr;
// lru lru_r指向的即为最闲的那个
always @ (posedge clk) begin
if (reset) begin
lru_r <= 0;
end
else if (hit_way0 & ~hit_way1) begin
lru_r[index] <= 1'b1;
end
else if (~hit_way0 & hit_way1) begin
lru_r[index] <= 1'b0;
end
else if (refresh) begin
lru_r[index] <= ~lru_r[index];
end
end
// way0
always @ (posedge clk) begin
if (reset) begin
tag_way0[ 0] <= 21'b0;
tag_way0[ 1] <= 21'b0;
tag_way0[ 2] <= 21'b0;
tag_way0[ 3] <= 21'b0;
tag_way0[ 4] <= 21'b0;
tag_way0[ 5] <= 21'b0;
tag_way0[ 6] <= 21'b0;
tag_way0[ 7] <= 21'b0;
tag_way0[ 8] <= 21'b0;
tag_way0[ 9] <= 21'b0;
tag_way0[10] <= 21'b0;
tag_way0[11] <= 21'b0;
tag_way0[12] <= 21'b0;
tag_way0[13] <= 21'b0;
tag_way0[14] <= 21'b0;
tag_way0[15] <= 21'b0;
tag_way0[16] <= 21'b0;
tag_way0[17] <= 21'b0;
tag_way0[18] <= 21'b0;
tag_way0[19] <= 21'b0;
tag_way0[20] <= 21'b0;
tag_way0[21] <= 21'b0;
tag_way0[22] <= 21'b0;
tag_way0[23] <= 21'b0;
tag_way0[24] <= 21'b0;
tag_way0[25] <= 21'b0;
tag_way0[26] <= 21'b0;
tag_way0[27] <= 21'b0;
tag_way0[28] <= 21'b0;
tag_way0[29] <= 21'b0;
tag_way0[30] <= 21'b0;
tag_way0[31] <= 21'b0;
tag_way0[32] <= 21'b0;
tag_way0[33] <= 21'b0;
tag_way0[34] <= 21'b0;
tag_way0[35] <= 21'b0;
tag_way0[36] <= 21'b0;
tag_way0[37] <= 21'b0;
tag_way0[38] <= 21'b0;
tag_way0[39] <= 21'b0;
tag_way0[40] <= 21'b0;
tag_way0[41] <= 21'b0;
tag_way0[42] <= 21'b0;
tag_way0[43] <= 21'b0;
tag_way0[44] <= 21'b0;
tag_way0[45] <= 21'b0;
tag_way0[46] <= 21'b0;
tag_way0[47] <= 21'b0;
tag_way0[48] <= 21'b0;
tag_way0[49] <= 21'b0;
tag_way0[50] <= 21'b0;
tag_way0[51] <= 21'b0;
tag_way0[52] <= 21'b0;
tag_way0[53] <= 21'b0;
tag_way0[54] <= 21'b0;
tag_way0[55] <= 21'b0;
tag_way0[56] <= 21'b0;
tag_way0[57] <= 21'b0;
tag_way0[58] <= 21'b0;
tag_way0[59] <= 21'b0;
tag_way0[60] <= 21'b0;
tag_way0[61] <= 21'b0;
tag_way0[62] <= 21'b0;
tag_way0[63] <= 21'b0;
end
else if (refresh & (~lru_r[index])) begin
tag_way0[index] <= {cached_v, tag};
end
end
// way1
always @ (posedge clk) begin
if (reset) begin
tag_way1[ 0] <= 21'b0;
tag_way1[ 1] <= 21'b0;
tag_way1[ 2] <= 21'b0;
tag_way1[ 3] <= 21'b0;
tag_way1[ 4] <= 21'b0;
tag_way1[ 5] <= 21'b0;
tag_way1[ 6] <= 21'b0;
tag_way1[ 7] <= 21'b0;
tag_way1[ 8] <= 21'b0;
tag_way1[ 9] <= 21'b0;
tag_way1[10] <= 21'b0;
tag_way1[11] <= 21'b0;
tag_way1[12] <= 21'b0;
tag_way1[13] <= 21'b0;
tag_way1[14] <= 21'b0;
tag_way1[15] <= 21'b0;
tag_way1[16] <= 21'b0;
tag_way1[17] <= 21'b0;
tag_way1[18] <= 21'b0;
tag_way1[19] <= 21'b0;
tag_way1[20] <= 21'b0;
tag_way1[21] <= 21'b0;
tag_way1[22] <= 21'b0;
tag_way1[23] <= 21'b0;
tag_way1[24] <= 21'b0;
tag_way1[25] <= 21'b0;
tag_way1[26] <= 21'b0;
tag_way1[27] <= 21'b0;
tag_way1[28] <= 21'b0;
tag_way1[29] <= 21'b0;
tag_way1[30] <= 21'b0;
tag_way1[31] <= 21'b0;
tag_way1[32] <= 21'b0;
tag_way1[33] <= 21'b0;
tag_way1[34] <= 21'b0;
tag_way1[35] <= 21'b0;
tag_way1[36] <= 21'b0;
tag_way1[37] <= 21'b0;
tag_way1[38] <= 21'b0;
tag_way1[39] <= 21'b0;
tag_way1[40] <= 21'b0;
tag_way1[41] <= 21'b0;
tag_way1[42] <= 21'b0;
tag_way1[43] <= 21'b0;
tag_way1[44] <= 21'b0;
tag_way1[45] <= 21'b0;
tag_way1[46] <= 21'b0;
tag_way1[47] <= 21'b0;
tag_way1[48] <= 21'b0;
tag_way1[49] <= 21'b0;
tag_way1[50] <= 21'b0;
tag_way1[51] <= 21'b0;
tag_way1[52] <= 21'b0;
tag_way1[53] <= 21'b0;
tag_way1[54] <= 21'b0;
tag_way1[55] <= 21'b0;
tag_way1[56] <= 21'b0;
tag_way1[57] <= 21'b0;
tag_way1[58] <= 21'b0;
tag_way1[59] <= 21'b0;
tag_way1[60] <= 21'b0;
tag_way1[61] <= 21'b0;
tag_way1[62] <= 21'b0;
tag_way1[63] <= 21'b0;
end
else if (refresh & lru_r[index]) begin
tag_way1[index] <= {cached_v, tag};
end
end
assign lru = lru_r[index];
assign hit = {hit_way1, hit_way0};
assign hit_way0 = ~flush & cached_v & sram_en & ({1'b1,tag} == tag_way0[index]);
assign hit_way1 = ~flush & cached_v & sram_en & ({1'b1,tag} == tag_way1[index]);
assign miss = cached_v & sram_en & ~(hit_way0 | hit_way1) & ~flush;
assign stallreq = miss;
assign axi_raddr = cached_v ? {sram_addr[31:6], 6'b0} : sram_addr;
assign write_back = flush ? 1'b0 : lru ? write_back_way1 : write_back_way0;
assign write_back_way0 = cached_v & sram_en & miss & tag_way0[index][TAG_WD -1];
assign write_back_way1 = cached_v & sram_en & miss & tag_way1[index][TAG_WD -1];
assign axi_waddr = lru_r[index] ? axi_waddr_way1 : axi_waddr_way0;
assign axi_waddr_way0 = {tag_way0[index][TAG_WD -2:0],
index,
6'b0
};
assign axi_waddr_way1 = {tag_way1[index][TAG_WD -2:0],
index,
6'b0
};
endmodule

105
lacpu/rtl/mycpu/csr.hv Normal file
View File

@@ -0,0 +1,105 @@
`define CRMD_ADDR 14'h0
`define PRMD_ADDR 14'h1
`define EUEN_ADDR 14'h2
`define ECFG_ADDR 14'h4
`define ESTAT_ADDR 14'h5
`define ERA_ADDR 14'h6
`define BADV_ADDR 14'h7
`define EENTRY_ADDR 14'hc
`define TLBIDX_ADDR 14'h10
`define TLBEHI_ADDR 14'h11
`define TLBELO0_ADDR 14'h12
`define TLBELO1_ADDR 14'h13
`define ASID_ADDR 14'h18
`define PGDL_ADDR 14'h19
`define PGDH_ADDR 14'h1a
`define PGD_ADDR 14'h1b
`define CPUID_ADDR 14'h20
`define SAVE0_ADDR 14'h30
`define SAVE1_ADDR 14'h31
`define SAVE2_ADDR 14'h32
`define SAVE3_ADDR 14'h33
`define TID_ADDR 14'h40
`define TCFG_ADDR 14'h41
`define TVAL_ADDR 14'h42
`define CNTC_ADDR 14'h43
`define TICLR_ADDR 14'h44
`define LLBCTL_ADDR 14'h60
`define TLBRENTRY_ADDR 14'h88
`define CTAG_ADDR 14'h98
`define DMW0_ADDR 14'h180
`define DMW1_ADDR 14'h181
//CRMD
`define PLV 1:0
`define IE 2
`define DA 3
`define PG 4
`define DATF 6:5
`define DATM 8:7
//PRMD
`define PPLV 1:0
`define PIE 2
//ECTL
`define LIE 12:0
`define LIE_1 9:0
`define LIE_2 12:11
//ESTAT
`define IS 12:0
`define ECODE 21:16
`define ESUBCODE 30:22
//TLBIDX
`define INDEX 4:0
`define PS 29:24
`define NE 31
//TLBEHI
`define VPPN 31:13
//TLBELO
`define TLB_V 0
`define TLB_D 1
`define TLB_PLV 3:2
`define TLB_MAT 5:4
`define TLB_G 6
`define TLB_PPN 31:8
`define TLB_PPN_EN 27:8 //todo
//ASID
`define TLB_ASID 9:0
//CPUID
`define COREID 8:0
//LLBCTL
`define ROLLB 0
`define WCLLB 1
`define KLO 2
//TCFG
`define EN 0
`define PERIODIC 1
`define INITVAL 31:2
//TICLR
`define CLR 0
//TLBRENTRY
`define TLBRENTRY_PA 31:6
//DMW
`define PLV0 0
`define PLV3 3
`define DMW_MAT 5:4
`define PSEG 27:25
`define VSEG 31:29
//PGDL PGDH PGD
`define BASE 31:12
`define ECODE_INT 6'h0
`define ECODE_PIL 6'h1
`define ECODE_PIS 6'h2
`define ECODE_PIF 6'h3
`define ECODE_PME 6'h4
`define ECODE_PPI 6'h7
`define ECODE_ADEF 6'h8
`define ECODE_ALE 6'h9
`define ECODE_SYS 6'hb
`define ECODE_BRK 6'hc
`define ECODE_INE 6'hd
`define ECODE_IPE 6'he
`define ECODE_FPD 6'hf
`define ECODE_TLBR 6'h3f
`define ESUBCODE_ADEF 9'h0

355
lacpu/rtl/mycpu/csr.v Normal file
View File

@@ -0,0 +1,355 @@
`include "csr.hv"
module csr(
input clk,
input reset,
input stall,
input [31:0] pc,
input [31:0] src1,
input stallreq_axi,
input [31:0] error_va,
input csr_we,
input [63:0] csr_vec,
input [ 6:0] csr_op,
input [13:0] csr_addr,
input csr_wdata_sel,
input [31:0] csr_wdata,
output [31:0] csr_rdata,
output except_en,
output [31:0] new_pc,
output [ 1:0] plv_out,
output has_int_out
);
reg [31:0] crmd; // ??????
reg [31:0] prmd; // ???????
reg [31:0] euen; // ??????
reg [31:0] ecfg; // ????
reg [31:0] estat; // ????
reg [31:0] era; // ??????
reg [31:0] badv; // ?????
reg [31:0] eentry; // ??????
reg [31:0] tlbidx; // TLB ??
reg [31:0] tlbehi; // TLB ?????
reg [31:0] tlbelo0; // TLB ???? 0
reg [31:0] tlbelo1; // TLB ???? 1
reg [31:0] asid; // ???????
reg [31:0] pgdl; // ????????????
reg [31:0] pgdh; // ????????????
reg [31:0] pgd; // ??????
reg [31:0] cpuid; // ?????
reg [31:0] save0; // ????0
reg [31:0] save1; // ????1
reg [31:0] save2; // ????2
reg [31:0] save3; // ????3
reg [31:0] tid; // ?????
reg [31:0] tcfg; // ?????
reg [31:0] tval; // ????
reg [31:0] ticlr; // ??????
reg [31:0] llbctl; // LLbit ??
reg [31:0] tlbrentry; // TLB ????????
reg [31:0] ctag; // ??????
reg [31:0] dmw0; // ????????0
reg [31:0] dmw1; // ????????1
reg [31:0] csr_rdata_r;
reg timer_en;
reg [63:0] timer_64;
// reg has_int_r;
// reg [ 1:0] plv_r;
wire inst_sc_w;
wire inst_csrrd;
wire inst_csrwr;
wire inst_csrxchg;
wire inst_rdcntid_w;
wire inst_rdcntvl_w;
wire inst_rdcntvh_w;
wire has_int;
wire excp_ale;
wire excp_adef;
wire excp_ipe;
wire excp_ine;
wire inst_break;
wire inst_syscall;
wire inst_ertn;
wire [31:0] csr_wdata_temp;
wire [ 5:0] ecode;
wire [ 8:0] esubcode;
wire va_error;
wire [31:0] bad_va;
// always @(posedge clk) begin
// if(reset) begin
// has_int_r <= 0;
// plv_r <= 0;
// end
// else begin
// has_int_r <= ((ecfg[`LIE] & estat[`IS]) != 13'b0) & crmd[`IE];
// plv_r <= except_en & !inst_ertn ? 2'b0 :
// inst_ertn ? prmd[`PPLV] :
// csr_we && (csr_addr == `CRMD_ADDR) ? csr_wdata[`PLV] :
// crmd[`PLV];
// end
// end
// out TODO!
assign has_int_out = ((ecfg[`LIE] & estat[`IS]) != 13'b0) & crmd[`IE];
assign plv_out = except_en & !inst_ertn ? 2'b0 :
inst_ertn ? prmd[`PPLV] :
csr_we && (csr_addr == `CRMD_ADDR) ? csr_wdata[`PLV] :
crmd[`PLV];
assign {excp_ale,
excp_adef,
excp_ipe,
excp_ine,
inst_break,
inst_syscall,
inst_ertn,
has_int
} = csr_vec[7:0];
assign {ecode, esubcode, va_error, bad_va} = excp_adef ? {`ECODE_ADEF, `ESUBCODE_ADEF, 1'b1, pc } :
has_int ? {`ECODE_INT , 9'b0 , 1'b0, 32'b0 } :
inst_syscall ? {`ECODE_SYS , 9'b0 , 1'b0, 32'b0 } :
inst_break ? {`ECODE_BRK , 9'b0 , 1'b0, 32'b0 } :
excp_ine ? {`ECODE_INE , 9'b0 , 1'b0, 32'b0 } :
excp_ipe ? {`ECODE_IPE , 9'b0 , 1'b0, 32'b0 } :
excp_ale ? {`ECODE_ALE , 9'b0 , 1'b1, error_va} :
0;
assign csr_rdata = csr_rdata_r;
always @(*) begin
if(|csr_op[6:4]) begin
case(csr_addr)
`CRMD_ADDR : csr_rdata_r <= crmd;
`PRMD_ADDR : csr_rdata_r <= prmd;
`EUEN_ADDR : csr_rdata_r <= euen;
`ECFG_ADDR : csr_rdata_r <= ecfg;
`ESTAT_ADDR : csr_rdata_r <= estat;
`ERA_ADDR : csr_rdata_r <= era;
`BADV_ADDR : csr_rdata_r <= badv;
`EENTRY_ADDR : csr_rdata_r <= eentry;
`TLBIDX_ADDR : csr_rdata_r <= tlbidx;
`TLBEHI_ADDR : csr_rdata_r <= tlbehi;
`TLBELO0_ADDR : csr_rdata_r <= tlbelo0;
`TLBELO1_ADDR : csr_rdata_r <= tlbelo1;
`ASID_ADDR : csr_rdata_r <= asid;
`PGDL_ADDR : csr_rdata_r <= pgdl;
`PGDH_ADDR : csr_rdata_r <= pgdh;
`PGD_ADDR : csr_rdata_r <= pgd;
`CPUID_ADDR : csr_rdata_r <= cpuid;
`SAVE0_ADDR : csr_rdata_r <= save0;
`SAVE1_ADDR : csr_rdata_r <= save1;
`SAVE2_ADDR : csr_rdata_r <= save2;
`SAVE3_ADDR : csr_rdata_r <= save3;
`TID_ADDR : csr_rdata_r <= tid;
`TCFG_ADDR : csr_rdata_r <= tcfg;
`TVAL_ADDR : csr_rdata_r <= tval;
`TICLR_ADDR : csr_rdata_r <= ticlr;
`LLBCTL_ADDR : csr_rdata_r <= llbctl;
`TLBRENTRY_ADDR : csr_rdata_r <= tlbrentry;
`CTAG_ADDR : csr_rdata_r <= ctag;
`DMW0_ADDR : csr_rdata_r <= dmw0;
`DMW1_ADDR : csr_rdata_r <= dmw1;
default : csr_rdata_r <= 32'b0;
endcase
end
else if(|csr_op[3:1]) begin
csr_rdata_r <= ({33{csr_op[1]}} & timer_64[31: 0]) |
({33{csr_op[2]}} & timer_64[63:32]) |
({33{csr_op[3]}} & tid);
end
else begin
//csr_rdata_r <= 32'b0;
end
end
assign {inst_csrrd,
inst_csrwr,
inst_csrxchg,
inst_rdcntid_w,
inst_rdcntvh_w,
inst_rdcntvl_w,
inst_sc_w
} = csr_op;
assign csr_wdata_temp = csr_wdata_sel ? (src1 & csr_wdata) | (~src1 & csr_rdata_r) : csr_wdata;
always @(posedge clk) begin
if(reset) begin
crmd <= 32'd8;
prmd <= 0;
euen <= 0;
ecfg <= 0;
estat <= 0;
era <= 0;
badv <= 0;
eentry <= 0;
tlbidx <= 0;
tlbehi <= 0;
tlbelo0 <= 0;
tlbelo1 <= 0;
asid <= 0;
pgdl <= 0;
pgdh <= 0;
pgd <= 0;
cpuid <= 0;
save0 <= 0;
save1 <= 0;
save2 <= 0;
save3 <= 0;
tid <= 0;
tcfg <= 32'hfffffffe;
tval <= 0;
ticlr <= 0;
llbctl <= 0;
tlbrentry <= 0;
ctag <= 0;
dmw0 <= 0;
dmw1 <= 0;
timer_en <= 1'b0;
end
else if(except_en & ~stallreq_axi) begin
if((|csr_vec[7:0] & !inst_ertn) | excp_adef) begin
crmd[ `PLV] <= 2'b0;
crmd[ `IE] <= 1'b0;
prmd[`PPLV] <= crmd[`PLV];
prmd[ `PIE] <= crmd[`IE ];
estat[ `ECODE] <= ecode;
estat[`ESUBCODE] <= esubcode;
era <= pc;
end
else if(inst_ertn) begin
crmd[ `PLV] <= prmd[`PPLV];
crmd[ `IE] <= prmd[`PIE ];
end
if(va_error) begin
badv <= bad_va;
end
end
else if (csr_we) begin
case (csr_addr)
`CRMD_ADDR : begin
crmd[ `PLV] <= csr_wdata_temp[ `PLV];
crmd[ `IE] <= csr_wdata_temp[ `IE];
crmd[ `DA] <= csr_wdata_temp[ `DA];
crmd[ `PG] <= csr_wdata_temp[ `PG];
crmd[`DATF] <= csr_wdata_temp[`DATF];
crmd[`DATM] <= csr_wdata_temp[`DATM];
end
`PRMD_ADDR : begin
prmd[`PPLV] <= csr_wdata_temp[`PPLV];
prmd[ `PIE] <= csr_wdata_temp[ `PIE];
end
`EUEN_ADDR : euen <= csr_wdata_temp;
`ECFG_ADDR : begin
ecfg <= csr_wdata_temp; // ????????????????
end
`ESTAT_ADDR : estat[1:0] <= csr_wdata_temp[1:0];
`ERA_ADDR : era <= csr_wdata_temp;
`BADV_ADDR : badv <= csr_wdata_temp; // MORE
`EENTRY_ADDR : eentry[31:6] <= csr_wdata_temp[31:6];
`TLBIDX_ADDR : tlbidx <= csr_wdata_temp; // PASS
`TLBEHI_ADDR : tlbehi <= csr_wdata_temp; // PASS
`TLBELO0_ADDR : tlbelo0 <= csr_wdata_temp; // PASS
`TLBELO1_ADDR : tlbelo1 <= csr_wdata_temp; // PASS
`ASID_ADDR : asid[`TLB_ASID] <= csr_wdata_temp[`TLB_ASID]; // MORE
`PGDL_ADDR : pgdl <= csr_wdata_temp;
`PGDH_ADDR : pgdh <= csr_wdata_temp;
`PGD_ADDR : pgd <= csr_wdata_temp;
//`CPUID_ADDR : cpuid <= csr_wdata_temp;
`SAVE0_ADDR : save0 <= csr_wdata_temp;
`SAVE1_ADDR : save1 <= csr_wdata_temp;
`SAVE2_ADDR : save2 <= csr_wdata_temp;
`SAVE3_ADDR : save3 <= csr_wdata_temp;
`TID_ADDR : tid <= csr_wdata_temp;
`TCFG_ADDR : begin
tcfg[ `EN] <= csr_wdata_temp[ `EN];
tcfg[`PERIODIC] <= csr_wdata_temp[`PERIODIC];
tcfg[ `INITVAL] <= csr_wdata_temp[ `INITVAL];
tval <= {csr_wdata_temp[ `INITVAL], 2'b0};
timer_en <= csr_wdata_temp[`EN];
end
//`TVAL_ADDR : tval <= {csr_wdata_temp[ `INITVAL], 2'b0};
`TICLR_ADDR : begin
if(csr_wdata_temp[`CLR]) begin
estat[11] <= 1'b0;
end
end
`LLBCTL_ADDR : llbctl <= csr_wdata_temp; // PASS
`TLBRENTRY_ADDR : tlbrentry <= csr_wdata_temp; // PASS
`CTAG_ADDR : ctag <= csr_wdata_temp;
`DMW0_ADDR : begin
dmw0[`PLV0] <= csr_wdata_temp[`PLV0];
dmw0[`PLV3] <= csr_wdata_temp[`PLV3];
dmw0[`DMW_MAT] <= csr_wdata_temp[`DMW_MAT];
dmw0[`PSEG] <= csr_wdata_temp[`PSEG];
dmw0[`VSEG] <= csr_wdata_temp[`VSEG];
end
`DMW1_ADDR : begin
dmw1[`PLV0] <= csr_wdata_temp[`PLV0];
dmw1[`PLV3] <= csr_wdata_temp[`PLV3];
dmw1[`DMW_MAT] <= csr_wdata_temp[`DMW_MAT];
dmw1[`PSEG] <= csr_wdata_temp[`PSEG];
dmw1[`VSEG] <= csr_wdata_temp[`VSEG];
end
endcase
end
else begin
// estat
if(timer_en && (tval == 32'b0)) begin
estat[11] <= 1'b1;
timer_en <= tcfg[`PERIODIC];
end
//estat[9:0] <= intrpt; // ???
// tval
if(timer_en) begin
if (tval != 32'b0) begin
tval <= tval - 32'b1;
end
else if (tval == 32'b0) begin
tval <= tcfg[`PERIODIC] ? {tcfg[`INITVAL], 2'b0} : 32'hffffffff;
end
end
end
end
assign except_en = |csr_vec[7:0];
assign new_pc = (|csr_vec[7:0] & !inst_ertn) | excp_adef ? eentry :
inst_ertn ? era :
32'b0; // TODO!
//timer_64
always @(posedge clk) begin
if (reset) begin
timer_64 <= 64'b0;
end
else begin
timer_64 <= timer_64 + 1'b1;
end
end
endmodule

65
lacpu/rtl/mycpu/dcache.v Normal file
View File

@@ -0,0 +1,65 @@
module dcache
#(
parameter HIT_WD = 2,
parameter LRU_WD = 1,
parameter CACHELINE_WD = 512
)
(
input clk,
input reset,
input data_sram_en,
input [ 3:0] data_sram_we,
input [31:0] data_sram_addr,
input [31:0] data_sram_wdata,
input dcache_refresh,
input dcache_uncached,
input [CACHELINE_WD -1:0] dcache_cacheline_new,
output stallreq_dcache,
output [31:0] data_sram_rdata,
output dcache_miss,
output [31:0] dcache_raddr,
output [31:0] dcache_waddr,
output dcache_write_back,
output [CACHELINE_WD -1:0] dcache_cacheline_old
);
wire [HIT_WD -1:0] dcache_hit;
wire [LRU_WD -1:0] dcache_lru;
cache_tag_v5 u_dcache_tag(
.clk (clk ),
.reset (reset ),
.flush (1'b0 ),
.stallreq (stallreq_dcache ),
.cached (~dcache_uncached ), // ? TODO from tlb
.sram_en (data_sram_en/* & ~d_refill & ~d_invalid & ~d_modify*/), // TODO!
.sram_we (data_sram_we ),
.sram_addr (data_sram_addr ), // _mmu ?
.refresh (dcache_refresh ),
.miss (dcache_miss ),
.axi_raddr (dcache_raddr ),
.write_back (dcache_write_back ),
.axi_waddr (dcache_waddr ),
.hit (dcache_hit ),
.lru (dcache_lru )
);
cache_data_v5 u_dcache_data(
.clk (clk ),
.reset (reset ),
.write_back (dcache_write_back ),
.hit (dcache_hit ),
.lru (dcache_lru ),
.cached (~dcache_uncached ), // ? from tlb
.sram_en (data_sram_en/* & ~d_refill & ~d_invalid & ~d_modify*/), // TODO!
.sram_we (data_sram_we ),
.sram_addr (data_sram_addr ), // _mmu ?
.sram_wdata (data_sram_wdata ),
.sram_rdata (data_sram_rdata ),
.refresh (dcache_refresh ),
.cacheline_new (dcache_cacheline_new ),
.cacheline_old (dcache_cacheline_old )
);
endmodule

52
lacpu/rtl/mycpu/div.v Normal file
View File

@@ -0,0 +1,52 @@
module div(
input clk,
input reset,
output stallreq,
input in_valid,
output out_valid,
input [31:0] a,
input [31:0] b,
output reg [31:0] quotient, //
output reg [31:0] remainder //余数
);
reg [ 5:0] cnt;
wire [31:0] sub_result;
wire carry;
wire [31:0] temp;
always @ (posedge clk) begin
if (reset) begin
cnt <= 0;
end
else if (cnt != 0) begin
cnt <= cnt -1;
end
else if (in_valid) begin
cnt <= 32;
end
end
assign temp = {remainder[30:0],quotient[31]};
assign carry = temp < b ? 0 : 1;
assign sub_result = carry ? temp - b : temp;
always @ (posedge clk) begin
if (reset) begin
quotient <= 0;
remainder <= 0;
end
else if (cnt != 0) begin
{remainder, quotient} <= {sub_result, quotient[30:0], carry};
end
else if (in_valid) begin
quotient <= a;
remainder <= 0;
end
end
assign out_valid = (cnt==0);
assign stallreq = in_valid | (~(cnt==0));
endmodule

253
lacpu/rtl/mycpu/exe_stage.v Normal file
View File

@@ -0,0 +1,253 @@
module exe_stage
#(
parameter BR_BUS_WD = 33,
parameter DS_TO_ES_BUS_WD = 301,
parameter ES_TO_MS_BUS_WD = 271,
parameter MS_TO_ES_BUS_WD = 38,
parameter WS_TO_ES_BUS_WD = 38
)
(
input clk,
input reset,
input flush,
input [ 5:0] stall,
output stallreq_es,
input [DS_TO_ES_BUS_WD -1:0] ds_to_es_bus,
output [ES_TO_MS_BUS_WD -1:0] es_to_ms_bus,
input [MS_TO_ES_BUS_WD -1:0] ms_to_es_bus,
input [WS_TO_ES_BUS_WD -1:0] ws_to_es_bus,
output [BR_BUS_WD -1:0] br_bus,
output data_sram_en,
output [ 3:0] data_sram_we,
output [31:0] data_sram_addr,
output [31:0] data_sram_wdata
);
reg [DS_TO_ES_BUS_WD -1:0] ds_to_es_bus_r;
wire [63:0] csr_vec;
wire [63:0] csr_vec_temp;
wire [ 6:0] csr_op;
wire csr_wdata_sel;
wire [13:0] csr_addr;
wire csr_we;
wire [11:0] alu_op;
wire [ 3:0] mul_div_op;
wire mul_div_sign;
wire [ 8:0] branch_op;
wire [ 2:0] store_op;
wire [ 5:0] load_op;
wire reg_we;
wire src1_is_pc;
wire src2_is_imm;
wire src2_is_4;
wire [ 4:0] rj;
wire [ 4:0] rkd;
wire [31:0] rj_value;
wire [31:0] rkd_value;
wire [ 4:0] dest;
wire [31:0] imm;
wire [31:0] es_pc;
wire [31:0] inst;
wire ms_reg_we;
wire [ 4:0] ms_dest;
wire [31:0] ms_result;
wire ws_reg_we;
wire [ 4:0] ws_dest;
wire [31:0] ws_result;
wire [31:0] src1;
wire [31:0] src2;
wire [31:0] alu_src1;
wire [31:0] alu_src2;
wire [31:0] alu_result;
wire br_taken;
wire [31:0] br_target;
wire br_flush;
wire data_sram_en_temp;
wire [ 3:0] data_sram_we_temp;
wire stallreq_for_mul_div;
wire [31:0] mul_div_result;
wire [31:0] es_result;
wire [31:0] csr_wdata;
wire [63:0] csr_bus;
wire excp_ale;
assign {csr_vec_temp ,//300:237
csr_op ,//236:230
csr_wdata_sel ,//229:229
csr_addr ,//228:215
csr_we ,//214:214
alu_op ,//213:202
mul_div_op ,//198:189
mul_div_sign ,//197:197
branch_op ,//196:188
store_op ,//187:185
load_op ,//184:179
reg_we ,//178:178
src1_is_pc ,//177:177
src2_is_imm ,//176:176
src2_is_4 ,//175:175
rj ,//174:170
rkd ,//169:165
rj_value ,//164:133
rkd_value ,//132:101
dest ,//100:96
imm ,//95 :64
es_pc ,//63 :32
inst //31 :0
} = ds_to_es_bus_r;
assign {ms_reg_we,
ms_dest,
ms_result
} = ms_to_es_bus;
assign {ws_reg_we,
ws_dest,
ws_result
} = ws_to_es_bus;
assign es_to_ms_bus = {csr_vec ,//270:207
csr_bus ,//206:143
load_op ,//142:137
store_op ,//136:134
reg_we ,//133:133
dest ,//132:128
es_result,//127:96
src1 ,//95 :64
es_pc ,//63 :32
inst //31 :0
};
assign br_flush = br_taken;
always @ (posedge clk) begin
if (reset) begin
ds_to_es_bus_r <= 0;
end
else if (flush) begin
ds_to_es_bus_r <= 0;
end
//nop, id stall and ex not stall
else if (stall[2]&(!stall[3])) begin
ds_to_es_bus_r <= 0;
end
//nop, id not stall and br_bus[32]
else if (!stall[2]&br_flush) begin
ds_to_es_bus_r <= 0;
end
// id not stall so can go on
else if (!stall[2]) begin
ds_to_es_bus_r <= ds_to_es_bus;
end
end
assign src1 = ms_reg_we & (ms_dest == rj ) & (rj != 1'b0) ? ms_result :
ws_reg_we & (ws_dest == rj ) & (rj != 1'b0) ? ws_result :
rj_value;
assign src2 = ms_reg_we & (ms_dest == rkd) & (rkd != 1'b0) ? ms_result :
ws_reg_we & (ws_dest == rkd) & (rkd != 1'b0) ? ws_result :
rkd_value;
assign alu_src1 = src1_is_pc ? es_pc :
src1;
assign alu_src2 = src2_is_4 ? 3'd4 :
src2_is_imm ? imm :
src2;
alu u_alu(
.alu_op (alu_op ),
.alu_src1 (alu_src1 ),
.alu_src2 (alu_src2 ),
.alu_result(alu_result)
);
bru u_bru(
.pc (es_pc ),
.rj_value (src1 ),
.rkd_value(src2 ),
.imm (imm ),
.branch_op(branch_op),
.br_taken (br_taken ),
.br_target(br_target)
);
wire csr_cancel;
reg csr_cancel_reg;
assign csr_cancel = flush ? 1'b0 : |csr_vec[31:0];// TODO!
always @ (posedge clk) begin
if (reset) begin
csr_cancel_reg <= 0;
end
else if (flush) begin
csr_cancel_reg <= 0;
end
else if (csr_cancel) begin
csr_cancel_reg <= 1;
end
end
assign br_bus = {br_taken & ~(csr_cancel|csr_cancel_reg),
br_target
};
lsu u_lsu(
.load_op (load_op ),
.store_op (store_op ),
.rj_value (src1 ),
.rkd_value (src2 ),
.imm (imm ),
.excp_ale (excp_ale ),
.data_sram_en (data_sram_en_temp),
.data_sram_we (data_sram_we_temp),
.data_sram_addr (data_sram_addr ),
.data_sram_wdata(data_sram_wdata )
);
assign data_sram_en = (csr_cancel|csr_cancel_reg) ? 1'b0 : data_sram_en_temp;
assign data_sram_we = {4{data_sram_en}} & data_sram_we_temp;
// mul_div
mul_div_top u_mul_div_top(
.clk (clk ),
.reset (reset | flush ),
.stall (stall ),
.stallreq (stallreq_for_mul_div),
.mul_div_op (mul_div_op ),
.mul_div_sign (mul_div_sign ),
.a (alu_src1 ),
.b (alu_src2 ),
.mul_div_result(mul_div_result )
);
assign es_result = (|mul_div_op ) ? mul_div_result :
(|load_op | |store_op) ? data_sram_addr :
alu_result;
assign csr_wdata = src2;
assign csr_bus = {csr_we,
csr_wdata_sel,
csr_op,
csr_addr,
csr_wdata
};
assign csr_vec = {csr_vec_temp[63:8], excp_ale, csr_vec_temp[6:0]};
assign stallreq_es = stallreq_for_mul_div;
endmodule

63
lacpu/rtl/mycpu/icache.v Normal file
View File

@@ -0,0 +1,63 @@
module icache
#(
parameter HIT_WD = 2,
parameter LRU_WD = 1,
parameter CACHELINE_WD = 512
)
(
input clk,
input reset,
input inst_sram_en,
input [ 3:0] inst_sram_we,
input [31:0] inst_sram_addr,
input [31:0] inst_sram_wdata,
input icache_refresh,
input [CACHELINE_WD -1:0] icache_cacheline_new,
output stallreq_icache,
output [31:0] inst_sram_rdata,
output icache_miss,
output [31:0] icache_raddr,
output [31:0] icache_waddr,
output [CACHELINE_WD -1:0] icache_cacheline_old
);
wire [HIT_WD -1:0] icache_hit;
wire [LRU_WD -1:0] icache_lru;
cache_tag_v5 u_icache_tag(
.clk (clk ),
.reset (reset ),
.flush (1'b0 ),
.stallreq (stallreq_icache ),
.cached (1'b1 ),
.sram_en (inst_sram_en/* & ~i_refill & ~i_invalid*/ ), // TODO!
.sram_we (inst_sram_we ),
.sram_addr (inst_sram_addr ), // _mmu ?
.refresh (icache_refresh ),
.miss (icache_miss ),
.axi_raddr (icache_raddr ),
.write_back (/*icache_write_back*/ ), // no use
.axi_waddr (icache_waddr ),
.hit (icache_hit ),
.lru (icache_lru )
);
cache_data_v5 u_icache_data(
.clk (clk ),
.reset (reset ),
.write_back (1'b0 ),
.hit (icache_hit ),
.lru (icache_lru ),
.cached (1'b1 ),
.sram_en (inst_sram_en/* & ~i_refill & ~i_invalid*/ ), // TODO!
.sram_we (inst_sram_we ),
.sram_addr (inst_sram_addr ),
.sram_wdata (inst_sram_wdata ),
.sram_rdata (inst_sram_rdata ),
.refresh (icache_refresh ),
.cacheline_new (icache_cacheline_new ),
.cacheline_old (icache_cacheline_old )
);
endmodule

257
lacpu/rtl/mycpu/id_stage.v Normal file
View File

@@ -0,0 +1,257 @@
module id_stage
#(
parameter FS_TO_DS_BUS_WD = 65,
parameter DS_TO_ES_BUS_WD = 301,
parameter WS_TO_RF_BUS_WD = 38
)
(
input clk,
input reset,
input flush,
input [ 5:0] stall,
input br_taken,
output stallreq_ds,
input pc_valid,
input [31:0] inst_sram_rdata,
input [ 1:0] csr_plv,
input csr_has_int,
input [FS_TO_DS_BUS_WD -1:0] fs_to_ds_bus,
input [WS_TO_RF_BUS_WD -1:0] ws_to_rf_bus,
output [DS_TO_ES_BUS_WD -1:0] ds_to_es_bus
);
reg [FS_TO_DS_BUS_WD -1:0] fs_to_ds_bus_r;
reg pc_valid_r;
reg [31:0] inst_r;
reg stall_flag;
reg [ 6:0] ex_load_buffer;
reg ex_csr_buffer;
wire br_flush;
wire [31:0] ds_pc;
wire src1_is_pc;
wire src2_is_imm;
wire src2_is_4;
wire src_reg_is_rd;
wire [ 4:0] rj;
wire [ 4:0] rk;
wire [ 4:0] rd;
wire [ 4:0] rkd;
wire [31:0] imm;
wire [ 4:0] dest;
wire [11:0] alu_op;
wire [ 3:0] mul_div_op;
wire mul_div_sign;
wire [ 8:0] branch_op;
wire [ 5:0] load_op;
wire [ 2:0] store_op;
wire reg_we;
wire csr_we;
wire [ 6:0] csr_op;
wire [13:0] csr_addr;
wire csr_wdata_sel;
wire [31:0] inst;
wire [31:0] next_inst;
wire [ 4:0] rf_raddr1;
wire [31:0] rf_rdata1;
wire [ 4:0] rf_raddr2;
wire [31:0] rf_rdata2;
wire rf_we;
wire [ 4:0] rf_waddr;
wire [31:0] rf_wdata;
wire [31:0] rj_value;
wire [31:0] rkd_value;
wire [ 4:0] ex_rf_waddr;
wire ex_is_load;
wire ex_is_csr;
wire ex_rf_we;
wire stallreq_load;
wire stallreq_csr;
wire excp_adef;
wire [31:0] csr_vec_h;
wire [31:0] csr_vec_l;
wire [63:0] csr_vec;
assign {csr_vec_h,
excp_adef,
ds_pc
} = fs_to_ds_bus_r;
assign csr_vec = {csr_vec_h, csr_vec_l};
assign br_flush = br_taken;
assign {rf_we , //37:37
rf_waddr, //36:32
rf_wdata //31:0
} = ws_to_rf_bus;
assign ds_to_es_bus = {csr_vec & {64{pc_valid_r}} ,//300:237
csr_op ,//236:230
csr_wdata_sel ,//229:229
csr_addr ,//228:215
csr_we ,//214:214
alu_op ,//213:202
mul_div_op & {4{pc_valid_r}} ,//198:189
mul_div_sign & pc_valid_r ,//197:197
branch_op & {9{pc_valid_r}} ,//196:188
store_op & {3{pc_valid_r}} ,//187:185
load_op & {6{pc_valid_r}} ,//184:179
reg_we & pc_valid_r ,//178:178
src1_is_pc ,//177:177
src2_is_imm ,//176:176
src2_is_4 ,//175:175
rj ,//174:170
rkd ,//169:165
rj_value ,//164:133
rkd_value ,//132:101
dest ,//100:96
imm ,//95 :64
ds_pc ,//63 :32
inst & {32{pc_valid_r}} //31 :0
};
always @ (posedge clk)begin
if (reset) begin
pc_valid_r <= 1'b0;
fs_to_ds_bus_r <= 0;
end
else if (flush) begin
pc_valid_r <= 1'b0;
fs_to_ds_bus_r <= 0;
end
//nop, ID stall and EX not stall
else if (stall[1] & (!stall[2]))begin
pc_valid_r <= 1'b0;
fs_to_ds_bus_r <= 0;
end
//nop, ID not stall but branch
else if (!stall[1] & br_flush) begin
pc_valid_r <= 1'b0;
fs_to_ds_bus_r <= 0;
end
// ID not stall so go on
else if (!stall[1]) begin
pc_valid_r <= pc_valid;
fs_to_ds_bus_r <= fs_to_ds_bus;
end
end
always @ (posedge clk) begin
if (reset) begin
inst_r <= 64'b0;
stall_flag <= 1'b0;
end
else if (flush) begin
inst_r <= 64'b0;
stall_flag <= 1'b0;
end
//if not stall, get inst from inst_sram
else if (!stall[1]) begin
inst_r <= inst_sram_rdata;
stall_flag <= 1'b0;
end
else if (stall_flag) begin
end
//if stall and id stall, get inst from inst_ram ?
else if (stall[1]&stall[2]) begin
inst_r <= inst_sram_rdata;
stall_flag <= 1'b1;
end
end
assign next_inst = stall_flag ? inst_r : inst_sram_rdata;
assign inst = ~pc_valid_r ? 32'b0 : next_inst;
inst_decoder u_inst_decoder(
.inst (inst ),
.src1_is_pc (src1_is_pc ),
.src2_is_imm (src2_is_imm ),
.src2_is_4 (src2_is_4 ),
.src_reg_is_rd (src_reg_is_rd ),
.rj (rj ),
.rk (rk ),
.rd (rd ),
.imm (imm ),
.dest (dest ),
.alu_op (alu_op ),
.mul_div_op (mul_div_op ),
.mul_div_sign (mul_div_sign ),
.branch_op (branch_op ),
.load_op (load_op ),
.store_op (store_op ),
.excp_adef (excp_adef ),
.csr_plv (csr_plv ),
.csr_has_int (csr_has_int ),
.csr_we (csr_we ),
.csr_op (csr_op ),
.csr_addr (csr_addr ),
.csr_wdata_sel (csr_wdata_sel ),
.csr_vec_l (csr_vec_l ),
.reg_we (reg_we )
);
assign rf_raddr1 = rj;
assign rf_raddr2 = src_reg_is_rd ? rd : rk;
assign rkd = src_reg_is_rd ? rd : rk;
regfile u_regfile(
.clk (clk ),
.reset (reset ),
.raddr1 (rf_raddr1),
.rdata1 (rf_rdata1),
.raddr2 (rf_raddr2),
.rdata2 (rf_rdata2),
.we (rf_we ),
.waddr (rf_waddr ),
.wdata (rf_wdata )
);
assign rj_value = rf_rdata1;
assign rkd_value = rf_rdata2;
always @ (posedge clk) begin
if (reset) begin
ex_load_buffer <= 7'b0;
ex_csr_buffer <= 1'b0;
end
else if (flush) begin
ex_load_buffer <= 7'b0;
ex_csr_buffer <= 1'b0;
end
else if (stall[2]&(!stall[3])) begin
ex_load_buffer <= 7'b0;
ex_csr_buffer <= 1'b0;
end
else if (!stall[2]) begin
ex_load_buffer <= {|load_op, rf_we, rf_waddr};
ex_csr_buffer <= |csr_op;
end
end
assign {ex_is_load,
ex_rf_we,
ex_rf_waddr
} = ex_load_buffer;
assign ex_is_csr = ex_csr_buffer;
//ex段为load指令且发生数据相关时id段需要被暂停
assign stallreq_load = ex_is_load & ex_rf_we & ((ex_rf_waddr==rj_value & rj_value!=0)|(ex_rf_waddr==rkd_value & rkd_value!=0));
assign stallreq_csr = ex_is_csr & ex_rf_we & ((ex_rf_waddr==rj_value & rj_value!=0)|(ex_rf_waddr==rkd_value & rkd_value!=0));
assign stallreq_ds = stallreq_load | stallreq_csr;
endmodule

View File

@@ -0,0 +1,76 @@
module if_stage
#(
parameter BR_BUS_WD = 33,
parameter FS_TO_DS_BUS_WD = 65
)
(
input clk ,
input reset,
input flush,
input [ 5:0] stall,
input [31:0] new_pc,
input timer_int,
output inst_sram_en ,
output [ 3:0] inst_sram_we ,
output [31:0] inst_sram_addr ,
output [31:0] inst_sram_wdata,
input [BR_BUS_WD -1:0] br_bus,
output [FS_TO_DS_BUS_WD -1:0] fs_to_ds_bus
);
reg pc_valid;
reg [31:0] fs_pc;
reg excp_adef;
reg [31:0] csr_vec_h;
wire [31:0] seq_pc;
wire [31:0] next_pc;
wire br_taken;
wire [31:0] br_target;
assign fs_to_ds_bus = {csr_vec_h, //64:33
excp_adef, //32:32
fs_pc //31:0
};
assign {br_taken,
br_target
} = br_bus;
always @ (posedge clk) begin
if (reset) begin
pc_valid <= 1'b0;
fs_pc <= 32'h1bff_fffc;
excp_adef <= 1'b0;
csr_vec_h <= 32'b0;
end
else if (flush) begin
pc_valid <= 1'b1;
fs_pc <= new_pc;
excp_adef <= |new_pc[1:0];
csr_vec_h <= 32'b0;
end
else if (!stall[0]) begin
pc_valid <= 1'b1;
fs_pc <= next_pc;
excp_adef <= |next_pc[1:0];
csr_vec_h <= 0; // timer_int; TODO!
end
end
assign seq_pc = fs_pc + 3'h4;
assign next_pc = br_taken ? br_target : seq_pc;
assign inst_sram_en = flush | (br_taken ? 1'b0 : pc_valid);
assign inst_sram_we = 4'h0;
assign inst_sram_addr = fs_pc;
assign inst_sram_wdata = 32'b0;
endmodule

View File

@@ -0,0 +1,545 @@
module inst_decoder(
input [31:0] inst,
output src1_is_pc,
output src2_is_imm,
output src2_is_4,
output src_reg_is_rd,
output [ 4:0] rj,
output [ 4:0] rk,
output [ 4:0] rd,
output [31:0] imm,
output [ 4:0] dest,
// alu
output [11:0] alu_op,
// mul div
output [ 3:0] mul_div_op,
output mul_div_sign,
// branch
output [ 8:0] branch_op,
output [ 5:0] load_op,
output [ 2:0] store_op,
// csr
input excp_adef,
input [ 1:0] csr_plv,
input csr_has_int,
output csr_we,
output [ 6:0] csr_op,
output [13:0] csr_addr,
output csr_wdata_sel,
output [31:0] csr_vec_l,
//output [ 3:0] sel_rf_res,
output reg_we
);
wire dest_is_r1;
wire dest_is_rj;
wire [ 5:0] op_31_26;
wire [ 3:0] op_25_22;
wire [ 1:0] op_21_20;
wire [ 4:0] op_19_15;
wire [63:0] op_31_26_d;
wire [15:0] op_25_22_d;
wire [ 3:0] op_21_20_d;
wire [31:0] op_19_15_d;
wire [31:0] rd_d;
wire [31:0] rj_d;
wire [31:0] rk_d;
wire [11:0] i12;
wire [13:0] i14;
wire [19:0] i20;
wire [15:0] i16;
wire [25:0] i26;
wire [13:0] csr_idx;
wire inst_add_w;
wire inst_sub_w;
wire inst_slt;
wire inst_sltu;
wire inst_nor;
wire inst_and;
wire inst_or;
wire inst_xor;
wire inst_lu12i_w;
wire inst_addi_w;
wire inst_slti;
wire inst_sltui;
wire inst_pcaddi;
wire inst_pcaddu12i;
//wire inst_andn;
//wire inst_orn;
wire inst_andi;
wire inst_ori;
wire inst_xori;
wire inst_mul_w;
wire inst_mulh_w;
wire inst_mulh_wu;
wire inst_div_w;
wire inst_mod_w;
wire inst_div_wu;
wire inst_mod_wu;
wire inst_slli_w;
wire inst_srli_w;
wire inst_srai_w;
wire inst_sll_w;
wire inst_srl_w;
wire inst_sra_w;
wire inst_jirl;
wire inst_b;
wire inst_bl;
wire inst_beq;
wire inst_bne;
wire inst_blt;
wire inst_bge;
wire inst_bltu;
wire inst_bgeu;
wire inst_ll_w;
wire inst_sc_w;
wire inst_ld_b;
wire inst_ld_bu;
wire inst_ld_h;
wire inst_ld_hu;
wire inst_ld_w;
wire inst_st_b;
wire inst_st_h;
wire inst_st_w;
wire inst_syscall;
wire inst_break;
wire inst_csrrd;
wire inst_csrwr;
wire inst_csrxchg;
wire inst_ertn;
wire inst_rdcntid_w;
wire inst_rdcntvl_w;
wire inst_rdcntvh_w;
//wire inst_idle;
//wire inst_tlbsrch;
//wire inst_tlbrd;
//wire inst_tlbwr;
//wire inst_tlbfill;
//wire inst_invtlb;
//wire inst_cacop;
//wire inst_preld;
wire inst_dbar;
wire inst_ibar;
wire need_ui5;
wire need_si12;
wire need_ui12;
wire need_si14_pc;
wire need_si16_pc;
wire need_si20;
wire need_si20_pc;
wire need_si26_pc;
wire inst_valid;
wire excp_ine;
wire kernel_inst;
wire excp_ipe;
assign op_31_26 = inst[31:26];
assign op_25_22 = inst[25:22];
assign op_21_20 = inst[21:20];
assign op_19_15 = inst[19:15];
assign rd = inst[ 4: 0];
assign rj = inst[ 9: 5];
assign rk = inst[14:10];
assign i12 = inst[21:10];
assign i14 = inst[23:10];
assign i20 = inst[24: 5];
assign i16 = inst[25:10];
assign i26 = {inst[ 9: 0], inst[25:10]};
assign csr_idx = inst[23:10];
decoder_6_64 u_dec0(.in(op_31_26 ), .out(op_31_26_d ));
decoder_4_16 u_dec1(.in(op_25_22 ), .out(op_25_22_d ));
decoder_2_4 u_dec2(.in(op_21_20 ), .out(op_21_20_d ));
decoder_5_32 u_dec3(.in(op_19_15 ), .out(op_19_15_d ));
decoder_5_32 u_dec4(.in(rd ), .out(rd_d ));
decoder_5_32 u_dec5(.in(rj ), .out(rj_d ));
decoder_5_32 u_dec6(.in(rk ), .out(rk_d ));
assign inst_add_w = op_31_26_d[6'h00] & op_25_22_d[4'h0] & op_21_20_d[2'h1] & op_19_15_d[5'h00];
assign inst_sub_w = op_31_26_d[6'h00] & op_25_22_d[4'h0] & op_21_20_d[2'h1] & op_19_15_d[5'h02];
assign inst_slt = op_31_26_d[6'h00] & op_25_22_d[4'h0] & op_21_20_d[2'h1] & op_19_15_d[5'h04];
assign inst_sltu = op_31_26_d[6'h00] & op_25_22_d[4'h0] & op_21_20_d[2'h1] & op_19_15_d[5'h05];
assign inst_nor = op_31_26_d[6'h00] & op_25_22_d[4'h0] & op_21_20_d[2'h1] & op_19_15_d[5'h08];
assign inst_and = op_31_26_d[6'h00] & op_25_22_d[4'h0] & op_21_20_d[2'h1] & op_19_15_d[5'h09];
assign inst_or = op_31_26_d[6'h00] & op_25_22_d[4'h0] & op_21_20_d[2'h1] & op_19_15_d[5'h0a];
assign inst_xor = op_31_26_d[6'h00] & op_25_22_d[4'h0] & op_21_20_d[2'h1] & op_19_15_d[5'h0b];
//assign inst_orn = op_31_26_d[6'h00] & op_25_22_d[4'h0] & op_21_20_d[2'h1] & op_19_15_d[5'h0c];
//assign inst_andn = op_31_26_d[6'h00] & op_25_22_d[4'h0] & op_21_20_d[2'h1] & op_19_15_d[5'h0d];
assign inst_sll_w = op_31_26_d[6'h00] & op_25_22_d[4'h0] & op_21_20_d[2'h1] & op_19_15_d[5'h0e];
assign inst_srl_w = op_31_26_d[6'h00] & op_25_22_d[4'h0] & op_21_20_d[2'h1] & op_19_15_d[5'h0f];
assign inst_sra_w = op_31_26_d[6'h00] & op_25_22_d[4'h0] & op_21_20_d[2'h1] & op_19_15_d[5'h10];
assign inst_mul_w = op_31_26_d[6'h00] & op_25_22_d[4'h0] & op_21_20_d[2'h1] & op_19_15_d[5'h18];
assign inst_mulh_w = op_31_26_d[6'h00] & op_25_22_d[4'h0] & op_21_20_d[2'h1] & op_19_15_d[5'h19];
assign inst_mulh_wu = op_31_26_d[6'h00] & op_25_22_d[4'h0] & op_21_20_d[2'h1] & op_19_15_d[5'h1a];
assign inst_div_w = op_31_26_d[6'h00] & op_25_22_d[4'h0] & op_21_20_d[2'h2] & op_19_15_d[5'h00];
assign inst_mod_w = op_31_26_d[6'h00] & op_25_22_d[4'h0] & op_21_20_d[2'h2] & op_19_15_d[5'h01];
assign inst_div_wu = op_31_26_d[6'h00] & op_25_22_d[4'h0] & op_21_20_d[2'h2] & op_19_15_d[5'h02];
assign inst_mod_wu = op_31_26_d[6'h00] & op_25_22_d[4'h0] & op_21_20_d[2'h2] & op_19_15_d[5'h03];
assign inst_break = op_31_26_d[6'h00] & op_25_22_d[4'h0] & op_21_20_d[2'h2] & op_19_15_d[5'h14];
assign inst_syscall = op_31_26_d[6'h00] & op_25_22_d[4'h0] & op_21_20_d[2'h2] & op_19_15_d[5'h16];
assign inst_slli_w = op_31_26_d[6'h00] & op_25_22_d[4'h1] & op_21_20_d[2'h0] & op_19_15_d[5'h01];
assign inst_srli_w = op_31_26_d[6'h00] & op_25_22_d[4'h1] & op_21_20_d[2'h0] & op_19_15_d[5'h09];
assign inst_srai_w = op_31_26_d[6'h00] & op_25_22_d[4'h1] & op_21_20_d[2'h0] & op_19_15_d[5'h11];
//assign inst_idle = op_31_26_d[6'h01] & op_25_22_d[4'h9] & op_21_20_d[2'h0] & op_19_15_d[5'h11];
//assign inst_invtlb = op_31_26_d[6'h01] & op_25_22_d[4'h9] & op_21_20_d[2'h0] & op_19_15_d[5'h13];
assign inst_dbar = op_31_26_d[6'h0e] & op_25_22_d[4'h1] & op_21_20_d[2'h3] & op_19_15_d[5'h04];
assign inst_ibar = op_31_26_d[6'h0e] & op_25_22_d[4'h1] & op_21_20_d[2'h3] & op_19_15_d[5'h05];
assign inst_slti = op_31_26_d[6'h00] & op_25_22_d[4'h8];
assign inst_sltui = op_31_26_d[6'h00] & op_25_22_d[4'h9];
assign inst_addi_w = op_31_26_d[6'h00] & op_25_22_d[4'ha];
assign inst_andi = op_31_26_d[6'h00] & op_25_22_d[4'hd];
assign inst_ori = op_31_26_d[6'h00] & op_25_22_d[4'he];
assign inst_xori = op_31_26_d[6'h00] & op_25_22_d[4'hf];
assign inst_ld_b = op_31_26_d[6'h0a] & op_25_22_d[4'h0];
assign inst_ld_h = op_31_26_d[6'h0a] & op_25_22_d[4'h1];
assign inst_ld_w = op_31_26_d[6'h0a] & op_25_22_d[4'h2];
assign inst_st_b = op_31_26_d[6'h0a] & op_25_22_d[4'h4];
assign inst_st_h = op_31_26_d[6'h0a] & op_25_22_d[4'h5];
assign inst_st_w = op_31_26_d[6'h0a] & op_25_22_d[4'h6];
assign inst_ld_bu = op_31_26_d[6'h0a] & op_25_22_d[4'h8];
assign inst_ld_hu = op_31_26_d[6'h0a] & op_25_22_d[4'h9];
//assign inst_cacop = op_31_26_d[6'h01] & op_25_22_d[4'h8];
//assign inst_preld = op_31_26_d[6'h0a] & op_25_22_d[4'hb];
assign inst_jirl = op_31_26_d[6'h13];
assign inst_b = op_31_26_d[6'h14];
assign inst_bl = op_31_26_d[6'h15];
assign inst_beq = op_31_26_d[6'h16];
assign inst_bne = op_31_26_d[6'h17];
assign inst_blt = op_31_26_d[6'h18];
assign inst_bge = op_31_26_d[6'h19];
assign inst_bltu = op_31_26_d[6'h1a];
assign inst_bgeu = op_31_26_d[6'h1b];
assign inst_lu12i_w = op_31_26_d[6'h05] & ~inst[25];
assign inst_pcaddi = op_31_26_d[6'h06] & ~inst[25];
assign inst_pcaddu12i = op_31_26_d[6'h07] & ~inst[25];
assign inst_csrxchg = op_31_26_d[6'h01] & ~inst[25] & ~inst[24] & (~rj_d[5'h00] & ~rj_d[5'h01]); //rj != 0,1
assign inst_ll_w = op_31_26_d[6'h08] & ~inst[25] & ~inst[24];
assign inst_sc_w = op_31_26_d[6'h08] & ~inst[25] & inst[24];
assign inst_csrrd = op_31_26_d[6'h01] & ~inst[25] & ~inst[24] & rj_d[5'h00];
assign inst_csrwr = op_31_26_d[6'h01] & ~inst[25] & ~inst[24] & rj_d[5'h01];
assign inst_rdcntid_w = op_31_26_d[6'h00] & op_25_22_d[4'h0] & op_21_20_d[2'h0] & op_19_15_d[5'h00] & rk_d[5'h18] & rd_d[5'h00];
assign inst_rdcntvl_w = op_31_26_d[6'h00] & op_25_22_d[4'h0] & op_21_20_d[2'h0] & op_19_15_d[5'h00] & rk_d[5'h18] & rj_d[5'h00] & !rd_d[5'h00];
assign inst_rdcntvh_w = op_31_26_d[6'h00] & op_25_22_d[4'h0] & op_21_20_d[2'h0] & op_19_15_d[5'h00] & rk_d[5'h19] & rj_d[5'h00];
assign inst_ertn = op_31_26_d[6'h01] & op_25_22_d[4'h9] & op_21_20_d[2'h0] & op_19_15_d[5'h10] & rk_d[5'h0e] & rj_d[5'h00] & rd_d[5'h00];
//assign inst_tlbsrch = op_31_26_d[6'h01] & op_25_22_d[4'h9] & op_21_20_d[2'h0] & op_19_15_d[5'h10] & rk_d[5'h0a] & rj_d[5'h00] & rd_d[5'h00];
//assign inst_tlbrd = op_31_26_d[6'h01] & op_25_22_d[4'h9] & op_21_20_d[2'h0] & op_19_15_d[5'h10] & rk_d[5'h0b] & rj_d[5'h00] & rd_d[5'h00];
//assign inst_tlbwr = op_31_26_d[6'h01] & op_25_22_d[4'h9] & op_21_20_d[2'h0] & op_19_15_d[5'h10] & rk_d[5'h0c] & rj_d[5'h00] & rd_d[5'h00];
//assign inst_tlbfill = op_31_26_d[6'h01] & op_25_22_d[4'h9] & op_21_20_d[2'h0] & op_19_15_d[5'h10] & rk_d[5'h0d] & rj_d[5'h00] & rd_d[5'h00];
assign src_reg_is_rd = inst_beq |
inst_bne |
inst_blt |
inst_bltu |
inst_bge |
inst_bgeu |
inst_st_b |
inst_st_h |
inst_st_w |
inst_sc_w |
inst_csrwr |
inst_csrxchg;
assign src1_is_pc = inst_jirl |
inst_bl |
inst_pcaddi |
inst_pcaddu12i;
assign src2_is_imm = inst_slli_w |
inst_srli_w |
inst_srai_w |
inst_addi_w |
inst_slti |
inst_sltui |
inst_andi |
inst_ori |
inst_xori |
inst_pcaddi |
inst_pcaddu12i |
inst_ld_b |
inst_ld_h |
inst_ld_w |
inst_ld_bu |
inst_ld_hu |
inst_st_b |
inst_st_h |
inst_st_w |
inst_ll_w |
inst_sc_w |
inst_lu12i_w ;
//inst_cacop |
//inst_preld ;
assign src2_is_4 = inst_jirl |
inst_bl;
assign dest_is_r1 = inst_bl;
assign dest_is_rj = inst_rdcntid_w;
assign dest = (dest_is_r1) ? 5'd1 :
(dest_is_rj) ? rj :
rd;
// alu_op
assign alu_op[ 0] = inst_add_w |
inst_addi_w |
//inst_ld_b |
//inst_ld_h |
//inst_ld_w |
//inst_st_b |
//inst_st_h |
//inst_st_w |
//inst_ld_bu |
//inst_ld_hu |
//inst_ll_w |
//inst_sc_w |
inst_jirl |
inst_bl |
inst_pcaddi |
inst_pcaddu12i;
//inst_cacop |
//inst_preld ;
assign alu_op[ 1] = inst_sub_w;
assign alu_op[ 2] = inst_slt | inst_slti;
assign alu_op[ 3] = inst_sltu | inst_sltui;
assign alu_op[ 4] = inst_and | inst_andi;
assign alu_op[ 5] = inst_nor;
assign alu_op[ 6] = inst_or | inst_ori;
assign alu_op[ 7] = inst_xor | inst_xori;
assign alu_op[ 8] = inst_sll_w | inst_slli_w;
assign alu_op[ 9] = inst_srl_w | inst_srli_w;
assign alu_op[10] = inst_sra_w | inst_srai_w;
assign alu_op[11] = inst_lu12i_w;
//assign alu_op[12] = inst_andn;
//assign alu_op[13] = inst_orn;
// imm
assign need_ui5 = inst_slli_w | inst_srli_w | inst_srai_w;
assign need_si12 = inst_addi_w |
inst_ld_b |
inst_ld_h |
inst_ld_w |
inst_st_b |
inst_st_h |
inst_st_w |
inst_ld_bu |
inst_ld_hu |
inst_slti |
inst_sltui;
//inst_cacop |
//inst_preld ;
assign need_ui12 = inst_andi | inst_ori | inst_xori;
assign need_si14_pc = inst_ll_w | inst_sc_w;
assign need_si16_pc = inst_jirl |
inst_beq |
inst_bne |
inst_blt |
inst_bge |
inst_bltu |
inst_bgeu;
assign need_si20 = inst_lu12i_w | inst_pcaddu12i;
assign need_si20_pc = inst_pcaddi;
assign need_si26_pc = inst_b | inst_bl;
assign imm = ({32{need_ui5 }} & {27'b0, rk} ) |
({32{need_si12 }} & {{20{i12[11]}}, i12} ) |
({32{need_ui12 }} & {20'b0, i12} ) |
({32{need_si14_pc}} & {{16{i14[13]}}, i14, 2'b0}) |
({32{need_si16_pc}} & {{14{i16[15]}}, i16, 2'b0}) |
({32{need_si20 }} & {i20, 12'b0} ) |
({32{need_si20_pc}} & {{10{i20[19]}}, i20, 2'b0}) |
({32{need_si26_pc}} & {{ 4{i26[25]}}, i26, 2'b0}) ;
// mul_div
assign mul_div_op[ 0] = inst_mul_w;
assign mul_div_op[ 1] = inst_mulh_w | inst_mulh_wu;
assign mul_div_op[ 2] = inst_div_w | inst_div_wu;
assign mul_div_op[ 3] = inst_mod_w | inst_mod_wu;
assign mul_div_sign = inst_mul_w | inst_mulh_w | inst_div_w | inst_mod_w;
// branch_op
assign branch_op = {inst_beq,
inst_bne,
inst_blt,
inst_bge,
inst_bltu,
inst_bgeu,
inst_jirl,
inst_bl,
inst_b
};
// load_op store_op
assign load_op = {inst_ld_b,
inst_ld_h,
inst_ld_w,
inst_ld_bu,
inst_ld_hu,
inst_ll_w
};
assign store_op = {inst_st_b,
inst_st_h,
inst_st_w
};
assign reg_we = ~inst_st_b &
~inst_st_h &
~inst_st_w &
~inst_beq &
~inst_bne &
~inst_blt &
~inst_bge &
~inst_bltu &
~inst_bgeu &
~inst_b &
~inst_syscall &
//~inst_tlbsrch &
//~inst_tlbrd &
//~inst_tlbwr &
//~inst_tlbfill &
//~inst_invtlb &
//~inst_cacop &
//~inst_preld &
~inst_dbar &
~inst_ibar ;
// csr
assign csr_we = inst_csrwr | inst_csrxchg;
assign csr_op = {inst_csrrd,
inst_csrwr,
inst_csrxchg,
inst_rdcntid_w,
inst_rdcntvh_w,
inst_rdcntvl_w,
inst_sc_w
};
assign csr_addr = inst[23:10];
assign csr_wdata_sel = inst_csrxchg;
assign csr_vec_l = {25'b0, excp_adef, excp_ipe, excp_ine, inst_break, inst_syscall, inst_ertn, csr_has_int};
assign inst_valid = inst_add_w |
inst_sub_w |
inst_slt |
inst_sltu |
inst_nor |
inst_and |
inst_or |
inst_xor |
inst_sll_w |
inst_srl_w |
inst_sra_w |
inst_mul_w |
inst_mulh_w |
inst_mulh_wu |
inst_div_w |
inst_mod_w |
inst_div_wu |
inst_mod_wu |
inst_break |
inst_syscall |
inst_slli_w |
inst_srli_w |
inst_srai_w |
//inst_idle |
inst_slti |
inst_sltui |
inst_addi_w |
inst_andi |
inst_ori |
inst_xori |
inst_ld_b |
inst_ld_h |
inst_ld_w |
inst_st_b |
inst_st_h |
inst_st_w |
inst_ld_bu |
inst_ld_hu |
inst_ll_w |
inst_sc_w |
inst_jirl |
inst_b |
inst_bl |
inst_beq |
inst_bne |
inst_blt |
inst_bge |
inst_bltu |
inst_bgeu |
inst_lu12i_w |
inst_pcaddu12i |
inst_csrrd |
inst_csrwr |
inst_csrxchg |
inst_rdcntid_w |
inst_rdcntvh_w |
inst_rdcntvl_w |
inst_ertn |
//inst_cacop |
//inst_preld |
inst_dbar |
inst_ibar ;
//inst_tlbsrch |
//inst_tlbrd |
//inst_tlbwr |
//inst_tlbfill |
//(inst_invtlb && (rd == 5'd0 ||
// rd == 5'd1 ||
// rd == 5'd2 ||
// rd == 5'd3 ||
// rd == 5'd4 ||
// rd == 5'd5 ||
// rd == 5'd6 )); //invtlb valid op
assign excp_ine = ~inst_valid;
assign kernel_inst = inst_csrrd |
inst_csrwr |
inst_csrxchg |
//inst_cacop |
//inst_tlbsrch |
//inst_tlbrd |
//inst_tlbwr |
//inst_tlbfill |
//inst_invtlb |
inst_ertn ;
//inst_idle ;
assign excp_ipe = kernel_inst && (csr_plv == 2'b11);
// rf_res from
// assign sel_rf_res[0] = inst_jirl | inst_bl;
// assign sel_rf_res[1] = |load_op;
// assign sel_rf_res[2] = |csr_op;
// assign sel_rf_res[3] = |mul_div_op;
endmodule

63
lacpu/rtl/mycpu/lsu.v Normal file
View File

@@ -0,0 +1,63 @@
module lsu(
input [ 5:0] load_op,
input [ 2:0] store_op,
input [31:0] rj_value,
input [31:0] rkd_value,
input [31:0] imm,
output excp_ale,
output data_sram_en,
output [ 3:0] data_sram_we,
output [31:0] data_sram_addr,
output [31:0] data_sram_wdata
);
wire inst_ll_w;
wire inst_ld_b;
wire inst_ld_bu;
wire inst_ld_h;
wire inst_ld_hu;
wire inst_ld_w;
wire inst_st_b;
wire inst_st_h;
wire inst_st_w;
wire [31:0] addr;
wire [ 3:0] byte_sel;
assign {inst_ld_b,
inst_ld_h,
inst_ld_w,
inst_ld_bu,
inst_ld_hu,
inst_ll_w
} = load_op;
assign {inst_st_b,
inst_st_h,
inst_st_w
} = store_op;
assign addr = rj_value + imm;
decoder_2_4 u_decoder_2_4(
.in (addr[1:0]),
.out(byte_sel )
);
assign excp_ale = data_sram_en & (((inst_st_b | inst_ld_b | inst_ld_bu) & 1'b0 ) |
((inst_st_h | inst_ld_h | inst_ld_hu) & addr[0] ) |
((inst_st_w | inst_ld_w) & (|addr[1:0])));
assign data_sram_en = (|store_op) | (|load_op);
assign data_sram_we = inst_st_b ? byte_sel :
inst_st_h ? {{2{byte_sel[2]}}, {2{byte_sel[0]}}} :
inst_st_w ? { 4{byte_sel[0]}} :
4'b0;
assign data_sram_addr = addr;
assign data_sram_wdata = inst_st_b ? {4{rkd_value[ 7:0]}} :
inst_st_h ? {2{rkd_value[15:0]}} :
inst_st_w ? rkd_value :
32'b0;
endmodule

196
lacpu/rtl/mycpu/mem_stage.v Normal file
View File

@@ -0,0 +1,196 @@
module mem_stage
#(
parameter ES_TO_MS_BUS_WD = 271,
parameter MS_TO_ES_BUS_WD = 38,
parameter MS_TO_WS_BUS_WD = 102
)
(
input clk,
input reset,
input flush,
input [ 5:0] stall,
output except_en,
output [31:0] new_pc,
output [ 1:0] csr_plv,
output csr_has_int,
input stallreq_axi,
input [ES_TO_MS_BUS_WD -1:0] es_to_ms_bus,
output [MS_TO_ES_BUS_WD -1:0] ms_to_es_bus,
output [MS_TO_WS_BUS_WD -1:0] ms_to_ws_bus,
input [31:0] data_sram_rdata
);
reg [ES_TO_MS_BUS_WD -1:0] es_to_ms_bus_r;
reg [31:0] data_sram_rdata_r;
reg [31:0] csr_rdata_r;
reg stall_flag;
wire [63:0] csr_vec;
wire [63:0] csr_bus;
wire [ 5:0] load_op;
wire [ 2:0] store_op;
wire reg_we;
wire [ 4:0] dest;
wire [31:0] es_result;
wire [31:0] ms_pc;
wire [31:0] inst;
wire [31:0] data_temp;
wire [31:0] csr_result;
wire [31:0] csr_rdata;
wire inst_ll_w;
wire inst_ld_b;
wire inst_ld_bu;
wire inst_ld_h;
wire inst_ld_hu;
wire inst_ld_w;
wire [ 3:0] byte_sel;
wire [31:0] ms_result;
wire csr_we;
wire csr_wdata_sel;
wire [ 6:0] csr_op;
wire [13:0] csr_addr;
wire [31:0] csr_wdata;
wire [31:0] src1;
wire [31:0] ms_final_result;
assign {csr_vec ,//270:207
csr_bus ,//206:143
load_op ,//142:137
store_op ,//136:134
reg_we ,//133:133
dest ,//132:128
es_result,//127:96
src1 ,//95 :64
ms_pc ,//63 :32
inst //31 :0
} = es_to_ms_bus_r;
assign ms_to_es_bus = {reg_we,
dest,
ms_final_result
};
assign ms_to_ws_bus = {reg_we ,//101:101
dest ,//100:96
ms_final_result ,//95 :64
ms_pc ,//63 :32
inst //31 :0
};
always @ (posedge clk) begin
if (reset) begin
es_to_ms_bus_r <= 0;
end
else if (flush) begin
es_to_ms_bus_r <= 0;
end
else if (stall[3]&(!stall[4])) begin
es_to_ms_bus_r <= 0;
end
else if (!stall[3]) begin
es_to_ms_bus_r <= es_to_ms_bus;
end
end
always @ (posedge clk) begin
if (reset) begin
data_sram_rdata_r <= 0;
csr_rdata_r <= 0;
stall_flag <= 1'b0;
end
else if (flush) begin
data_sram_rdata_r <= 0;
csr_rdata_r <= 0;
stall_flag <= 1'b0;
end
else if (!stall[3]) begin
data_sram_rdata_r <= data_sram_rdata;
csr_rdata_r <= csr_rdata;
stall_flag <= 1'b0;
end
else if (stall_flag) begin
end
else if (stall[3]&stall[4])begin
data_sram_rdata_r <= data_sram_rdata;
csr_rdata_r <= csr_rdata;
stall_flag <= 1'b1;
end
end
assign data_temp = stall_flag ? data_sram_rdata_r : data_sram_rdata;
assign csr_result = stall_flag ? csr_rdata_r : csr_rdata;
assign {inst_ld_b,
inst_ld_h,
inst_ld_w,
inst_ld_bu,
inst_ld_hu,
inst_ll_w
} = load_op;
decoder_2_4 u_decoder_2_4(
.in (es_result[1:0]),
.out(byte_sel )
);
assign ms_result = (inst_ld_b & byte_sel[0]) ? {{24{data_temp[ 7]}}, data_temp[ 7: 0]} :
(inst_ld_b & byte_sel[1]) ? {{24{data_temp[15]}}, data_temp[15: 8]} :
(inst_ld_b & byte_sel[2]) ? {{24{data_temp[23]}}, data_temp[23:16]} :
(inst_ld_b & byte_sel[3]) ? {{24{data_temp[31]}}, data_temp[31:24]} :
(inst_ld_bu & byte_sel[0]) ? { 24'b0, data_temp[ 7: 0]} :
(inst_ld_bu & byte_sel[1]) ? { 24'b0, data_temp[15: 8]} :
(inst_ld_bu & byte_sel[2]) ? { 24'b0, data_temp[23:16]} :
(inst_ld_bu & byte_sel[3]) ? { 24'b0, data_temp[31:24]} :
(inst_ld_h & byte_sel[0]) ? {{16{data_temp[15]}}, data_temp[15: 0]} :
(inst_ld_h & byte_sel[2]) ? {{16{data_temp[31]}}, data_temp[31:16]} :
(inst_ld_hu & byte_sel[0]) ? { 16'b0, data_temp[15: 0]} :
(inst_ld_hu & byte_sel[2]) ? { 16'b0, data_temp[31:16]} :
(inst_ld_w & byte_sel[0]) ? data_temp :
32'b0; // inst_ll ?
assign {csr_we,
csr_wdata_sel,
csr_op,
csr_addr,
csr_wdata
} = csr_bus;
csr u_csr(
.clk (clk ),
.reset (reset ),
.stall (stall[3]&stall[4] ),
.pc (ms_pc ),
.src1 (src1 ),
.error_va (es_result ),
.plv_out (csr_plv ),
.has_int_out (csr_has_int ),
.csr_we (csr_we ),
.csr_vec (csr_vec ),
.csr_op (csr_op ),
.csr_addr (csr_addr ),
.csr_wdata_sel (csr_wdata_sel ),
.csr_wdata (csr_wdata ),
.csr_rdata (csr_rdata ),
.except_en (except_en ),
.new_pc (new_pc ),
.stallreq_axi (stallreq_axi )
);
assign ms_final_result = (|load_op) ? ms_result :
(|csr_op ) ? csr_result :
es_result;
endmodule

21
lacpu/rtl/mycpu/mmu.v Normal file
View File

@@ -0,0 +1,21 @@
module mmu (
input [31:0] addr_i,
output [31:0] addr_o,
output cache_v
);
wire [1:0] addr_head_i, addr_head_o;
assign addr_head_i = addr_i[31:30];
wire kseg0_l, kseg0_h, kseg1_l, kseg1_h;
assign kseg0_l = addr_head_i == 2'b00;
assign kseg0_h = addr_head_i == 2'b01;
assign kseg1_l = addr_head_i == 2'b10;
assign kseg1_h = addr_head_i == 2'b11;
wire other_seg;
assign other_seg = ~kseg0_l & ~kseg0_h & ~kseg1_l & ~kseg1_h;
assign addr_head_o = {2{kseg0_l}}&2'b00 | {2{kseg0_h}}&2'b01 | {2{kseg1_l}}&2'b10 | {2{kseg1_h}}&2'b11 | {2{other_seg}}&addr_head_i;
assign addr_o = {addr_head_o, addr_i[29:0]};
assign cache_v = ~(kseg0_l|kseg1_l|kseg1_h);
endmodule

47
lacpu/rtl/mycpu/mul.v Normal file
View File

@@ -0,0 +1,47 @@
module mul(
input clk,
input reset,
output stallreq,
input in_valid,
output out_valid,
input [31:0] a,
input [31:0] b,
output reg [31:0] result_h,
output reg [31:0] result_l
);
reg [ 5:0] cnt;
wire [31:0] add_result;
wire carry;
always @ (posedge clk) begin
if (reset) begin
cnt <= 0;
end
else if (cnt != 0) begin
cnt <= cnt - 1;
end
else if (in_valid) begin
cnt <= 32;
end
end
assign {carry, add_result} = result_h + (result_l[0] ? a : 0);
always @ (posedge clk) begin
if (reset) begin
result_h <= 0;
result_l <= 0;
end
else if (cnt != 0) begin
{result_h, result_l} <= {carry, add_result, result_l[31:1]};
end
else if (in_valid) begin
result_h <= 0;
result_l <= b;
end
end
assign out_valid = (cnt==0);
assign stallreq = in_valid | (~(cnt==0));
endmodule

View File

@@ -0,0 +1,66 @@
module mul_div_lock (
input clk,
input reset,
input [ 5:0] stall,
input [31:0] a,
input [31:0] b,
input mul_en,
input div_en,
input stallreq_for_mul,
input stallreq_for_div,
output [31:0] a_locked,
output [31:0] b_locked,
output mul_en_locked,
output div_en_locked
);
reg first_enable;
reg mul_en_musk;
reg div_en_musk;
reg [31:0] a_buffer;
reg [31:0] b_buffer;
wire stallreq = stallreq_for_mul | stallreq_for_div;
assign mul_en_locked = mul_en & mul_en_musk;
assign div_en_locked = div_en & div_en_musk;
assign a_locked = first_enable ? a : a_buffer;
assign b_locked = first_enable ? b : b_buffer;
always @ (posedge clk) begin
if (reset) begin
a_buffer <= 0;
b_buffer <= 0;
mul_en_musk <= 1;
div_en_musk <= 1;
first_enable <= 1;
end
else if (mul_en & first_enable) begin
a_buffer <= a;
b_buffer <= b;
mul_en_musk <= 0;
div_en_musk <= 1;
first_enable <= 0;
end
else if (div_en & first_enable) begin
a_buffer <= a;
b_buffer <= b;
mul_en_musk <= 1;
div_en_musk <= 0;
first_enable <= 0;
end
else if (!stallreq & (mul_en|div_en) & !first_enable & !stall[2]) begin
a_buffer <= 0;
b_buffer <= 0;
mul_en_musk <= 1;
div_en_musk <= 1;
first_enable <= 1;
end
end
endmodule

View File

@@ -0,0 +1,87 @@
module mul_div_top(
input clk,
input reset,
input [ 5:0] stall,
output stallreq,
input [ 3:0] mul_div_op,
input mul_div_sign,
input [31:0] a,
input [31:0] b,
output [31:0] mul_div_result
);
wire stallreq_for_mul;
wire stallreq_for_div;
wire sign_flag;
wire [31:0] src_a;
wire [31:0] src_b;
wire [31:0] result_h;
wire [31:0] result_l;
wire [31:0] quotient;
wire [31:0] remainder;
wire mul_en;
wire div_en;
wire [31:0] a_locked;
wire [31:0] b_locked;
wire mul_en_locked;
wire div_en_locked;
assign mul_en = mul_div_op[0] | mul_div_op[1];
assign div_en = mul_div_op[2] | mul_div_op[3];
assign sign_flag = a[31] ^ b[31];
assign src_a = (mul_div_sign & a[31]) ? (~a[31:0] + 1'b1) : a;
assign src_b = (mul_div_sign & b[31]) ? (~b[31:0] + 1'b1) : b;
mul_div_lock u_mul_div_lock(
.clk (clk ),
.reset (reset ),
.stall (stall ),
.a (src_a ),
.b (src_b ),
.mul_en (mul_en ),
.div_en (div_en ),
.stallreq_for_mul (stallreq_for_mul ),
.stallreq_for_div (stallreq_for_div ),
.a_locked (a_locked ),
.b_locked (b_locked ),
.mul_en_locked (mul_en_locked ),
.div_en_locked (div_en_locked )
);
mul u_mul(
.clk (clk ),
.reset (reset ),
.stallreq (stallreq_for_mul),
.in_valid (mul_en_locked ),
.out_valid (),
.a (a_locked ),
.b (b_locked ),
.result_h (result_h ),
.result_l (result_l )
);
div u_div(
.clk (clk ),
.reset (reset ),
.stallreq (stallreq_for_div),
.in_valid (div_en_locked ),
.out_valid (),
.a (a_locked ),
.b (b_locked ),
.quotient (quotient ),
.remainder (remainder )
);
assign stallreq = stallreq_for_mul | stallreq_for_div;
assign mul_div_result = mul_div_op[0] ? (mul_div_sign & (a[31] ^ b[31]) & |result_l ) ? { ~result_l[31:0] + 1'b1} : result_l :
mul_div_op[1] ? (mul_div_sign & (a[31] ^ b[31]) & |result_h ) ? {a[31] ^ b[31], ~result_h[30:0] } : result_h :
mul_div_op[2] ? (mul_div_sign & (a[31] ^ b[31]) & |quotient ) ? {a[31] ^ b[31], ~quotient[30:0] + 1'b1} : quotient :
mul_div_op[3] ? (mul_div_sign & a[31] & |remainder) ? {a[31] , ~remainder[30:0] + 1'b1} : remainder :
32'b0;
endmodule

View File

@@ -0,0 +1,168 @@
`default_nettype wire
module mycpu_core
#(
parameter FS_TO_DS_BUS_WD = 65,
parameter DS_TO_ES_BUS_WD = 301,
parameter ES_TO_MS_BUS_WD = 271,
parameter MS_TO_WS_BUS_WD = 102,
parameter WS_TO_RF_BUS_WD = 38,
parameter MS_TO_ES_BUS_WD = 38,
parameter WS_TO_ES_BUS_WD = 38,
parameter BR_BUS_WD = 33
)
(
input clk,
input resetn,
output timer_int,
// inst sram interface
output inst_sram_en,
output [ 3:0] inst_sram_we,
output [31:0] inst_sram_addr,
output [31:0] inst_sram_wdata,
input [31:0] inst_sram_rdata,
// data sram interface
output data_sram_en,
output [ 3:0] data_sram_we,
output [31:0] data_sram_addr,
output [31:0] data_sram_wdata,
input [31:0] data_sram_rdata,
// cache
input stallreq_dcache,
input stallreq_icache,
input stallreq_uncache,
// trace debug interface
output [31:0] debug_wb_pc,
output [ 3:0] debug_wb_rf_we,
output [ 4:0] debug_wb_rf_wnum,
output [31:0] debug_wb_rf_wdata
);
reg reset;
always @(posedge clk) reset <= ~resetn;
wire [FS_TO_DS_BUS_WD -1:0] fs_to_ds_bus;
wire [DS_TO_ES_BUS_WD -1:0] ds_to_es_bus;
wire [ES_TO_MS_BUS_WD -1:0] es_to_ms_bus;
wire [MS_TO_WS_BUS_WD -1:0] ms_to_ws_bus;
wire [WS_TO_RF_BUS_WD -1:0] ws_to_rf_bus;
wire [MS_TO_ES_BUS_WD -1:0] ms_to_es_bus;
wire [WS_TO_ES_BUS_WD -1:0] ws_to_es_bus;
wire [BR_BUS_WD -1:0] br_bus;
wire flush;
wire stallreq_es;
wire stallreq_ds;
wire [ 5:0] stall;
wire except_en;
wire [31:0] new_pc;
wire [ 1:0] csr_plv;
wire csr_has_int;
wire stallreq_cache;
assign stallreq_cache = stallreq_dcache | stallreq_icache | stallreq_uncache;
if_stage if_stage(
.clk (clk ),
.reset (reset ),
.flush (flush ),
.stall (stall ),
.new_pc (new_pc ),
.timer_int (timer_int ),
.fs_to_ds_bus (fs_to_ds_bus ),
.br_bus (br_bus ),
.inst_sram_en (inst_sram_en ),
.inst_sram_we (inst_sram_we ),
.inst_sram_addr (inst_sram_addr ),
.inst_sram_wdata (inst_sram_wdata )
);
id_stage id_stage(
.clk (clk ),
.reset (reset ),
.flush (flush ),
.stall (stall ),
.br_taken (br_bus[32] ),
.stallreq_ds (stallreq_ds ),
.fs_to_ds_bus (fs_to_ds_bus ),
.pc_valid (inst_sram_en ),
.inst_sram_rdata (inst_sram_rdata ),
.csr_plv (csr_plv ),
.csr_has_int (csr_has_int ),
.ws_to_rf_bus (ws_to_rf_bus ),
.ds_to_es_bus (ds_to_es_bus )
);
exe_stage exe_stage(
.clk (clk ),
.reset (reset ),
.flush (flush ),
.stall (stall ),
.stallreq_es (stallreq_es ),
.ds_to_es_bus (ds_to_es_bus ),
.es_to_ms_bus (es_to_ms_bus ),
.ms_to_es_bus (ms_to_es_bus ),
.ws_to_es_bus (ws_to_es_bus ),
.br_bus (br_bus ),
.data_sram_en (data_sram_en ),
.data_sram_we (data_sram_we ),
.data_sram_addr (data_sram_addr ),
.data_sram_wdata (data_sram_wdata )
);
mem_stage mem_stage(
.clk (clk ),
.reset (reset ),
.flush (flush ),
.stall (stall ),
.except_en (except_en ),
.new_pc (new_pc ),
.csr_plv (csr_plv ),
.csr_has_int (csr_has_int ),
.stallreq_axi (stallreq_cache ),
.es_to_ms_bus (es_to_ms_bus ),
.ms_to_es_bus (ms_to_es_bus ),
.ms_to_ws_bus (ms_to_ws_bus ),
.data_sram_rdata (data_sram_rdata )
);
wb_stage wb_stage(
.clk (clk ),
.reset (reset ),
.flush (flush ),
.stall (stall ),
.ms_to_ws_bus (ms_to_ws_bus ),
.ws_to_rf_bus (ws_to_rf_bus ),
.ws_to_es_bus (ws_to_es_bus ),
.debug_wb_pc (debug_wb_pc ),
.debug_wb_rf_we (debug_wb_rf_we ),
.debug_wb_rf_wnum (debug_wb_rf_wnum ),
.debug_wb_rf_wdata (debug_wb_rf_wdata)
);
pip_ctrl pip_ctrl(
.reset (reset ),
.except_en (except_en ),
.stallreq_ds (stallreq_ds ),
.stallreq_es (stallreq_es ),
.stallreq_axi (stallreq_cache ), // TODO!
.stallreq_cache (stallreq_cache ),
.flush (flush ),
.stall (stall )
);
endmodule

309
lacpu/rtl/mycpu/mycpu_top.v Normal file
View File

@@ -0,0 +1,309 @@
`default_nettype wire
module mycpu_top
#(
parameter HIT_WD = 2,
parameter LRU_WD = 1,
parameter CACHELINE_WD = 512
)
(
input aclk,
input aresetn,
output timer_int,
output [ 3:0] arid,
output [31:0] araddr,
output [ 3:0] arlen,
output [ 2:0] arsize,
output [ 1:0] arburst,
output [ 1:0] arlock,
output [ 3:0] arcache,
output [ 2:0] arprot,
output arvalid,
input arready,
input [ 3:0] rid,
input [31:0] rdata,
input [ 1:0] rresp,
input rlast,
input rvalid,
output rready,
output [ 3:0] awid,
output [31:0] awaddr,
output [ 3:0] awlen,
output [ 2:0] awsize,
output [ 1:0] awburst,
output [ 1:0] awlock,
output [ 3:0] awcache,
output [ 2:0] awprot,
output awvalid,
input awready,
output [ 3:0] wid,
output [31:0] wdata,
output [ 3:0] wstrb,
output wlast,
output wvalid,
input wready,
input [ 3:0] bid,
input [ 1:0] bresp,
input bvalid,
output bready,
// // inst sram interface
// output inst_sram_en,
// output [ 3:0] inst_sram_we,
// output [31:0] inst_sram_addr,
// output [31:0] inst_sram_wdata,
// input [31:0] inst_sram_rdata,
// // data sram interface
// output data_sram_en,
// output [ 3:0] data_sram_we,
// output [31:0] data_sram_addr,
// output [31:0] data_sram_wdata,
// input [31:0] data_sram_rdata,
// trace debug interface
output [31:0] debug_wb_pc,
output [ 3:0] debug_wb_rf_we,
output [ 4:0] debug_wb_rf_wnum,
output [31:0] debug_wb_rf_wdata
);
wire inst_sram_en;
wire [ 3:0] inst_sram_we;
wire [31:0] inst_sram_addr;
wire [31:0] inst_sram_wdata;
wire [31:0] inst_sram_rdata;
wire data_sram_en;
wire [ 3:0] data_sram_we;
wire [31:0] data_sram_addr;
wire [31:0] data_sram_wdata;
wire [31:0] data_sram_rdata;
wire clk;
wire resetn;
assign clk = aclk;
assign resetn = aresetn;
// icache tag
wire icache_cached;
wire icache_uncached;
wire icache_refresh;
wire icache_miss;
wire [31:0] icache_raddr;
//wire icache_write_back;
wire [31:0] icache_waddr;
// icache data
wire [CACHELINE_WD -1:0] icache_cacheline_new;
wire [CACHELINE_WD -1:0] icache_cacheline_old;
// dcache tag
wire dcache_cached;
wire dcache_uncached;
wire dcache_refresh;
wire dcache_miss;
wire [31:0] dcache_raddr;
wire dcache_write_back;
wire [31:0] dcache_waddr;
// dcache data
wire [CACHELINE_WD -1:0] dcache_cacheline_new;
wire [CACHELINE_WD -1:0] dcache_cacheline_old;
// uncache tag
wire uncache_refresh;
wire uncache_en;
wire [ 3:0] uncache_we;
wire [31:0] uncache_addr;
wire [31:0] uncache_wdata;
// uncache data
wire [31:0] uncache_rdata;
wire [31:0] data_sram_addr_mmu;
wire [31:0] dcache_temp_rdata;
wire [31:0] uncache_temp_rdata;
wire stallreq_icache;
wire stallreq_dcache;
wire stallreq_uncache;
mycpu_core mycpu_core(
.clk (clk ),
.resetn (resetn ),
.inst_sram_en (inst_sram_en ),
.inst_sram_we (inst_sram_we ),
.inst_sram_addr (inst_sram_addr ),
.inst_sram_wdata (inst_sram_wdata ),
.inst_sram_rdata (inst_sram_rdata ),
.data_sram_en (data_sram_en ),
.data_sram_we (data_sram_we ),
.data_sram_addr (data_sram_addr ),
.data_sram_wdata (data_sram_wdata ),
.data_sram_rdata (data_sram_rdata ),
.stallreq_dcache (stallreq_dcache ),
.stallreq_icache (stallreq_icache ),
.stallreq_uncache (stallreq_uncache ),
.debug_wb_pc (debug_wb_pc ),
.debug_wb_rf_we (debug_wb_rf_we ),
.debug_wb_rf_wnum (debug_wb_rf_wnum ),
.debug_wb_rf_wdata (debug_wb_rf_wdata )
);
icache icache(
.clk (clk ),
.reset (~resetn ),
.inst_sram_en (inst_sram_en ),
.inst_sram_we (inst_sram_we ),
.inst_sram_addr (inst_sram_addr ),
.inst_sram_wdata (inst_sram_wdata ),
.icache_refresh (icache_refresh ),
.icache_cacheline_new (icache_cacheline_new),
.stallreq_icache (stallreq_icache ),
.inst_sram_rdata (inst_sram_rdata ),
.icache_miss (icache_miss ),
.icache_raddr (icache_raddr ),
.icache_waddr (icache_waddr ),
.icache_cacheline_old (icache_cacheline_old)
);
dcache dcache(
.clk (clk ),
.reset (~resetn ),
.data_sram_en (data_sram_en ),
.data_sram_we (data_sram_we ),
.data_sram_addr (data_sram_addr_mmu ),
.data_sram_wdata (data_sram_wdata ),
.dcache_refresh (dcache_refresh ),
.dcache_uncached (dcache_uncached ),
.dcache_cacheline_new (dcache_cacheline_new),
.stallreq_dcache (stallreq_dcache ),
.data_sram_rdata (dcache_temp_rdata ),
.dcache_miss (dcache_miss ),
.dcache_raddr (dcache_raddr ),
.dcache_waddr (dcache_waddr ),
.dcache_write_back (dcache_write_back ),
.dcache_cacheline_old (dcache_cacheline_old)
);
uncache uncache(
.clk (clk ),
.resetn (resetn ),
.stallreq (stallreq_uncache ),
.conf_en (data_sram_en & ~dcache_cached ),
.conf_we (data_sram_we ),
.conf_addr (data_sram_addr_mmu ), // _mmu ?
.conf_wdata (data_sram_wdata ),
.conf_rdata (uncache_temp_rdata ),
.axi_en (uncache_en ),
.axi_wsel (uncache_we ),
.axi_addr (uncache_addr ),
.axi_wdata (uncache_wdata ),
.reload (uncache_refresh ),
.axi_rdata (uncache_rdata )
);
reg dcache_cached_r;
//assign dcache_cached = ~dcache_uncached;
assign dcache_uncached = ~dcache_cached;
always @ (posedge clk) begin
dcache_cached_r <= dcache_cached;
end
assign data_sram_rdata = dcache_cached_r ? dcache_temp_rdata : uncache_temp_rdata;
// mmu u_inst_mmu(
// .addr_i (inst_sram_addr ),
// .addr_o (inst_sram_addr_mmu ),
// .cache_v (icache_cached )
// );
mmu data_mmu(
.addr_i (data_sram_addr ),
.addr_o (data_sram_addr_mmu ),
.cache_v (dcache_cached )
);
// cache signal from tlb
// begin
//assign dcache_uncached = 1'b0;
// end
axi_ctrl_v5 axi_ctrl(
.clk (clk ),
.reset (~resetn ),
.icache_re (icache_miss ),
.icache_raddr (icache_raddr ),
.icache_cacheline_new (icache_cacheline_new ),
.icache_we (1'b0 ),
.icache_waddr (icache_waddr ),
.icache_cacheline_old (icache_cacheline_old ),
.icache_refresh (icache_refresh ),
.dcache_re (dcache_miss ),
.dcache_raddr (dcache_raddr ),
.dcache_cacheline_new (dcache_cacheline_new ),
.dcache_we (dcache_write_back ),
.dcache_waddr (dcache_waddr ),
.dcache_cacheline_old (dcache_cacheline_old ),
.dcache_refresh (dcache_refresh ),
.uncache_en (uncache_en ),
.uncache_we (uncache_we ),
.uncache_addr (uncache_addr ),
.uncache_wdata (uncache_wdata ),
.uncache_rdata (uncache_rdata ),
.uncache_refresh (uncache_refresh ),
.arid (arid ),
.araddr (araddr ),
.arlen (arlen ),
.arsize (arsize ),
.arburst (arburst ),
.arlock (arlock ),
.arcache (arcache ),
.arprot (arprot ),
.arvalid (arvalid ),
.arready (arready ),
.rid (rid ),
.rdata (rdata ),
.rresp (rresp ),
.rlast (rlast ),
.rvalid (rvalid ),
.rready (rready ),
.awid (awid ),
.awaddr (awaddr ),
.awlen (awlen ),
.awsize (awsize ),
.awburst (awburst ),
.awlock (awlock ),
.awcache (awcache ),
.awprot (awprot ),
.awvalid (awvalid ),
.awready (awready ),
.wid (wid ),
.wdata (wdata ),
.wstrb (wstrb ),
.wlast (wlast ),
.wvalid (wvalid ),
.wready (wready ),
.bid (bid ),
.bresp (bresp ),
.bvalid (bvalid ),
.bready (bready )
);
endmodule

View File

@@ -0,0 +1,49 @@
`define StallBus 6
module pip_ctrl(
input reset,
input except_en,
input stallreq_ds,
input stallreq_es,
input stallreq_axi,
input stallreq_cache,
output reg flush,
output reg [`StallBus-1:0] stall
);
//stall[0] --?
//stall[1] --?
//stall[2] --id
//stall[3]
//stall[4]
//stall[5]
always @ (*) begin
if (reset) begin
flush = 0;
stall = `StallBus'b000000;
end
else if (stallreq_axi) begin
flush = 0;
stall = `StallBus'b111111;
end
else if (except_en) begin
flush = 1;
stall = `StallBus'b0;
end
//id段发生暂停此时id及之前暂停
else if (stallreq_ds) begin
flush = 0;
stall = `StallBus'b000111;
end
else if (stallreq_es) begin
flush = 0;
stall = `StallBus'b011111;
end
// else if(stallreq_cache) begin
// flush = 0;
// stall = `StallBus'b111111;
// end
else begin
flush = 0;
stall = `StallBus'b000000;
end
end
endmodule

68
lacpu/rtl/mycpu/regfile.v Normal file
View File

@@ -0,0 +1,68 @@
module regfile(
input clk,
input reset,
// READ PORT 1
input [ 4:0] raddr1,
output [31:0] rdata1,
// READ PORT 2
input [ 4:0] raddr2,
output [31:0] rdata2,
// WRITE PORT
input we, //write enable, HIGH valid
input [ 4:0] waddr,
input [31:0] wdata
);
reg [31:0] rf[31:0];
//WRITE
always @(posedge clk) begin
if (reset) begin
rf[ 0] <= 32'b0;
rf[ 1] <= 32'b0;
rf[ 2] <= 32'b0;
rf[ 3] <= 32'b0;
rf[ 4] <= 32'b0;
rf[ 5] <= 32'b0;
rf[ 6] <= 32'b0;
rf[ 7] <= 32'b0;
rf[ 8] <= 32'b0;
rf[ 9] <= 32'b0;
rf[10] <= 32'b0;
rf[11] <= 32'b0;
rf[12] <= 32'b0;
rf[13] <= 32'b0;
rf[14] <= 32'b0;
rf[15] <= 32'b0;
rf[16] <= 32'b0;
rf[17] <= 32'b0;
rf[18] <= 32'b0;
rf[19] <= 32'b0;
rf[20] <= 32'b0;
rf[21] <= 32'b0;
rf[22] <= 32'b0;
rf[23] <= 32'b0;
rf[24] <= 32'b0;
rf[25] <= 32'b0;
rf[26] <= 32'b0;
rf[27] <= 32'b0;
rf[28] <= 32'b0;
rf[29] <= 32'b0;
rf[30] <= 32'b0;
rf[31] <= 32'b0;
end
else if (we) begin
rf[waddr]<= wdata;
end
end
//READ OUT 1
assign rdata1 = (raddr1==5'b0 ) ? 32'b0 :
(raddr1==waddr) & we ? wdata :
rf[raddr1];
//READ OUT 2
assign rdata2 = (raddr2==5'b0 ) ? 32'b0 :
(raddr2==waddr) & we ? wdata :
rf[raddr2];
endmodule

182
lacpu/rtl/mycpu/tlb.v Normal file
View File

@@ -0,0 +1,182 @@
module tlb
(
input clk,
//search port 1
input [12:0] s0_vppn,
input [9:0] s0_asid,
input s0_odd,
output reg [11:0] s0_ppn,
output reg [3:0] s0_index,
output reg s0_found,
//search port 2
input [12:0] s1_vppn,
input [9:0] s1_asid,
input s1_odd,
output reg [11:0] s1_ppn,
output reg [3:0] s1_index,
output reg s1_found,
//read port
input [3:0] r_index,
output [12:0] r_vppn,
output [5:0] r_ps,
output r_g,
output [9:0] r_asid,
output r_e,
output [11:0] r_ppn0,
output [1:0] r_plv0,
output [1:0] r_mat0,
output r_d0,
output r_v0,
output [11:0] r_ppn1,
output [1:0] r_plv1,
output [1:0] r_mat1,
output r_d1,
output r_v1,
//write port
input we,
input [3:0] w_index,
input [12:0] w_vppn,
input [5:0] w_ps,
input w_g,
input [9:0] w_asid,
input w_e,
input [11:0] w_ppn0,
input [1:0] w_plv0,
input [1:0] w_mat0,
input w_d0,
input w_v0,
input [11:0] w_ppn1,
input [1:0] w_plv1,
input [1:0] w_mat1,
input w_d1,
input w_v1
);
reg [12:0] tlb_vppn [0:15];
reg [5:0] tlb_ps [0:15];
reg tlb_g [0:15];
reg [9:0] tlb_asid [0:15];
reg tlb_e [0:15];
reg [11:0] tlb_ppn0 [0:15];
reg [1:0] tlb_plv0 [0:15];
reg [1:0] tlb_mat0 [0:15];
reg tlb_d0 [0:15];
reg tlb_v0 [0:15];
reg [11:0] tlb_ppn1 [0:15];
reg [1:0] tlb_plv1 [0:15];
reg [1:0] tlb_mat1 [0:15];
reg tlb_d1 [0:15];
reg tlb_v1 [0:15];
//search
integer i;
reg match0 [0:15];
reg match1 [0:15];
always @(*) begin
for(i = 0; i < 16; i++) begin
match0[i] = (s0_vppn == tlb_vppn[i]) && ((s0_asid == tlb_asid[i]) || tlb_g[i]);
match1[i] = (s1_vppn == tlb_vppn[i]) && ((s1_asid == tlb_asid[i]) || tlb_g[i]);
end
end
always @(*) begin
s0_found = match0[0];
s1_found = match1[0];
for(i = 1; i < 16; i++) begin
s0_found = match0[i] || s0_found;
s1_found = match1[i] || s1_found;
end
end
always @(*) begin
case (1'b1)
match0[0]: begin s0_ppn = s0_odd ? tlb_ppn0[0] : tlb_ppn1[0]; s0_index = 4'd0; end
match0[1]: begin s0_ppn = s0_odd ? tlb_ppn0[1] : tlb_ppn1[1]; s0_index = 4'd1; end
match0[2]: begin s0_ppn = s0_odd ? tlb_ppn0[2] : tlb_ppn1[2]; s0_index = 4'd2; end
match0[3]: begin s0_ppn = s0_odd ? tlb_ppn0[3] : tlb_ppn1[3]; s0_index = 4'd3; end
match0[4]: begin s0_ppn = s0_odd ? tlb_ppn0[4] : tlb_ppn1[4]; s0_index = 4'd4; end
match0[5]: begin s0_ppn = s0_odd ? tlb_ppn0[5] : tlb_ppn1[5]; s0_index = 4'd5; end
match0[6]: begin s0_ppn = s0_odd ? tlb_ppn0[6] : tlb_ppn1[6]; s0_index = 4'd6; end
match0[7]: begin s0_ppn = s0_odd ? tlb_ppn0[7] : tlb_ppn1[7]; s0_index = 4'd7; end
match0[8]: begin s0_ppn = s0_odd ? tlb_ppn0[8] : tlb_ppn1[8]; s0_index = 4'd8; end
match0[9]: begin s0_ppn = s0_odd ? tlb_ppn0[9] : tlb_ppn1[9]; s0_index = 4'd9; end
match0[10]: begin s0_ppn = s0_odd ? tlb_ppn0[10] : tlb_ppn1[10]; s0_index = 4'd10; end
match0[11]: begin s0_ppn = s0_odd ? tlb_ppn0[11] : tlb_ppn1[11]; s0_index = 4'd11; end
match0[12]: begin s0_ppn = s0_odd ? tlb_ppn0[12] : tlb_ppn1[12]; s0_index = 4'd12; end
match0[13]: begin s0_ppn = s0_odd ? tlb_ppn0[13] : tlb_ppn1[13]; s0_index = 4'd13; end
match0[14]: begin s0_ppn = s0_odd ? tlb_ppn0[14] : tlb_ppn1[14]; s0_index = 4'd14; end
match0[15]: begin s0_ppn = s0_odd ? tlb_ppn0[15] : tlb_ppn1[15]; s0_index = 4'd15; end
default: begin
s0_ppn = 12'b0;
s0_index = 4'd0;
end
endcase
case (1'b1)
match1[0]: begin s1_ppn = s1_odd ? tlb_ppn0[0] : tlb_ppn1[0]; s1_index = 4'd0; end
match1[1]: begin s1_ppn = s1_odd ? tlb_ppn0[1] : tlb_ppn1[1]; s1_index = 4'd1; end
match1[2]: begin s1_ppn = s1_odd ? tlb_ppn0[2] : tlb_ppn1[2]; s1_index = 4'd2; end
match1[3]: begin s1_ppn = s1_odd ? tlb_ppn0[3] : tlb_ppn1[3]; s1_index = 4'd3; end
match1[4]: begin s1_ppn = s1_odd ? tlb_ppn0[4] : tlb_ppn1[4]; s1_index = 4'd4; end
match1[5]: begin s1_ppn = s1_odd ? tlb_ppn0[5] : tlb_ppn1[5]; s1_index = 4'd5; end
match1[6]: begin s1_ppn = s1_odd ? tlb_ppn0[6] : tlb_ppn1[6]; s1_index = 4'd6; end
match1[7]: begin s1_ppn = s1_odd ? tlb_ppn0[7] : tlb_ppn1[7]; s1_index = 4'd7; end
match1[8]: begin s1_ppn = s1_odd ? tlb_ppn0[8] : tlb_ppn1[8]; s1_index = 4'd8; end
match1[9]: begin s1_ppn = s1_odd ? tlb_ppn0[9] : tlb_ppn1[9]; s1_index = 4'd9; end
match1[10]: begin s1_ppn = s1_odd ? tlb_ppn0[10] : tlb_ppn1[10]; s1_index = 4'd10; end
match1[11]: begin s1_ppn = s1_odd ? tlb_ppn0[11] : tlb_ppn1[11]; s1_index = 4'd11; end
match1[12]: begin s1_ppn = s1_odd ? tlb_ppn0[12] : tlb_ppn1[12]; s1_index = 4'd12; end
match1[13]: begin s1_ppn = s1_odd ? tlb_ppn0[13] : tlb_ppn1[13]; s1_index = 4'd13; end
match1[14]: begin s1_ppn = s1_odd ? tlb_ppn0[14] : tlb_ppn1[14]; s1_index = 4'd14; end
match1[15]: begin s1_ppn = s1_odd ? tlb_ppn0[15] : tlb_ppn1[15]; s1_index = 4'd15; end
default: begin
s1_ppn = 12'b0;
end
endcase
end
//read
assign r_vppn = (we && w_index == r_index) ? w_vppn : tlb_vppn[r_index];
assign r_ps = (we && w_index == r_index) ? w_ps : tlb_ps[r_index];
assign r_g = (we && w_index == r_index) ? w_g : tlb_g[r_index];
assign r_asid = (we && w_index == r_index) ? w_asid : tlb_asid[r_index];
assign r_e = (we && w_index == r_index) ? w_e : tlb_e[r_index];
assign r_ppn0 = (we && w_index == r_index) ? w_ppn0 : tlb_ppn0[r_index];
assign r_plv0 = (we && w_index == r_index) ? w_plv0 : tlb_plv0[r_index];
assign r_mat0 = (we && w_index == r_index) ? w_mat0 : tlb_mat0[r_index];
assign r_d0 = (we && w_index == r_index) ? w_d0 : tlb_d0[r_index];
assign r_v0 = (we && w_index == r_index) ? w_v0 : tlb_v0[r_index];
assign r_ppn1 = (we && w_index == r_index) ? w_ppn1 : tlb_ppn1[r_index];
assign r_plv1 = (we && w_index == r_index) ? w_plv1 : tlb_plv1[r_index];
assign r_mat1 = (we && w_index == r_index) ? w_mat1 : tlb_mat1[r_index];
assign r_d1 = (we && w_index == r_index) ? w_d1 : tlb_d1[r_index];
assign r_v1 = (we && w_index == r_index) ? w_v1 : tlb_v1[r_index];
//write
always @(posedge clk) begin
if(we) begin
tlb_vppn[w_index] <= w_vppn;
tlb_ps[w_index] <= w_ps;
tlb_g[w_index] <= w_g;
tlb_asid[w_index] <= w_asid;
tlb_e[w_index] <= w_e;
tlb_ppn0[w_index] <= w_ppn0;
tlb_plv0[w_index] <= w_plv0;
tlb_mat0[w_index] <= w_mat0;
tlb_d0[w_index] <= w_d0;
tlb_v0[w_index] <= w_v0;
tlb_ppn1[w_index] <= w_ppn1;
tlb_plv1[w_index] <= w_plv1;
tlb_mat1[w_index] <= w_mat1;
tlb_d1[w_index] <= w_d1;
tlb_v1[w_index] <= w_v1;
end
end
endmodule

54
lacpu/rtl/mycpu/tools.v Normal file
View File

@@ -0,0 +1,54 @@
`default_nettype wire
module decoder_2_4(
input [ 1:0] in,
output [ 3:0] out
);
genvar i;
generate for (i=0; i<4; i=i+1) begin : gen_for_dec_2_4
assign out[i] = (in == i);
end endgenerate
endmodule
module decoder_4_16(
input [ 3:0] in,
output [15:0] out
);
genvar i;
generate for (i=0; i<16; i=i+1) begin : gen_for_dec_4_16
assign out[i] = (in == i);
end endgenerate
endmodule
module decoder_5_32(
input [ 4:0] in,
output [31:0] out
);
genvar i;
generate for (i=0; i<32; i=i+1) begin : gen_for_dec_5_32
assign out[i] = (in == i);
end endgenerate
endmodule
module decoder_6_64(
input [ 5:0] in,
output [63:0] out
);
genvar i;
generate for (i=0; i<64; i=i+1) begin : gen_for_dec_6_64 //bug7
assign out[i] = (in == i);
end endgenerate
endmodule

131
lacpu/rtl/mycpu/uncache.v Normal file
View File

@@ -0,0 +1,131 @@
`default_nettype wire
module uncache
#(
parameter STAGE_WD = 4,
parameter WAIT = 4'b1000,
parameter IDLE = 4'b0001,
parameter BUFFER = 4'b0010
)
(
input clk,
input resetn,
output stallreq,
input conf_en,
input [ 3:0] conf_we,
input [31:0] conf_addr,
input [31:0] conf_wdata,
output reg [31:0] conf_rdata,
output reg axi_en, // en
output reg [ 3:0] axi_wsel, // we
output reg [31:0] axi_addr, // addr
output reg [31:0] axi_wdata,
input reload,
input [31:0] axi_rdata
);
reg valid;
reg finish;
reg buffer_valid;
reg [STAGE_WD -1:0] stage;
wire conf_rd_req;
wire conf_wr_req;
assign conf_rd_req = conf_en & ~valid & ~(|conf_we);
assign conf_wr_req = conf_en & ~valid & (|conf_we);
assign stallreq = conf_rd_req & ~valid | conf_wr_req & buffer_valid & ~valid | stage[3];
always @ (posedge clk) begin
if (!resetn) begin
valid <= 1'b0;
end
else if (finish) begin
valid <= 1'b1;
end
else begin
valid <= 1'b0;
end
end
// assign rd_req = conf_en & ~valid & ~(|conf_we);
// assign rd_addr = conf_addr;
// assign wr_req = conf_en & ~valid & (|conf_we);
// assign wr_wstrb = conf_we;
// assign wr_addr = conf_addr;
// assign wr_data = conf_wdata;
always @ (posedge clk) begin
if (!resetn) begin
conf_rdata <= 32'b0;
end
else if (reload) begin
conf_rdata <= axi_rdata;
end
end
always @ (posedge clk) begin
if (!resetn) begin
buffer_valid <= 1'b0;
stage <= {{(STAGE_WD-1){1'b0}}, 1'b1};
finish <= 1'b0;
axi_en <= 1'b0;
axi_wsel <= 4'b0;
axi_addr <= 32'b0;
axi_wdata <= 32'b0;
end
else begin
case(1'b1)
stage[0]:begin
if (conf_rd_req & ~buffer_valid) begin
axi_en <= 1'b1;
axi_wsel <= conf_we;
axi_addr <= conf_addr;
axi_wdata <= conf_wdata;
stage <= WAIT;
end
else if (conf_wr_req & ~buffer_valid) begin
axi_en <= 1'b1;
axi_wsel <= conf_we;
axi_addr <= conf_addr;
axi_wdata <= conf_wdata;
buffer_valid <= 1'b1;
// finish <= 1'b1;
stage <= BUFFER;
end
end
stage[1]:begin //BUFFER
// finish <= 1'b0;
if (reload) begin
buffer_valid <= 1'b0;
axi_en <= 1'b0;
axi_wsel <= 4'b0;
axi_addr <= 32'b0;
axi_wdata <= 32'b0;
stage <= IDLE;
end
end
stage[3]:begin
if (reload) begin
axi_en <= 1'b0;
axi_wsel <= 4'b0;
axi_addr <= 32'b0;
axi_wdata <= 32'b0;
finish <= 1'b1;
end
else if (finish) begin
finish <= 1'b0;
stage <= {{(STAGE_WD-1){1'b0}}, 1'b1};
end
end
default:begin
stage <= {{(STAGE_WD-1){1'b0}}, 1'b1};
end
endcase
end
end
endmodule

View File

@@ -0,0 +1,68 @@
module wb_stage
#(
parameter MS_TO_WS_BUS_WD = 102,
parameter WS_TO_RF_BUS_WD = 38,
parameter WS_TO_ES_BUS_WD = 38
)
(
input clk,
input reset,
input flush,
input [5:0] stall,
input [MS_TO_WS_BUS_WD -1:0] ms_to_ws_bus,
output [WS_TO_RF_BUS_WD -1:0] ws_to_rf_bus,
output [WS_TO_ES_BUS_WD -1:0] ws_to_es_bus,
output [31:0] debug_wb_pc,
output [ 3:0] debug_wb_rf_we,
output [ 4:0] debug_wb_rf_wnum,
output [31:0] debug_wb_rf_wdata
);
reg [MS_TO_WS_BUS_WD -1:0] ms_to_ws_bus_r;
wire reg_we;
wire [ 4:0] dest;
wire [31:0] ms_final_result;
wire [31:0] ws_pc;
wire [31:0] inst;
assign {reg_we ,//101:101
dest ,//100:96
ms_final_result ,//95 :64
ws_pc ,//63 :32
inst //31 :0
} = ms_to_ws_bus_r;
assign ws_to_rf_bus = {reg_we,
dest,
ms_final_result
};
assign ws_to_es_bus = {reg_we,
dest,
ms_final_result
};
always @ (posedge clk) begin
if (reset) begin
ms_to_ws_bus_r <= 0;
end
else if (flush) begin
ms_to_ws_bus_r <= 0;
end
else if (stall[4]&(!stall[5])) begin
ms_to_ws_bus_r <= 0;
end
else if (!stall[4]) begin
ms_to_ws_bus_r <= ms_to_ws_bus;
end
end
assign debug_wb_pc = stall[5] ? 0 : ws_pc;
assign debug_wb_rf_we = stall[5] ? 0 : {4{reg_we}};
assign debug_wb_rf_wnum = stall[5] ? 0 : dest;
assign debug_wb_rf_wdata = stall[5] ? 0 : ms_final_result;
endmodule