commit c4842146610afee2332a215dc09f627bc41f77ca
parent 660357167499dd93c3a735d064090b01e025692d
Author: Brian Swetland <swetland@frotz.net>
Date: Fri, 17 Feb 2012 01:36:16 -0800
cpu32: stall pipeline on hazards
- todo: forward alu results to avoid stalling when possible
- todo: writing to r15 is not a hazard because it has no effect
Diffstat:
4 files changed, 45 insertions(+), 17 deletions(-)
diff --git a/runtest.sh b/runtest.sh
@@ -14,7 +14,7 @@ else
exit 1
fi
-grep '^PC> ' $1.out > $1.trace
+grep '^PC> ' $1.out | grep -v HAZARD > $1.trace
if [ ! -f $1.gold ] ; then
cp $1.trace $1.gold
diff --git a/verilog/control.v b/verilog/control.v
@@ -5,6 +5,7 @@ module control (
input [3:0] opcode,
input [3:0] opfunc,
input ctl_adata_zero, // 1=(adata==0)
+ input hazard,
output ctl_alu_pc, // 0=adata, 1=pc+4 -> alu.left
output ctl_alu_imm, // 0=bdata, 1=signed_imm16
@@ -22,7 +23,7 @@ wire ctl_branch_nz;
reg [6:0] control;
-always @ (*)
+always @ (*) begin
case (opcode)
4'b0000: control = 7'b0010000; // ALU Rd, Ra, Rb
4'b0001: control = 7'b0110100; // ALU Rd, Ra, #I
@@ -36,6 +37,9 @@ always @ (*)
default: control = 7'b0000000;
endcase
+ if (hazard) control = 7'b1100000;
+end
+
assign {
ctl_alu_pc, ctl_alu_imm, ctl_regs_we, ctl_ram_we,
ctl_alu_altdest, ctl_branch_op, ctl_wdata_ram
diff --git a/verilog/cpu32.v b/verilog/cpu32.v
@@ -47,6 +47,7 @@ control control(
.opcode(opcode),
.opfunc(opfunc),
.ctl_adata_zero(ctl_adata_zero),
+ .hazard(hazard_rrw),
.ctl_alu_pc(ctl_alu_pc),
.ctl_alu_imm(ctl_alu_imm),
@@ -65,7 +66,7 @@ assign ctl_adata_zero = (adata == 32'h0);
register #(32) PC (
.clk(clk),
.reset(reset),
- .en(1),
+ .en(!hazard_rrw),
.din(next_pc),
.dout(pc)
);
@@ -85,12 +86,13 @@ regfile REGS (
);
// attempt to identify hazards
-wire hazard_rrw;
-assign hazard_rrw = (((regs_wsel == opsela) | (regs_wsel == opselb)) & regs_we);
+wire hazard1, hazard2, hazard_rrw;
+assign hazard1 = (((regs_wsel == opsela) | (regs_wsel == opselb)) & regs_we);
+assign hazard2 = (((mem_wsel == opsela) | (mem_wsel == opselb)) & mem_we);
+assign hazard_rrw = hazard1 | hazard2;
assign i_addr = pc;
assign ir = i_data;
-//assign ir = (hazard_rrw ? 32'hEEEEEEEE : i_data);
assign pc_plus_4 = (pc + 32'h4);
@@ -148,6 +150,7 @@ wire mem_we;
memory mem(
.clk(clk),
+ .reset(reset),
.in_alu_data(result),
.in_reg_data(bdata),
@@ -169,6 +172,7 @@ memory mem(
writeback wb(
.clk(clk),
+ .reset(reset),
.in_data(mem_data),
.in_wsel(mem_wsel),
@@ -184,6 +188,7 @@ endmodule
module memory(
input clk,
+ input reset,
/* interface to sync sram */
output [31:0] d_addr,
@@ -213,12 +218,21 @@ module memory(
reg wdata_ram;
always @(posedge clk) begin
- alu_data <= in_alu_data;
- reg_data <= in_reg_data;
- mem_we <= in_mem_we;
- regs_we <= in_regs_we;
- regs_wsel <= in_regs_wsel;
- wdata_ram <= in_wdata_ram;
+ if (reset) begin
+ alu_data <= 32'b0;
+ reg_data <= 32'b0;
+ mem_we <= 1'b0;
+ regs_we <= 1'b0;
+ regs_wsel <= 4'b0;
+ wdata_ram <= 1'b0;
+ end else begin
+ alu_data <= in_alu_data;
+ reg_data <= in_reg_data;
+ mem_we <= in_mem_we;
+ regs_we <= in_regs_we;
+ regs_wsel <= in_regs_wsel;
+ wdata_ram <= in_wdata_ram;
+ end
end
assign d_addr = in_alu_data;
@@ -238,6 +252,7 @@ endmodule
module writeback(
input clk,
+ input reset,
input [31:0] in_data,
input [3:0] in_wsel,
@@ -253,9 +268,15 @@ module writeback(
reg we;
always @(posedge clk) begin
- data <= in_data;
- wsel <= in_wsel;
- we <= in_we;
+ if (reset) begin
+ data <= 32'b0;
+ wsel <= 4'b0;
+ we <= 1'b0;
+ end else begin
+ data <= in_data;
+ wsel <= in_wsel;
+ we <= in_we;
+ end
end
assign out_we = we;
diff --git a/verilog/testbench.v b/verilog/testbench.v
@@ -13,8 +13,8 @@ wire ramwe;
initial begin
clk = 0;
reset = 0;
-// #1 reset = 1;
-// #4 reset = 0;
+ #1 reset = 1;
+ #19 reset = 0;
end
always
@@ -84,6 +84,9 @@ always @(posedge clk) begin
$display("PC> ERROR");
$finish();
end
+ if (cpu.hazard_rrw)
+ $display("PC> %h I> HAZARD", cpu.pc);
+ else if (!reset)
$display("PC> %h I> %h R> %h %h %h %h %h %h %h %h",
cpu.pc, cpu.ir,
cpu.REGS.R[0],