commit c9dfe3a22ac5ac36e379231aa94daa547043d57a
parent 28a2fb2465673e397897f70005023f101373788d
Author: Brian Swetland <swetland@frotz.net>
Date: Sat, 18 Feb 2012 03:28:27 -0800
cpu32: more pipeline insanity
- better reset logic
- add fetch phase, move to syncram for irom
- unified i/d memory
- adjust a32 for branch targets now being pc+4+imm
- we have a branch slot now
Diffstat:
4 files changed, 46 insertions(+), 21 deletions(-)
diff --git a/Makefile b/Makefile
@@ -1,7 +1,7 @@
# Copyright 2012, Brian Swetland. Use at your own risk.
SRC := verilog/testbench.v
-SRC += verilog/ram.v verilog/syncram.v verilog/rom.v verilog/control.v
+SRC += verilog/dualsyncram.v verilog/control.v
SRC += verilog/cpu32.v verilog/alu.v verilog/regfile.v
SRC += verilog/uart.v
SRC += verilog/library.v
diff --git a/a32.c b/a32.c
@@ -56,7 +56,7 @@ struct fixup *fixups;
void fixup_branch(const char *name, int addr, int btarget, int type) {
unsigned n;
- n = btarget - addr;
+ n = btarget - addr - 1;
if (!is_signed_16(n)) {
die("label '%s' at %08x is out of range of %08x\n",
@@ -418,7 +418,7 @@ void printinst(char *buf, unsigned pc, unsigned instr, const char *fmt) {
break;
case 'r':
buf = append(buf,"0x");
- buf = append_u32(buf,(pc + s16));
+ buf = append_u32(buf,(pc + 4 + s16));
break;
case 0:
goto done;
diff --git a/verilog/cpu32.v b/verilog/cpu32.v
@@ -15,9 +15,18 @@ module cpu32 (
output d_data_we
);
-wire [31:0] ir, pc;
+reg sync_reset;
-wire [31:0] next_pc, pc_plus_4;
+always @(posedge clk)
+ if (reset)
+ sync_reset <= 1'b1;
+ else
+ sync_reset <= 1'b0;
+
+wire [31:0] pc;
+reg [31:0] ir;
+
+wire [31:0] next_pc, pc_plus_4, next_pc0;
wire [3:0] opcode, opfunc, opsela, opselb, opseld;
wire [15:0] opimm16;
@@ -65,12 +74,22 @@ assign ctl_adata_zero = (adata == 32'h0);
register #(32) PC (
.clk(clk),
- .reset(reset),
- .en(!hazard_rrw),
+ .reset(sync_reset),
+ .en(1),
.din(next_pc),
.dout(pc)
);
+assign i_addr = next_pc;
+
+always @(posedge clk)
+ if (sync_reset) begin
+ ir <= 32'hEEEE7777;
+ end else begin
+ if (!hazard_rrw)
+ ir <= i_data;
+ end
+
/* these arrive from writeback */
wire [31:0] regs_wdata;
wire [3:0] regs_wsel;
@@ -91,10 +110,7 @@ assign hazard1 = (((regs_wsel == opsela) | (regs_wsel == opselb)) & regs_we) & (
assign hazard2 = (((mem_wsel == opsela) | (mem_wsel == opselb)) & mem_we) & (mem_wsel != 4'b1111);
assign hazard_rrw = hazard1 | hazard2;
-assign i_addr = pc;
-assign ir = i_data;
-
-assign pc_plus_4 = (pc + 32'h4);
+assign pc_plus_4 = hazard_rrw ? pc : (pc + 32'h4);
wire [31:0] branch_to;
mux2 #(32) mux_branch_to(
@@ -108,6 +124,13 @@ mux2 #(32) mux_pc_source(
.sel(ctl_branch_taken),
.in0(pc_plus_4),
.in1(branch_to),
+ .out(next_pc0)
+ );
+
+mux2 #(32) mux_next_pc(
+ .sel(sync_reset),
+ .in0(next_pc0),
+ .in1(32'h0),
.out(next_pc)
);
diff --git a/verilog/testbench.v b/verilog/testbench.v
@@ -34,19 +34,21 @@ cpu32 cpu(
.d_data_we(ramwe)
);
-rom #(32,8) rom(
- .addr(romaddr[9:2]),
- .data(romdata)
- );
-
-syncram #(32,8) ram(
+dualsyncram #(32,12) memory(
.clk(clk),
- .addr(ramaddr[9:2]),
- .rdata(ramrdata),
- .wdata(ramwdata),
- .we(ramwe)
+ .a_raddr(romaddr[13:2]),
+ .a_rdata(romdata),
+ .a_waddr(12'b0),
+ .a_wdata(32'b0),
+ .a_we(1'b0),
+ .b_raddr(ramaddr[13:2]),
+ .b_rdata(ramrdata),
+ .b_waddr(ramaddr[13:2]),
+ .b_wdata(ramwdata),
+ .b_we(ramwe)
);
+initial $readmemh("test.hex",memory.mem);
/*
wire tx;