From b5f43ef8431532b1e0b498a88072fdfd2cf81ac9 Mon Sep 17 00:00:00 2001 From: Alejandro Soto Date: Sun, 25 Sep 2022 17:46:38 -0600 Subject: Implement ALU --- rtl/core/alu/add.sv | 20 +++++++ rtl/core/alu/alu.sv | 139 ++++++++++++++++++++++++++++++++++++++++++++++++ rtl/core/alu/and.sv | 12 +++++ rtl/core/alu/orr.sv | 12 +++++ rtl/core/alu/shifter.sv | 12 +++++ rtl/core/alu/xor.sv | 12 +++++ rtl/core/isa.sv | 17 ------ rtl/core/uarch.sv | 26 ++++++--- 8 files changed, 226 insertions(+), 24 deletions(-) create mode 100644 rtl/core/alu/add.sv create mode 100644 rtl/core/alu/alu.sv create mode 100644 rtl/core/alu/and.sv create mode 100644 rtl/core/alu/orr.sv create mode 100644 rtl/core/alu/shifter.sv create mode 100644 rtl/core/alu/xor.sv (limited to 'rtl') diff --git a/rtl/core/alu/add.sv b/rtl/core/alu/add.sv new file mode 100644 index 0000000..12bd237 --- /dev/null +++ b/rtl/core/alu/add.sv @@ -0,0 +1,20 @@ +module core_alu_add +#(parameter W=16) +( + input logic[W - 1:0] a, + b, + c_in, + + output logic[W - 1:0] q, + output logic c, + v +); + + logic sgn_a, sgn_b, sgn_q; + assign {sgn_a, sgn_b, sgn_q} = {a[W - 1], b[W - 1], q[W - 1]}; + + //TODO: No sirve el carry + assign {c, q} = {1'b0, a} + {1'b0, b} + {1'b0, c_in}; + assign v = (sgn_a ~^ sgn_b) & (sgn_a ^ sgn_q); + +endmodule diff --git a/rtl/core/alu/alu.sv b/rtl/core/alu/alu.sv new file mode 100644 index 0000000..4d0a9cc --- /dev/null +++ b/rtl/core/alu/alu.sv @@ -0,0 +1,139 @@ +`include "core/psr.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, + + output logic[W - 1:0] q, + output psr_flags nzcv, + output logic v_valid +); + + 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; + + assign swap_a = swap ? b : a; + assign swap_b = swap ? a : b; + assign neg_b = -swap_b; + + core_alu_add #(.W(W)) op_add + ( + .a(swap_a), + .b(sub ? neg_b : swap_b), + .c_in(c_in_add), + .q(q_add), + .c(c_add), + .v(v_add), + .* + ); + + core_alu_and #(.W(W)) op_and + ( + .b(and_not ? ~b : b), + .q(q_and), + .* + ); + + 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, `ALU_CMP, `ALU_SUB, `ALU_SBC: + swap = 0; + + `ALU_RSB, `ALU_RSC: + swap = 1; + + default: + swap = 1'bx; + endcase + + unique case(op) + `ALU_ADD, `ALU_CMN, `ALU_ADC: + sub = 0; + + `ALU_SUB, `ALU_CMP, `ALU_SBC, `ALU_RSB, `ALU_RSC: + sub = 1; + + default: + sub = 1'bx; + endcase + + unique case(op) + `ALU_ADD, `ALU_CMN, `ALU_CMP, `ALU_SUB, `ALU_RSB: + c_in_add = 0; + + `ALU_ADC: + c_in_add = {{(W - 1){1'b0}}, c_in}; + + `ALU_SBC, `ALU_RSC: + c_in_add = {{(W - 1){~c_in}}, ~c_in}; + + default: + c_in_add = {W{1'bx}}; + endcase + + unique case(op) + `ALU_AND, `ALU_TST: + and_not = 0; + + `ALU_BIC: + and_not = 1; + + default: + and_not = 1'bx; + endcase + + unique case(op) + `ALU_SUB, `ALU_RSB, `ALU_ADD, `ALU_ADC, `ALU_SBC, `ALU_RSC, `ALU_CMP, `ALU_CMN: + q = q_add; + + `ALU_AND, `ALU_TST, `ALU_BIC: + q = q_and; + + `ALU_EOR, `ALU_TEQ: + q = q_xor; + + `ALU_ORR: + q = q_orr; + + `ALU_MOV: + q = b; + + `ALU_MVN: + q = neg_b; + endcase + + unique case(op) + `ALU_AND, `ALU_EOR, `ALU_TST, `ALU_TEQ, `ALU_ORR, `ALU_MOV, `ALU_BIC, `ALU_MVN: begin + c = c_shifter; + v = 1'bx; + v_valid = 0; + end + + `ALU_SUB, `ALU_RSB, `ALU_ADD, `ALU_ADC, `ALU_SBC, `ALU_RSC, `ALU_CMP, `ALU_CMN: begin + c = c_add; + v = v_add; + v_valid = 1; + end + endcase + end + + assign nzcv = {q[W - 1], ~|q, c, v}; + +endmodule diff --git a/rtl/core/alu/and.sv b/rtl/core/alu/and.sv new file mode 100644 index 0000000..d119f24 --- /dev/null +++ b/rtl/core/alu/and.sv @@ -0,0 +1,12 @@ +module core_alu_and +#(parameter W=16) +( + input logic[W - 1:0] a, + b, + + output logic[W - 1:0] q +); + + assign q = a & b; + +endmodule diff --git a/rtl/core/alu/orr.sv b/rtl/core/alu/orr.sv new file mode 100644 index 0000000..1ee87c2 --- /dev/null +++ b/rtl/core/alu/orr.sv @@ -0,0 +1,12 @@ +module core_alu_orr +#(parameter W=16) +( + input logic[W - 1:0] a, + b, + + output logic[W - 1:0] q +); + + assign q = a | b; + +endmodule diff --git a/rtl/core/alu/shifter.sv b/rtl/core/alu/shifter.sv new file mode 100644 index 0000000..3effb2c --- /dev/null +++ b/rtl/core/alu/shifter.sv @@ -0,0 +1,12 @@ +module alu_shl +#(parameter W=16) +( + input logic[W - 1:0] a, + b, + output logic[W - 1:0] q, + output logic c +); + + assign {c, q} = {1'b0, a} << b; + +endmodule diff --git a/rtl/core/alu/xor.sv b/rtl/core/alu/xor.sv new file mode 100644 index 0000000..f55dfc2 --- /dev/null +++ b/rtl/core/alu/xor.sv @@ -0,0 +1,12 @@ +module core_alu_xor +#(parameter W=16) +( + input logic[W - 1:0] a, + b, + + output logic[W - 1:0] q +); + + assign q = a ^ b; + +endmodule diff --git a/rtl/core/isa.sv b/rtl/core/isa.sv index 256c1cc..710b11b 100644 --- a/rtl/core/isa.sv +++ b/rtl/core/isa.sv @@ -64,23 +64,6 @@ typedef logic[3:0] reg_num; `define FIELD_DATA_RD [15:12] `define FIELD_DATA_SHIFTER [11:0] -`define DATA_AND 4'b0000 -`define DATA_EOR 4'b0001 -`define DATA_SUB 4'b0010 -`define DATA_RSB 4'b0011 -`define DATA_ADD 4'b0100 -`define DATA_ADC 4'b0101 -`define DATA_SBC 4'b0110 -`define DATA_RSC 4'b0111 -`define DATA_TST 4'b1000 -`define DATA_TEQ 4'b1001 -`define DATA_CMP 4'b1010 -`define DATA_CMN 4'b1011 -`define DATA_ORR 4'b1100 -`define DATA_MOV 4'b1101 -`define DATA_BIC 4'b1110 -`define DATA_MVN 4'b1111 - // Instrucciones de multiplicación `define INSN_MUL 28'b0000000_?_????_0000_????_1001_???? diff --git a/rtl/core/uarch.sv b/rtl/core/uarch.sv index 1ba039e..be67bd5 100644 --- a/rtl/core/uarch.sv +++ b/rtl/core/uarch.sv @@ -17,12 +17,24 @@ typedef logic[29:0] ptr; */ typedef logic[4:0] reg_index; -typedef enum logic[1:0] -{ - ALU_ADD, - ALU_AND, - ALU_ORR, - ALU_XOR -} alu_op; +typedef logic[3:0] alu_op; + +// Coincide con campo respectivo de instrucciones de procesamiento de datos +`define ALU_AND 4'b0000 +`define ALU_EOR 4'b0001 +`define ALU_SUB 4'b0010 +`define ALU_RSB 4'b0011 +`define ALU_ADD 4'b0100 +`define ALU_ADC 4'b0101 +`define ALU_SBC 4'b0110 +`define ALU_RSC 4'b0111 +`define ALU_TST 4'b1000 +`define ALU_TEQ 4'b1001 +`define ALU_CMP 4'b1010 +`define ALU_CMN 4'b1011 +`define ALU_ORR 4'b1100 +`define ALU_MOV 4'b1101 +`define ALU_BIC 4'b1110 +`define ALU_MVN 4'b1111 `endif -- cgit v1.2.3