From af2f49f863deaeb6dc905bbb15701b50bc139873 Mon Sep 17 00:00:00 2001 From: Alejandro Soto Date: Mon, 26 Sep 2022 09:26:35 -0600 Subject: Implement ALU shifter --- rtl/core/alu/alu.sv | 14 +++++- rtl/core/alu/shifter.sv | 33 +++++++++++--- rtl/core/arm810.sv | 11 +++-- rtl/core/cycles.sv | 116 +++++++++++++++++++++++++++++++++++------------- 4 files changed, 132 insertions(+), 42 deletions(-) (limited to 'rtl/core') diff --git a/rtl/core/alu/alu.sv b/rtl/core/alu/alu.sv index 914b40e..f5a0487 100644 --- a/rtl/core/alu/alu.sv +++ b/rtl/core/alu/alu.sv @@ -5,7 +5,8 @@ module core_alu ( input alu_control ctrl, input logic[W - 1:0] a, - b, + base, + input logic[7:0] shift, input logic c_in, output logic[W - 1:0] q, @@ -14,12 +15,21 @@ module core_alu ); logic c, v, swap, sub, and_not, c_shifter, c_add, v_add; - logic[W - 1:0] swap_a, swap_b, neg_b, c_in_add, q_add, q_and, q_orr, q_xor; + logic[W - 1:0] b, swap_a, swap_b, neg_b, c_in_add, q_add, q_and, q_orr, q_xor; assign swap_a = swap ? b : a; assign swap_b = swap ? a : b; assign neg_b = -swap_b; + core_alu_shifter #(.W(W)) shifter + ( + .base(base), + .shift(shift), + .b(b), + .c(c_shifter), + .* + ); + core_alu_add #(.W(W)) op_add ( .a(swap_a), diff --git a/rtl/core/alu/shifter.sv b/rtl/core/alu/shifter.sv index 3effb2c..4385b41 100644 --- a/rtl/core/alu/shifter.sv +++ b/rtl/core/alu/shifter.sv @@ -1,12 +1,35 @@ -module alu_shl +`include "core/uarch.sv" + +module core_alu_shifter #(parameter W=16) ( - input logic[W - 1:0] a, - b, - output logic[W - 1:0] q, + input alu_control ctrl, + input logic[W - 1:0] base, + input logic[7:0] shift, + input logic c_in, + + output logic[W - 1:0] b, output logic c ); - assign {c, q} = {1'b0, a} << b; + logic [W - 1:0] b_no_c, b_shl, b_shr, b_ror; + logic [W:0] sign_mask; + logic c_shl, c_shr; + + assign sign_mask = {(W + 1){ctrl.sign_extend & base[W - 1]}}; + assign {c_shl, b_shl} = {c_in, base} << shift; + assign {b_shr, c_shr} = {base, c_in} >> shift | ~(sign_mask >> shift); + assign b_ror = b_shr | base << (W - shift); + + assign b = {b_no_c[W - 1] | (ctrl.put_carry & c_in), b_no_c[W - 2:0]}; + assign c = ctrl.shr | ctrl.ror ? c_shr : c_shl; + + always_comb + if(ctrl.ror) + b = b_ror; + else if(ctrl.shr) + b = {b_shr[W - 1] | (ctrl.put_carry & c_in), b_shr[W - 2:0]}; + else + b = b_shl; endmodule diff --git a/rtl/core/arm810.sv b/rtl/core/arm810.sv index d9939fd..b344836 100644 --- a/rtl/core/arm810.sv +++ b/rtl/core/arm810.sv @@ -45,11 +45,13 @@ module arm810 .* ); - reg_num rd; + reg_num rd, ra, rb; logic explicit_branch, writeback, update_flags; ptr branch_target; psr_mode reg_mode; alu_control alu_ctrl; + word alu_base; + logic[7:0] alu_shift; core_cycles cycles ( @@ -70,8 +72,8 @@ module arm810 core_regs regs ( - .rd_r_a(0), //TODO - .rd_r_b(0), //TODO + .rd_r_a(ra), + .rd_r_b(rb), .rd_mode(reg_mode), .wr_mode(reg_mode), .wr_r(rd), @@ -87,7 +89,8 @@ module arm810 ( .ctrl(alu_ctrl), .a(rd_value_a), - .b(rd_value_b), + .base(alu_base), + .shift(alu_shift), .c_in(flags.c), .q(wr_value), .nzcv(alu_flags), diff --git a/rtl/core/cycles.sv b/rtl/core/cycles.sv index 84bbd32..f503188 100644 --- a/rtl/core/cycles.sv +++ b/rtl/core/cycles.sv @@ -2,63 +2,116 @@ module core_cycles ( - input logic clk, - dec_execute, - dec_branch, - dec_writeback, - dec_update_flags, - input ptr dec_branch_offset, - input alu_decode dec_alu, - input ptr fetch_insn_pc, + input logic clk, + dec_execute, + dec_branch, + dec_writeback, + dec_update_flags, + input ptr dec_branch_offset, + input alu_decode dec_alu, + input ptr fetch_insn_pc, + input word rd_value_b, output logic stall, branch, writeback, update_flags, output reg_num rd, + ra, + rb, output ptr branch_target, pc, pc_visible, output psr_mode reg_mode, - output alu_control alu + output alu_control alu, + output word alu_base, + output logic[7:0] alu_shift ); enum { - EXECUTE + EXECUTE, + RD_SHIFT } cycle, next_cycle; + logic final_writeback, data_snd_is_imm, data_snd_shift_by_reg; + logic[5:0] data_shift_imm; + logic[7:0] data_imm; + word saved_base; + reg_num r_shift; + assign stall = next_cycle != EXECUTE; assign pc_visible = pc + 2; - assign next_cycle = EXECUTE; //TODO assign reg_mode = `MODE_SVC; //TODO + always_comb begin + next_cycle = EXECUTE; + if((cycle == EXECUTE) & data_snd_shift_by_reg) + next_cycle = RD_SHIFT; + + unique case(cycle) + RD_SHIFT: + alu_base = saved_base; + + default: + if(data_snd_is_imm) + alu_base = {{24{1'b0}}, data_imm}; + else + alu_base = rd_value_b; + endcase + + unique case(cycle) + RD_SHIFT: alu_shift = rd_value_b[7:0]; + default: alu_shift = {2'b00, data_shift_imm}; + endcase + end + always_ff @(posedge clk) begin cycle <= next_cycle; - if(next_cycle == EXECUTE) begin - branch <= 0; - writeback <= 0; - update_flags <= 0; - branch_target <= 30'bxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; + unique case(next_cycle) + EXECUTE: begin + branch <= 0; + writeback <= 0; + update_flags <= 0; + branch_target <= 30'bxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; - if(dec_execute) begin - branch <= dec_branch; - writeback <= dec_writeback; - branch_target <= pc_visible + dec_branch_offset; + if(dec_execute) begin + branch <= dec_branch; + writeback <= dec_writeback & ~dec_alu.snd_shift_by_reg; + update_flags <= dec_update_flags; + branch_target <= pc_visible + dec_branch_offset; + + data_snd_is_imm <= dec_alu.snd_is_imm; + data_snd_shift_by_reg <= dec_alu.snd_shift_by_reg; + data_imm <= dec_alu.imm; + data_shift_imm <= dec_alu.shift_imm; + + alu.op <= dec_alu.op; + alu.shl <= dec_alu.shl; + alu.shr <= dec_alu.shr; + alu.ror <= dec_alu.ror; + alu.put_carry <= dec_alu.put_carry; + alu.sign_extend <= dec_alu.sign_extend; + + rd <= dec_alu.rd; + ra <= dec_alu.rn; + rb <= dec_alu.r_snd; + r_shift <= dec_alu.r_shift; + + final_writeback <= dec_writeback; + end + + pc <= fetch_insn_pc; end - alu.op <= dec_alu.op; - alu.shl <= dec_alu.shl; - alu.shr <= dec_alu.shr; - alu.ror <= dec_alu.ror; - alu.put_carry <= dec_alu.put_carry; - alu.sign_extend <= dec_alu.sign_extend; - - pc <= fetch_insn_pc; - rd <= dec_alu.rd; - update_flags <= dec_update_flags; - end + RD_SHIFT: begin + rb <= r_shift; + data_snd_shift_by_reg <= 0; + saved_base <= rd_value_b; + writeback <= final_writeback; + end + endcase end initial begin @@ -66,6 +119,7 @@ module core_cycles branch = 1; writeback = 0; + data_snd_shift_by_reg = 0; branch_target = 30'd0; pc = 0; end -- cgit v1.2.3