summaryrefslogtreecommitdiff
path: root/rtl
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--rtl/core/alu/add.sv20
-rw-r--r--rtl/core/alu/alu.sv139
-rw-r--r--rtl/core/alu/and.sv12
-rw-r--r--rtl/core/alu/orr.sv12
-rw-r--r--rtl/core/alu/shifter.sv12
-rw-r--r--rtl/core/alu/xor.sv12
-rw-r--r--rtl/core/isa.sv17
-rw-r--r--rtl/core/uarch.sv26
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