commit 31cf511b4e78dc976efaf7c806265f1e2f0850f8
parent 838c1bf8f985da394032076e6aad3020ee61b3e1
Author: Brian Swetland <swetland@frotz.net>
Date: Wed, 28 Nov 2018 09:57:09 -0800
cpu16: conditional branches and branch with link
Diffstat:
3 files changed, 17 insertions(+), 7 deletions(-)
diff --git a/hdl/cpu16.sv b/hdl/cpu16.sv
@@ -34,18 +34,21 @@ reg ir_valid_next;
reg [15:0]pc = 16'd0;
reg [15:0]ir = 16'd0;
+reg [15:0]ir_link = 16'b0;
reg ir_valid = 1'b0;
assign ins_rd_addr = pc_next;
assign ins_rd_req = 1'b1;
+wire [15:0]pc_plus_1 = pc + 16'h0001;
+
always_comb begin
if (reset) begin
pc_next = 16'h0000;
- end else if (ex_do_branch_imm) begin
- pc_next = ex_branch_tgt;
+ end else if (ex_do_branch) begin
+ pc_next = ex_do_branch_reg ? ex_adata : ex_branch_tgt;
end else if (ins_rd_rdy) begin
- pc_next = pc + 16'h0001;
+ pc_next = pc_plus_1;
end else begin
pc_next = pc;
end
@@ -56,6 +59,7 @@ end
always_ff @(posedge clk) begin
pc <= pc_next;
ir <= ir_next;
+ ir_link <= pc_plus_1;
ir_valid <= ir_valid_next;
end
@@ -177,15 +181,16 @@ regs16 regs(
.asel(ir_asel),
.bsel(do_mem_write ? ir_csel : ir_bsel),
.wsel(ex_wsel),
- .wreg(ex_do_wreg_alu),
+ .wreg(ex_do_wreg_alu | ex_do_wr_link),
.adata(ex_adata),
.bdata(ex_bdata),
- .wdata(ex_alu_rdata)
+ .wdata(ex_do_wr_link ? ex_link : ex_alu_rdata)
);
// ---- EXECUTE ----
reg [15:0]ex_branch_tgt = 16'b0;
+reg [15:0]ex_link = 16'b0;
reg [2:0]ex_alu_op = 3'b0;
reg [2:0]ex_wsel = 3'b0;
reg ex_do_wreg_alu = 1'b0;
@@ -202,6 +207,9 @@ reg ex_do_mem_write = 1'b0;
reg [15:0]ex_imm = 16'b0;
+wire ex_adata_zero = (ex_adata == 16'b0);
+wire ex_do_branch = ex_do_branch_reg | ex_do_branch_imm | (ex_do_branch_cond & (ex_do_branch_zero == ex_adata_zero));
+
`ifdef CPU16_WITH_TRACE
assign trace = {
pc,
@@ -226,10 +234,11 @@ assign trace = {
`endif
always_ff @(posedge clk) begin
+ ex_branch_tgt <= pc + (do_branch_imm ? ir_imm_s11 : ir_imm_s7);
+ ex_link <= ir_link;
// for mem-read or mem-write we use the ALU for Ra + imm7
ex_alu_op <= (do_adata_zero | do_mem_read | do_mem_write) ? 3'b0 : ir_alu_op;
ex_wsel <= do_wr_link ? 3'd7 : ir_csel;
- ex_branch_tgt <= pc + (do_branch_imm ? ir_imm_s11 : ir_imm_s7);
ex_do_wreg_alu <= do_wreg_alu;
ex_do_wreg_mem <= do_wreg_mem;
ex_do_adata_zero <= do_adata_zero;
diff --git a/hdl/ice40up.pcf b/hdl/ice40up.pcf
@@ -16,3 +16,4 @@ set_io spi_cs 16
set_io out1 3
set_io out2 4
+set_io uart_tx 28
diff --git a/hdl/testbench.sv b/hdl/testbench.sv
@@ -14,7 +14,7 @@ reg burp = 1'b0;
always @(posedge clk) begin
count <= count + 16'd1;
- burp <= (count >= 16'd0010) && (count <= 16'd0012) ? 1'b1 : 1'b0;
+// burp <= (count >= 16'd0010) && (count <= 16'd0012) ? 1'b1 : 1'b0;
if (count == 16'd0005) reset <= 1'b0;
if (count == 16'd1000) $finish;
if (cpu.ir == 16'hFFFF) begin