diff options
| author | Alejandro Soto <alejandro@34project.org> | 2024-01-21 06:23:46 -0600 |
|---|---|---|
| committer | Alejandro Soto <alejandro@34project.org> | 2024-02-20 11:11:17 -0600 |
| commit | f3b18ead59ae02f95dabbf0a1dea40873a816975 (patch) | |
| tree | 8979e50f2a37f66a4cd27e937b480efe60d72cf7 /rtl/core/core_alu.sv | |
| parent | a8bc5a353ea997f73209b39377ee15a73e471237 (diff) | |
rtl: refactor filenames and directory hierarchy
Diffstat (limited to 'rtl/core/core_alu.sv')
| -rw-r--r-- | rtl/core/core_alu.sv | 139 |
1 files changed, 139 insertions, 0 deletions
diff --git a/rtl/core/core_alu.sv b/rtl/core/core_alu.sv new file mode 100644 index 0000000..6dafa65 --- /dev/null +++ b/rtl/core/core_alu.sv @@ -0,0 +1,139 @@ +`include "core/isa.sv" +`include "core/uarch.sv" + +module core_alu +#(parameter W=16) +( + input alu_op op, + input logic[W - 1:0] a, + b, + input logic c_in, + c_logic, + + output logic[W - 1:0] q, + output psr_flags nzcv, + output logic v_valid +); + + logic c, v, c_add, c_sub, c_rsb, v_add, v_sub, v_rsb; + logic[W - 1:0] not_b, q_add, q_sub, q_rsb, q_and, q_bic, q_orr, q_xor; + + assign not_b = ~b; + + core_alu_add #(.W(W), .SUB(0)) op_add + ( + .q(q_add), + .c(c_add), + .v(v_add), + .c_in(c_in && !op `FIELD_ALUOP_ADD_CMN && op `FIELD_ALUOP_ADD_NOTCMN_ADC), + .* + ); + + core_alu_add #(.W(W), .SUB(1)) op_sub + ( + .q(q_sub), + .c(c_sub), + .v(v_sub), + .c_in(!c_in && op `FIELD_ALUOP_SUB_SBC), + .* + ); + + core_alu_add #(.W(W), .SUB(1)) op_rsb + ( + .a(b), + .b(a), + .q(q_rsb), + .c(c_rsb), + .v(v_rsb), + .c_in(!c_in && op `FIELD_ALUOP_RSB_RSC), + .* + ); + + core_alu_and #(.W(W)) op_and + ( + .q(q_and), + .* + ); + + core_alu_and #(.W(W)) op_bic + ( + .b(not_b), + .q(q_bic), + .* + ); + + core_alu_orr #(.W(W)) op_orr + ( + .q(q_orr), + .* + ); + + core_alu_xor #(.W(W)) op_xor + ( + .q(q_xor), + .* + ); + + always_comb begin + unique case(op) + `ALU_ADD, `ALU_ADC, `ALU_CMN: + q = q_add; + + `ALU_SUB, `ALU_SBC, `ALU_CMP: + q = q_sub; + + `ALU_RSB, `ALU_RSC: + q = q_rsb; + + `ALU_AND, `ALU_TST: + q = q_and; + + `ALU_BIC: + q = q_bic; + + `ALU_EOR, `ALU_TEQ: + q = q_xor; + + `ALU_ORR: + q = q_orr; + + `ALU_MOV: + q = b; + + `ALU_MVN: + q = not_b; + endcase + + v = 1'bx; + unique case(op) + `ALU_AND, `ALU_EOR, `ALU_TST, `ALU_TEQ, `ALU_ORR, `ALU_MOV, `ALU_BIC, `ALU_MVN: + c = c_logic; + + `ALU_ADD, `ALU_ADC, `ALU_CMN: begin + c = c_add; + v = v_add; + end + + `ALU_SUB, `ALU_SBC, `ALU_CMP: begin + c = c_sub; + v = v_sub; + end + + `ALU_RSB, `ALU_RSC: begin + c = c_rsb; + v = v_rsb; + end + endcase + + unique case(op) + `ALU_AND, `ALU_EOR, `ALU_TST, `ALU_TEQ, `ALU_ORR, `ALU_MOV, `ALU_BIC, `ALU_MVN: + v_valid = 0; + + `ALU_SUB, `ALU_RSB, `ALU_ADD, `ALU_ADC, `ALU_SBC, `ALU_RSC, `ALU_CMP, `ALU_CMN: + v_valid = 1; + endcase + end + + assign nzcv = {q[W - 1], q == 0, c, v}; + +endmodule |
