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; ...@@ -130,6 +130,7 @@ module main;
.dm_load_done_i(1'b1), .dm_load_done_i(1'b1),
.dm_ready_i(dm_ready) .dm_ready_i(dm_ready)
); );
always #5ns clk <= ~clk; always #5ns clk <= ~clk;
...@@ -231,16 +232,18 @@ module main; ...@@ -231,16 +232,18 @@ module main;
if(dm_write) if(dm_write)
$display("DM Write addr %x data %x", dm_addr, dm_data_s); $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 begin
if ($isunkown(dm_data_l)) /* -----\/----- EXCLUDED -----\/-----
if ($isunknown(dm_data_l))
begin begin
$error("Attempt to load uninitialized entry from memory"); $error("Attempt to load uninitialized entry from memory");
$stop; $stop;
end 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 end
end end
......
...@@ -60,6 +60,8 @@ module rv_cpu ...@@ -60,6 +60,8 @@ module rv_cpu
wire f_stall_req; wire f_stall_req;
wire d2x_valid;
wire [31:0] d2x_pc; wire [31:0] d2x_pc;
wire [4:0] rf_rs1, d2x_rs1; wire [4:0] rf_rs1, d2x_rs1;
...@@ -71,7 +73,9 @@ module rv_cpu ...@@ -71,7 +73,9 @@ module rv_cpu
wire d2x_shifter_sign; wire d2x_shifter_sign;
wire [31:0] d2x_imm_i, d2x_imm_s, d2x_imm_u, d2x_imm_b, d2x_imm_j; 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 rv_fetch fetch
( (
...@@ -81,10 +85,6 @@ module rv_cpu ...@@ -81,10 +85,6 @@ module rv_cpu
.im_data_i(im_data_i), .im_data_i(im_data_i),
.im_valid_i(im_valid_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_stall_i(f_stall),
.f_kill_i(f_kill), .f_kill_i(f_kill),
.f_valid_o(f2d_valid), .f_valid_o(f2d_valid),
...@@ -92,23 +92,30 @@ module rv_cpu ...@@ -92,23 +92,30 @@ module rv_cpu
.f_ir_o(f2d_ir), .f_ir_o(f2d_ir),
.f_pc_o(f2d_pc), .f_pc_o(f2d_pc),
// .f_ir_valid_o(f2d_ir_valid),
.x_pc_bra_i(x2f_pc_bra), .x_pc_bra_i(x2f_pc_bra),
.x_bra_i(x2f_bra) .x_bra_i(x2f_bra)
); );
rv_predecode decode rv_decode decode
( (
.clk_i(clk_i), .clk_i(clk_i),
.rst_i(rst_i), .rst_i(rst_i),
.d_stall_i(d_stall),
.d_kill_i(d_kill),
.f_ir_i(f2d_ir), .f_ir_i(f2d_ir),
.f_pc_i(f2d_pc), .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_pc_o(d2x_pc),
.x_rs1_o(d2x_rs1), .x_rs1_o(d2x_rs1),
.x_rs2_o(d2x_rs2), .x_rs2_o(d2x_rs2),
...@@ -177,8 +184,10 @@ module rv_cpu ...@@ -177,8 +184,10 @@ module rv_cpu
wire x_load_comb; wire x_load_comb;
wire x2w_load_hazard;
wire w_stall_req;
rv_exec execute rv_exec execute
( (
...@@ -188,8 +197,11 @@ module rv_cpu ...@@ -188,8 +197,11 @@ module rv_cpu
.x_stall_i(x_stall), .x_stall_i(x_stall),
.x_kill_i(x_kill), .x_kill_i(x_kill),
.x_stall_req_o(x_stall_req), .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_pc_i(d2x_pc),
.d_rd_i(d2x_rd), .d_rd_i(d2x_rd),
.d_fun_i(d2x_fun), .d_fun_i(d2x_fun),
...@@ -210,7 +222,7 @@ module rv_cpu ...@@ -210,7 +222,7 @@ module rv_cpu
.f_branch_take_o (x2f_bra), .f_branch_take_o (x2f_bra),
.x_load_o(x_load_comb), .w_load_hazard_o(x2w_load_hazard),
// Writeback stage I/F // Writeback stage I/F
.w_fun_o(x2w_fun), .w_fun_o(x2w_fun),
.w_load_o(x2w_load), .w_load_o(x2w_load),
...@@ -229,7 +241,6 @@ module rv_cpu ...@@ -229,7 +241,6 @@ module rv_cpu
.dm_ready_i(dm_ready_i) .dm_ready_i(dm_ready_i)
); );
wire w_stall_req;
rv_writeback writeback rv_writeback writeback
...@@ -242,6 +253,7 @@ module rv_cpu ...@@ -242,6 +253,7 @@ module rv_cpu
.x_fun_i(x2w_fun), .x_fun_i(x2w_fun),
.x_load_i(x2w_load), .x_load_i(x2w_load),
.x_load_hazard_i(x2w_load_hazard),
.x_store_i(x2w_store), .x_store_i(x2w_store),
.x_rd_i(x2w_rd), .x_rd_i(x2w_rd),
...@@ -259,34 +271,45 @@ module rv_cpu ...@@ -259,34 +271,45 @@ module rv_cpu
.rf_rd_write_o(rf_rd_write) .rf_rd_write_o(rf_rd_write)
); );
reg x2f_bra_d0; reg x2f_bra_d0, x2f_bra_d1;
always@(posedge clk_i) always@(posedge clk_i)
if(rst_i) if(rst_i) begin
x2f_bra_d0 <= 0; x2f_bra_d0 <= 0;
else if (!x_stall) x2f_bra_d1 <= 0;
x2f_bra_d0 <= x2f_bra; 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 // load to Rd in W stage while Rs1/Rs2==RD in fetch stage: assert interlock
/* -----\/----- EXCLUDED -----\/-----
reg interlock_load, interlock_load_d0 = 0; reg interlock_load, interlock_load_d0 = 0;
always@* always@*
interlock_load <= f_load_hazard && x_load_comb; interlock_load <= d_load_hazard && x_load_comb;
always@(posedge clk_i) always@(posedge clk_i)
if(interlock_load_d0) if(interlock_load_d0)
interlock_load_d0 <= 0; interlock_load_d0 <= 0;
else else
interlock_load_d0 <= interlock_load; interlock_load_d0 <= interlock_load;
-----/\----- EXCLUDED -----/\----- */
assign f_stall = x_stall_req || w_stall_req || (interlock_load && !interlock_load_d0); assign f_stall = x_stall_req || w_stall_req;
assign x_stall = x_stall_req || w_stall_req || (interlock_load && !interlock_load_d0); // || (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 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 ; assign f_kill = x2f_bra ;
......
...@@ -30,6 +30,7 @@ module rv_exec ...@@ -30,6 +30,7 @@ module rv_exec
input x_stall_i, input x_stall_i,
input x_kill_i, input x_kill_i,
output x_stall_req_o, output x_stall_req_o,
wire w_stall_req_i,
input [31:0] d_pc_i, input [31:0] d_pc_i,
...@@ -41,6 +42,8 @@ module rv_exec ...@@ -41,6 +42,8 @@ module rv_exec
input [31:0] rf_rs2_value_i, input [31:0] rf_rs2_value_i,
input d_valid_i, input d_valid_i,
input d_load_hazard_i,
input [4:0] d_opcode_i, input [4:0] d_opcode_i,
input d_shifter_sign_i, input d_shifter_sign_i,
...@@ -54,7 +57,7 @@ module rv_exec ...@@ -54,7 +57,7 @@ module rv_exec
output reg [31:0] f_branch_target_o, output reg [31:0] f_branch_target_o,
output reg f_branch_take_o, output reg f_branch_take_o,
output x_load_o, output w_load_hazard_o,
// Writeback stage I/F // Writeback stage I/F
output reg [2:0 ] w_fun_o, output reg [2:0 ] w_fun_o,
...@@ -188,7 +191,7 @@ module rv_exec ...@@ -188,7 +191,7 @@ module rv_exec
end // always@ * end // always@ *
reg shifter_req_d0; 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 ); (d_opcode_i == `OPC_OP || d_opcode_i == `OPC_OP_IMM );
rv_shifter shifter rv_shifter shifter
...@@ -298,8 +301,8 @@ module rv_exec ...@@ -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_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; wire is_store = (d_opcode_i == `OPC_STORE ? 1: 0) && d_valid_i && !x_kill_i;
assign dm_load_o = is_load; assign dm_load_o = is_load && !x_stall_i;
assign dm_store_o = is_store; assign dm_store_o = is_store && !x_stall_i;
always@(posedge clk_i) always@(posedge clk_i)
if (rst_i) begin if (rst_i) begin
...@@ -313,8 +316,7 @@ module rv_exec ...@@ -313,8 +316,7 @@ module rv_exec
w_dm_addr_o <= 0; w_dm_addr_o <= 0;
end end else if (!x_stall_i) begin
else begin //if (!x_stall_i) begin
f_branch_target_o <= branch_target; f_branch_target_o <= branch_target;
f_branch_take_o <= branch_take && !x_kill_i && d_valid_i; f_branch_take_o <= branch_take && !x_kill_i && d_valid_i;
...@@ -331,19 +333,19 @@ else begin //if (!x_stall_i) begin ...@@ -331,19 +333,19 @@ else begin //if (!x_stall_i) begin
w_dm_addr_o <= dm_addr; w_dm_addr_o <= dm_addr;
// end else begin // if (!x_stall_i) end else begin // if (!x_stall_i)
// f_branch_take_o <= 0; f_branch_take_o <= 0;
// w_rd_write_o <= 0; w_rd_write_o <= 0;
// w_load_o <= 0; w_load_o <= 0;
// w_store_o <= 0; w_store_o <= 0;
// end
end // else: !if(rst_i) end // else: !if(rst_i)
assign x_stall_req_o = shifter_stall_req || ((is_store || is_load) && !dm_ready_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 ...@@ -32,11 +32,6 @@ module rv_fetch
input f_stall_i, input f_stall_i,
input f_kill_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 [31:0] f_ir_o,
output reg [31:0] f_pc_o, output reg [31:0] f_pc_o,
output reg [31:0] f_pc_plus_4_o, output reg [31:0] f_pc_plus_4_o,
...@@ -48,31 +43,9 @@ module rv_fetch ...@@ -48,31 +43,9 @@ module rv_fetch
); );
reg [31:0] pc; reg [31:0] pc;
reg [31:0] ir; reg [31:0] ir ,ir_prev;
reg rst_d; 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; reg [31:0] pc_next;
always@* always@*
......
...@@ -23,79 +23,122 @@ ...@@ -23,79 +23,122 @@
`timescale 1ns/1ps `timescale 1ns/1ps
module rv_predecode module rv_decode
( (
input clk_i, input clk_i,
input rst_i, input rst_i,
input [31:0] im_data_i, input d_stall_i,
input d_kill_i,
input [31:0] f_ir_i, output reg x_load_hazard_o,
input [31:0] f_pc_i,
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 reg [4:0] rf_rs1_o,
output [4:0] rf_rs2_o, output reg [4:0] rf_rs2_o,
output [4:0] x_rs1_o, output [4:0] x_rs1_o,
output [4:0] x_rs2_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 reg [2:0] x_fun_o,
output [4:0] x_opcode_o, output [4:0] x_opcode_o,
output x_shifter_sign_o, output x_shifter_sign_o,
output [31:0] x_imm_i_o, output [31:0] x_imm_i_o,
output [31:0] x_imm_s_o, output [31:0] x_imm_s_o,
output [31:0] x_imm_b_o, output [31:0] x_imm_b_o,
output [31:0] x_imm_u_o, output [31:0] x_imm_u_o,
output [31:0] x_imm_j_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_rs1_o = d_ir [19:15];
assign x_rs2_o = f_ir_i [24:20]; assign x_rs2_o = d_ir [24:20];
assign x_rd_o = f_ir_i [11:7]; assign x_rd_o = d_ir [11:7];
assign x_opcode_o = f_ir_i[6:2]; assign x_opcode_o = d_ir[6:2];
assign x_shamt_o = f_ir_i[24:20]; assign x_shamt_o = d_ir[24:20];
// attempt to reuse ALU for jump address generation // attempt to reuse ALU for jump address generation
always@* always@*
case (f_opcode) case (opcode)
`OPC_JAL, `OPC_JALR, `OPC_LUI, `OPC_AUIPC: `OPC_JAL, `OPC_JALR, `OPC_LUI, `OPC_AUIPC:
x_fun_o <= `FUNC_ADD; x_fun_o <= `FUNC_ADD;
default: default:
x_fun_o <= f_ir_i[14:12]; x_fun_o <= d_ir[14:12];
endcase // case (f_opcode) endcase // case (f_opcode)
//assign x_fun_o = f_ir_i[14:12]; //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 // 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_i_o = { {21{ d_ir[31] }}, d_ir[30:25], d_ir[24:21], d_ir[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_s_o = { {21{ d_ir[31] }}, d_ir[30:25], d_ir[11:8], d_ir[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_b_o = { {20{ d_ir[31] }}, d_ir[7], d_ir[30:25], d_ir[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_u_o = { d_ir[31], d_ir[30:20], d_ir[19:12], 12'h000 };
assign x_imm_j_o = { {12{f_ir_i[31]}}, assign x_imm_j_o = { {12{d_ir[31]}},
f_ir_i[19:12], d_ir[19:12],
f_ir_i[20], f_ir_i[30:25], f_ir_i[24:21], 1'b0}; 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 ...@@ -141,8 +141,6 @@ module rv_regfile
.d2_i (w_rd_value_i), .d2_i (w_rd_value_i),
.we2_i (write) .we2_i (write)
); );
wire rs1_bypass = w_bypass_rd_write_i && (w_rd_i == d_rs1_i); 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); wire rs2_bypass = w_bypass_rd_write_i && (w_rd_i == d_rs2_i);
...@@ -150,12 +148,6 @@ module rv_regfile ...@@ -150,12 +148,6 @@ module rv_regfile
assign x_rs1_value_o = rs1_bypass ? w_bypass_rd_value_i : rs1_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; 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 endmodule // rv_regfile
......
...@@ -96,10 +96,27 @@ module rv_writeback ...@@ -96,10 +96,27 @@ module rv_writeback
endcase // case (d_fun_i) endcase // case (d_fun_i)
end // always@ * 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_value_o = (x_load_i ? load_value : x_rd_value_i );
assign rf_rd_o = (x_rd_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 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