cpu32

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

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:
Mruntest.sh | 2+-
Mverilog/control.v | 6+++++-
Mverilog/cpu32.v | 47++++++++++++++++++++++++++++++++++-------------
Mverilog/testbench.v | 7+++++--
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],