diff options
| author | Alejandro Soto <alejandro@34project.org> | 2022-09-25 17:46:38 -0600 |
|---|---|---|
| committer | Alejandro Soto <alejandro@34project.org> | 2022-09-25 17:46:38 -0600 |
| commit | b5f43ef8431532b1e0b498a88072fdfd2cf81ac9 (patch) | |
| tree | eac985d217721ce4ef4b6e355cce611c9e4d3a82 | |
| parent | 72991c8eb6791111de0378cfc46ede8581d53e2a (diff) | |
Implement ALU
| -rw-r--r-- | rtl/core/alu/add.sv | 20 | ||||
| -rw-r--r-- | rtl/core/alu/alu.sv | 139 | ||||
| -rw-r--r-- | rtl/core/alu/and.sv | 12 | ||||
| -rw-r--r-- | rtl/core/alu/orr.sv | 12 | ||||
| -rw-r--r-- | rtl/core/alu/shifter.sv | 12 | ||||
| -rw-r--r-- | rtl/core/alu/xor.sv | 12 | ||||
| -rw-r--r-- | rtl/core/isa.sv | 17 | ||||
| -rw-r--r-- | rtl/core/uarch.sv | 26 |
8 files changed, 226 insertions, 24 deletions
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 |
