Commit c374e8af authored by Tomasz Wlostowski's avatar Tomasz Wlostowski

4-stage pipeline running sorting test program

parent 08a9b8d4
......@@ -130,6 +130,7 @@ module main;
.dm_load_done_i(1'b1),
.dm_ready_i(dm_ready)
);
always #5ns clk <= ~clk;
......@@ -231,16 +232,18 @@ module main;
if(dm_write)
$display("DM Write addr %x data %x", dm_addr, dm_data_s);
if (DUT.writeback.x_load_i && !DUT.writeback.w_stall_i)
if (DUT.writeback.x_load_i && DUT.writeback.rf_rd_write_o)
begin
if ($isunkown(dm_data_l))
/* -----\/----- EXCLUDED -----\/-----
if ($isunknown(dm_data_l))
begin
$error("Attempt to load uninitialized entry from memory");
$stop;
end
-----/\----- EXCLUDED -----/\----- */
$display("DM Load addr %x data %x -> %s", dm_addr_d0, dm_data_l, decode_regname(DUT.writeback.x_rd_i));
$display("DM Load addr %x data %x -> %s", dm_addr_d0, DUT.writeback.rf_rd_value_o, decode_regname(DUT.writeback.x_rd_i));
end
end
end
......
......@@ -60,6 +60,8 @@ module rv_cpu
wire f_stall_req;
wire d2x_valid;
wire [31:0] d2x_pc;
wire [4:0] rf_rs1, d2x_rs1;
......@@ -71,7 +73,9 @@ module rv_cpu
wire d2x_shifter_sign;
wire [31:0] d2x_imm_i, d2x_imm_s, d2x_imm_u, d2x_imm_b, d2x_imm_j;
wire f_load_hazard;
wire d_load_hazard;
wire d_stall, d_kill;
rv_fetch fetch
(
......@@ -81,10 +85,6 @@ module rv_cpu
.im_data_i(im_data_i),
.im_valid_i(im_valid_i),
.rf_rs1_o(rf_rs1),
.rf_rs2_o(rf_rs2),
.f_load_hazard_o(f_load_hazard),
.f_stall_i(f_stall),
.f_kill_i(f_kill),
.f_valid_o(f2d_valid),
......@@ -92,23 +92,30 @@ module rv_cpu
.f_ir_o(f2d_ir),
.f_pc_o(f2d_pc),
// .f_ir_valid_o(f2d_ir_valid),
.x_pc_bra_i(x2f_pc_bra),
.x_bra_i(x2f_bra)
);
rv_predecode decode
rv_decode decode
(
.clk_i(clk_i),
.rst_i(rst_i),
.d_stall_i(d_stall),
.d_kill_i(d_kill),
.f_ir_i(f2d_ir),
.f_pc_i(f2d_pc),
.f_valid_i(f2d_valid),
.x_load_hazard_o(d_load_hazard),
.rf_rs1_o(rf_rs1),
.rf_rs2_o(rf_rs2),
.x_valid_o(d2x_valid),
.x_pc_o(d2x_pc),
.x_rs1_o(d2x_rs1),
.x_rs2_o(d2x_rs2),
......@@ -177,8 +184,10 @@ module rv_cpu
wire x_load_comb;
wire x2w_load_hazard;
wire w_stall_req;
rv_exec execute
(
......@@ -188,8 +197,11 @@ module rv_cpu
.x_stall_i(x_stall),
.x_kill_i(x_kill),
.x_stall_req_o(x_stall_req),
.d_valid_i(f2d_valid),
.w_stall_req_i(w_stall_req),
.d_valid_i(d2x_valid),
.d_load_hazard_i(d_load_hazard),
.d_pc_i(d2x_pc),
.d_rd_i(d2x_rd),
.d_fun_i(d2x_fun),
......@@ -210,7 +222,7 @@ module rv_cpu
.f_branch_take_o (x2f_bra),
.x_load_o(x_load_comb),
.w_load_hazard_o(x2w_load_hazard),
// Writeback stage I/F
.w_fun_o(x2w_fun),
.w_load_o(x2w_load),
......@@ -229,7 +241,6 @@ module rv_cpu
.dm_ready_i(dm_ready_i)
);
wire w_stall_req;
rv_writeback writeback
......@@ -242,6 +253,7 @@ module rv_cpu
.x_fun_i(x2w_fun),
.x_load_i(x2w_load),
.x_load_hazard_i(x2w_load_hazard),
.x_store_i(x2w_store),
.x_rd_i(x2w_rd),
......@@ -259,34 +271,45 @@ module rv_cpu
.rf_rd_write_o(rf_rd_write)
);
reg x2f_bra_d0;
reg x2f_bra_d0, x2f_bra_d1;
always@(posedge clk_i)
if(rst_i)
x2f_bra_d0 <= 0;
else if (!x_stall)
x2f_bra_d0 <= x2f_bra;
if(rst_i) begin
x2f_bra_d0 <= 0;
x2f_bra_d1 <= 0;
end else if (!x_stall) begin
x2f_bra_d0 <= x2f_bra;
x2f_bra_d1 <= x2f_bra_d0;
end
// load to Rd in W stage while Rs1/Rs2==RD in fetch stage: assert interlock
/* -----\/----- EXCLUDED -----\/-----
reg interlock_load, interlock_load_d0 = 0;
always@*
interlock_load <= f_load_hazard && x_load_comb;
interlock_load <= d_load_hazard && x_load_comb;
always@(posedge clk_i)
if(interlock_load_d0)
interlock_load_d0 <= 0;
else
interlock_load_d0 <= interlock_load;
-----/\----- EXCLUDED -----/\----- */
assign f_stall = x_stall_req || w_stall_req || (interlock_load && !interlock_load_d0);
assign x_stall = x_stall_req || w_stall_req || (interlock_load && !interlock_load_d0);
assign f_stall = x_stall_req || w_stall_req;
// || (interlock_load && !interlock_load_d0);
assign x_stall = x_stall_req || w_stall_req;
// || (interlock_load && !interlock_load_d0);
assign d_stall = x_stall_req || w_stall_req;
// || (interlock_load && !interlock_load_d0);
assign w_stall = 0;
assign x_kill = x2f_bra || x2f_bra_d0;
assign x_kill = x2f_bra || x2f_bra_d0 || x2f_bra_d1;
assign d_kill = x2f_bra || x2f_bra_d0;
assign f_kill = x2f_bra ;
......
......@@ -30,6 +30,7 @@ module rv_exec
input x_stall_i,
input x_kill_i,
output x_stall_req_o,
wire w_stall_req_i,
input [31:0] d_pc_i,
......@@ -41,6 +42,8 @@ module rv_exec
input [31:0] rf_rs2_value_i,
input d_valid_i,
input d_load_hazard_i,
input [4:0] d_opcode_i,
input d_shifter_sign_i,
......@@ -54,7 +57,7 @@ module rv_exec
output reg [31:0] f_branch_target_o,
output reg f_branch_take_o,
output x_load_o,
output w_load_hazard_o,
// Writeback stage I/F
output reg [2:0 ] w_fun_o,
......@@ -188,7 +191,7 @@ module rv_exec
end // always@ *
reg shifter_req_d0;
wire shifter_req = (d_valid_i) && (d_fun_i == `FUNC_SL || d_fun_i == `FUNC_SR) &&
wire shifter_req = !w_stall_req_i && (d_valid_i) && (d_fun_i == `FUNC_SL || d_fun_i == `FUNC_SR) &&
(d_opcode_i == `OPC_OP || d_opcode_i == `OPC_OP_IMM );
rv_shifter shifter
......@@ -298,8 +301,8 @@ module rv_exec
wire is_load = (d_opcode_i == `OPC_LOAD ? 1: 0) && d_valid_i && !x_kill_i;
wire is_store = (d_opcode_i == `OPC_STORE ? 1: 0) && d_valid_i && !x_kill_i;
assign dm_load_o = is_load;
assign dm_store_o = is_store;
assign dm_load_o = is_load && !x_stall_i;
assign dm_store_o = is_store && !x_stall_i;
always@(posedge clk_i)
if (rst_i) begin
......@@ -313,8 +316,7 @@ module rv_exec
w_dm_addr_o <= 0;
end
else begin //if (!x_stall_i) begin
end else if (!x_stall_i) begin
f_branch_target_o <= branch_target;
f_branch_take_o <= branch_take && !x_kill_i && d_valid_i;
......@@ -331,19 +333,19 @@ else begin //if (!x_stall_i) begin
w_dm_addr_o <= dm_addr;
// end else begin // if (!x_stall_i)
// f_branch_take_o <= 0;
// w_rd_write_o <= 0;
// w_load_o <= 0;
// w_store_o <= 0;
// end
end else begin // if (!x_stall_i)
f_branch_take_o <= 0;
w_rd_write_o <= 0;
w_load_o <= 0;
w_store_o <= 0;
end // else: !if(rst_i)
assign x_stall_req_o = shifter_stall_req || ((is_store || is_load) && !dm_ready_i);
assign x_load_o = is_load;
assign w_load_hazard_o = d_load_hazard_i;
......
......@@ -32,11 +32,6 @@ module rv_fetch
input f_stall_i,
input f_kill_i,
output reg [4:0] rf_rs1_o,
output reg [4:0] rf_rs2_o,
output reg f_load_hazard_o,
output [31:0] f_ir_o,
output reg [31:0] f_pc_o,
output reg [31:0] f_pc_plus_4_o,
......@@ -48,31 +43,9 @@ module rv_fetch
);
reg [31:0] pc;
reg [31:0] ir;
reg [31:0] ir ,ir_prev;
reg rst_d;
wire [4:0] rs1_mem = im_data_i[19:15];
wire [4:0] rs2_mem = im_data_i[24:20];
wire [4:0] rd = ir [11:7];
always@*
if(!f_stall_i)
begin
rf_rs1_o <= im_data_i [19:15];
rf_rs2_o <= im_data_i [24:20];
end else begin
rf_rs1_o <= ir[19:15];
rf_rs2_o <= ir[24:20];
end
always@*
f_load_hazard_o <= ( (rs1_mem == rd) || (rs2_mem == rd) ) && !f_kill_i;
reg [31:0] pc_next;
always@*
......
......@@ -23,79 +23,122 @@
`timescale 1ns/1ps
module rv_predecode
module rv_decode
(
input clk_i,
input rst_i,
input clk_i,
input rst_i,
input [31:0] im_data_i,
input d_stall_i,
input d_kill_i,
input [31:0] f_ir_i,
input [31:0] f_pc_i,
output reg x_load_hazard_o,
input [31:0] f_ir_i,
input [31:0] f_pc_i,
input f_valid_i,
output reg x_valid_o,
output [31:0] x_pc_o,
output reg [31:0] x_pc_o,
output [4:0] rf_rs1_o,
output [4:0] rf_rs2_o,
output reg [4:0] rf_rs1_o,
output reg [4:0] rf_rs2_o,
output [4:0] x_rs1_o,
output [4:0] x_rs2_o,
output [4:0] x_rs1_o,
output [4:0] x_rs2_o,
output [4:0] x_rd_o,
output [4:0] x_rd_o,
output [4:0] x_shamt_o,
output [4:0] x_shamt_o,
output reg [2:0] x_fun_o,
output [4:0] x_opcode_o,
output x_shifter_sign_o,
output [4:0] x_opcode_o,
output x_shifter_sign_o,
output [31:0] x_imm_i_o,
output [31:0] x_imm_s_o,
output [31:0] x_imm_b_o,
output [31:0] x_imm_u_o,
output [31:0] x_imm_j_o
output [31:0] x_imm_i_o,
output [31:0] x_imm_s_o,
output [31:0] x_imm_b_o,
output [31:0] x_imm_u_o,
output [31:0] x_imm_j_o
);
wire [4:0] f_opcode = f_ir_i[6:2];
reg [31:0] d_ir = 0;
wire [4:0] f_rs1 = f_ir_i[19:15];
wire [4:0] f_rs2 = f_ir_i[24:20];
wire [4:0] d_rs1 = d_ir[19:15];
wire [4:0] d_rs2 = d_ir[24:20];
wire [4:0] rd = d_ir [11:7];
reg [31:0] f_ir_d;
always@*
if(d_stall_i)
begin
rf_rs1_o <= d_rs1;
rf_rs2_o <= d_rs2;
end else begin
rf_rs1_o <= f_rs1;
rf_rs2_o <= f_rs2;
end
always@(posedge clk_i)
if(rst_i)
begin
x_pc_o <= 0;
x_valid_o <= 0;
end else if(!d_stall_i)
begin
d_ir <= f_ir_i;
x_valid_o <= f_valid_i && !d_kill_i;
x_pc_o <= f_pc_i;
end
wire [4:0] opcode = d_ir[6:2];
always@(posedge clk_i)
if(!d_stall_i)
x_load_hazard_o <= ( (f_rs1 == rd) || (f_rs2 == rd) ) && (!d_kill_i) && (opcode == `OPC_LOAD);
assign x_rs1_o = f_ir_i [19:15];
assign x_rs2_o = f_ir_i [24:20];
assign x_rs1_o = d_ir [19:15];
assign x_rs2_o = d_ir [24:20];
assign x_rd_o = f_ir_i [11:7];
assign x_opcode_o = f_ir_i[6:2];
assign x_shamt_o = f_ir_i[24:20];
assign x_rd_o = d_ir [11:7];
assign x_opcode_o = d_ir[6:2];
assign x_shamt_o = d_ir[24:20];
// attempt to reuse ALU for jump address generation
always@*
case (f_opcode)
case (opcode)
`OPC_JAL, `OPC_JALR, `OPC_LUI, `OPC_AUIPC:
x_fun_o <= `FUNC_ADD;
default:
x_fun_o <= f_ir_i[14:12];
x_fun_o <= d_ir[14:12];
endcase // case (f_opcode)
//assign x_fun_o = f_ir_i[14:12];
assign x_shifter_sign_o = f_ir_i[30];
assign x_shifter_sign_o = d_ir[30];
// decoded imm values
assign x_imm_i_o = { {21{ f_ir_i[31] }}, f_ir_i[30:25], f_ir_i[24:21], f_ir_i[20] };
assign x_imm_s_o = { {21{ f_ir_i[31] }}, f_ir_i[30:25], f_ir_i[11:8], f_ir_i[7] };
assign x_imm_b_o = { {20{ f_ir_i[31] }}, f_ir_i[7], f_ir_i[30:25], f_ir_i[11:8], 1'b0 };
assign x_imm_u_o = { f_ir_i[31], f_ir_i[30:20], f_ir_i[19:12], 12'h000 };
assign x_imm_j_o = { {12{f_ir_i[31]}},
f_ir_i[19:12],
f_ir_i[20], f_ir_i[30:25], f_ir_i[24:21], 1'b0};
assign x_imm_i_o = { {21{ d_ir[31] }}, d_ir[30:25], d_ir[24:21], d_ir[20] };
assign x_imm_s_o = { {21{ d_ir[31] }}, d_ir[30:25], d_ir[11:8], d_ir[7] };
assign x_imm_b_o = { {20{ d_ir[31] }}, d_ir[7], d_ir[30:25], d_ir[11:8], 1'b0 };
assign x_imm_u_o = { d_ir[31], d_ir[30:20], d_ir[19:12], 12'h000 };
assign x_imm_j_o = { {12{d_ir[31]}},
d_ir[19:12],
d_ir[20], d_ir[30:25], d_ir[24:21], 1'b0};
assign x_pc_o = f_pc_i;
......
......@@ -141,8 +141,6 @@ module rv_regfile
.d2_i (w_rd_value_i),
.we2_i (write)
);
wire rs1_bypass = w_bypass_rd_write_i && (w_rd_i == d_rs1_i);
wire rs2_bypass = w_bypass_rd_write_i && (w_rd_i == d_rs2_i);
......@@ -150,12 +148,6 @@ module rv_regfile
assign x_rs1_value_o = rs1_bypass ? w_bypass_rd_value_i : rs1_regfile;
assign x_rs2_value_o = rs2_bypass ? w_bypass_rd_value_i : rs2_regfile;
/* wire rs1_bypass = write && (w_rd_i == d_rs1_i);
wire rs2_bypass = write && (w_rd_i == d_rs2_i);
assign x_rs1_value_o = rs1_bypass ? w_rd_value_i : rs1_regfile;
assign x_rs2_value_o = rs2_bypass ? w_rd_value_i : rs2_regfile;*/
endmodule // rv_regfile
......
......@@ -96,10 +96,27 @@ module rv_writeback
endcase // case (d_fun_i)
end // always@ *
reg interlock_d = 0;
wire interlock = (x_load_i && dm_load_done_i && x_load_hazard_i);
always@(posedge clk_i)
begin
if(interlock_d)
interlock_d <= 0;
else
interlock_d <= interlock;
end
assign rf_rd_value_o = (x_load_i ? load_value : x_rd_value_i );
assign rf_rd_o = (x_rd_i);
assign rf_rd_write_o = (w_stall_i ? 1'b0 : (x_load_i && dm_load_done_i ? 1'b1 : x_rd_write_i ));
assign rf_rd_write_o = !interlock_d && (w_stall_i ? 1'b0 : (x_load_i && dm_load_done_i ? 1'b1 : x_rd_write_i ));
assign w_stall_req_o = (x_load_i && !dm_load_done_i) || (x_store_i && !dm_store_done_i) || (interlock && !interlock_d);
assign w_stall_req_o = (x_load_i && !dm_load_done_i) || (x_store_i && !dm_store_done_i);
endmodule // rv_writeback
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment