summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--alu.v5
-rw-r--r--alu_stage.v10
-rw-r--r--alu_tb.v9
-rw-r--r--ctrl_decode.v4
-rw-r--r--ctrl_encode.v4
-rw-r--r--decoder.v3
-rw-r--r--decoder_stage.v7
-rw-r--r--tests/alu15
8 files changed, 42 insertions, 15 deletions
diff --git a/alu.v b/alu.v
index 63812a7..37a84d5 100644
--- a/alu.v
+++ b/alu.v
@@ -2,6 +2,7 @@ module alu (
input [3:0] op,
input [15:0] x,
input [15:0] y,
+ input carry_in,
output [15:0] result,
output zero,
output carry
@@ -36,7 +37,7 @@ module alu (
assign issum = ~|(op[3:1]);
- assign sum = x + (op[0] ? ~y + 1 : y);
+ assign sum = x + ({16{op[0]}} ^ y) + (op[0] ^ carry_in);
assign prod = x * y;
assign quot = x / y;
assign anded = x & y;
@@ -62,6 +63,6 @@ module alu (
shifted;
assign zero = ~(|result);
- assign carry = issum ? sum[16] : 1'b0;
+ assign carry = issum ? op[0] ^ sum[16] : 1'b0;
endmodule
diff --git a/alu_stage.v b/alu_stage.v
index b178cad..92c8246 100644
--- a/alu_stage.v
+++ b/alu_stage.v
@@ -2,7 +2,7 @@ module alu_stage (
input clk,
input en,
input [15:0] pc_in,
- input [32:0] control_signals_in,
+ input [34:0] control_signals_in,
input [15:0] imm_in,
// register file
@@ -24,7 +24,7 @@ module alu_stage (
output setPC,
output [15:0] setPCValue,
- output reg [32:0] control_signals_out,
+ output reg [34:0] control_signals_out,
output reg [15:0] imm_out,
output reg [15:0] pc_out,
@@ -39,6 +39,8 @@ module alu_stage (
wire [1:0] aluOpSource1_in;
wire [1:0] aluOpSource2_in;
wire aluDest_in;
+ wire [1:0] aluCarrySource;
+ wire aluCarry_in;
wire [2:0] regDest_in;
wire regSetH_in;
wire regSetL_in;
@@ -58,6 +60,7 @@ module alu_stage (
.aluOpSource1(aluOpSource1_in), // ALU first operand: 0 = reg, 1 = memory read, 2 = imm8, 3 = PC
.aluOpSource2(aluOpSource2_in), // ALU second operand: 0 = reg, 1 = ~reg, 2 = PC, 3 = ???
.aluDest(aluDest_in), // 0 = reg, 1 = PC
+ .aluCarrySource(aluCarrySource), // ALU carry input source: 0 = zero, 1 = one, 2 = carry flag, 3 = inverted carry flag
.regDest(regDest_in),
.regSetH(regSetH_in),
@@ -83,12 +86,15 @@ module alu_stage (
aluOpSource1_in == 2'h0 ? rf_dataB :
aluOpSource1_in == 2'h1 ? ~rf_dataIn : pc_in;
+ assign aluCarry_in = aluCarrySource[0] ^ (aluCarrySource[1] & statusReg[0]);
+
wire [15:0] aluResult;
wire aluZero, aluCarry;
alu alu_inst (
.op(aluOp_in),
.x(aluSrc1),
.y(aluSrc2),
+ .carry_in(aluCarry_in),
.result(aluResult),
.zero(aluZero),
.carry(aluCarry)
diff --git a/alu_tb.v b/alu_tb.v
index 31141ce..bfe3e8a 100644
--- a/alu_tb.v
+++ b/alu_tb.v
@@ -11,6 +11,7 @@ module alu_tb ();
reg expected_zero;
wire carry;
reg expected_carry;
+ reg carry_in;
reg [3*8:0] opstr;
integer file, r;
@@ -24,9 +25,12 @@ module alu_tb ();
while (!$feof(file)) begin
r = $fscanf(file, " 0x%x %3s 0x%x = 0x%x Z=%x C=%x\n", x, opstr, y, expected_result, expected_zero, expected_carry);
+ carry_in = opstr == "++" || opstr == "--";
case (opstr)
- "+" : op = 0;
- "-" : op = 1;
+ "+" : op = 0;
+ "++" : op = 0;
+ "-" : op = 1;
+ "--" : op = 1;
"*" : op = 2;
"/" : op = 3;
"&" : op = 4;
@@ -59,6 +63,7 @@ module alu_tb ();
.op(op),
.x(x),
.y(y),
+ .carry_in(carry_in),
.result(result),
.zero(zero),
.carry(carry)
diff --git a/ctrl_decode.v b/ctrl_decode.v
index ede591f..86ecc97 100644
--- a/ctrl_decode.v
+++ b/ctrl_decode.v
@@ -1,5 +1,5 @@
module ctrl_decode (
- input [32:0] control_signals,
+ input [34:0] control_signals,
output [3:0] aluOp,
output [2:0] aluReg1,
@@ -7,6 +7,7 @@ module ctrl_decode (
output [1:0] aluOpSource1, // ALU first operand: 0 = reg, 1 = memory read, 2 = imm8, 3 = PC
output [1:0] aluOpSource2, // ALU second operand: 0 = reg, 1 = ~reg, 2 = PC, 3 = ???
output aluDest, // 0 = reg, 1 = PC
+ output [1:0] aluCarrySource, // ALU carry flag input source
output [2:0] regDest,
output regSetH,
@@ -28,6 +29,7 @@ module ctrl_decode (
aluOpSource1,
aluOpSource2,
aluDest,
+ aluCarrySource,
regDest,
regSetH,
regSetL,
diff --git a/ctrl_encode.v b/ctrl_encode.v
index d76f34f..92ad3c6 100644
--- a/ctrl_encode.v
+++ b/ctrl_encode.v
@@ -5,6 +5,7 @@ module ctrl_encode (
input [1:0] aluOpSource1, // ALU first operand: 0 = reg, 1 = memory read, 2 = imm8, 3 = PC
input [1:0] aluOpSource2, // ALU second operand: 0 = reg, 1 = ~reg, 2 = PC, 3 = ???
input aluDest, // 0 = reg, 1 = PC
+ input [1:0] aluCarrySource, // ALU carry flag input source
input [2:0] regDest,
input regSetH,
@@ -18,7 +19,7 @@ module ctrl_encode (
input [5:0] setRegCond, // {should set when condition is true, Z doesn't matter, S doesn't matter, Z must be this, S must be this}
- output [32:0] control_signals
+ output [34:0] control_signals
);
assign control_signals = {
@@ -28,6 +29,7 @@ module ctrl_encode (
aluOpSource1,
aluOpSource2,
aluDest,
+ aluCarrySource,
regDest,
regSetH,
regSetL,
diff --git a/decoder.v b/decoder.v
index d6a1e02..3e08df3 100644
--- a/decoder.v
+++ b/decoder.v
@@ -7,6 +7,7 @@ module decoder (
output [1:0] aluOpSource1, // ALU first operand: 0 = reg, 1 = memory read, 2 = imm8, 3 = PC
output [1:0] aluOpSource2, // ALU second operand: 0 = reg, 1 = ~reg, 2 = PC, 3 = ???
output aluDest, // 0 = reg, 1 = PC
+ output [1:0] aluCarrySource, // ALU carry input source: 0 = zero, 1 = one, 2 = carry, 3 = ~carry
output [2:0] regDest,
output regSetH,
@@ -216,6 +217,8 @@ module decoder (
assign regDest = reg0;
+ assign aluCarrySource = 2'h0;
+
assign regSetH =
instr_mov ? (mov_word | mov_dest_byte_high) :
instr_movimm ? movimm_high :
diff --git a/decoder_stage.v b/decoder_stage.v
index fcc7d60..fa2721e 100644
--- a/decoder_stage.v
+++ b/decoder_stage.v
@@ -5,7 +5,7 @@ module decoder_stage (
input [15:0] instr_in,
input [15:0] pc_in,
- output reg [32:0] control_signals_out,
+ output reg [34:0] control_signals_out,
output reg [15:0] imm_out,
output reg [15:0] pc_out
);
@@ -16,6 +16,7 @@ module decoder_stage (
wire [1:0] aluOpSource1_next;
wire [1:0] aluOpSource2_next;
wire aluDest_next;
+ wire [1:0] aluCarrySource_next;
wire [2:0] regDest_next;
wire regSetH_next;
wire regSetL_next;
@@ -35,6 +36,7 @@ module decoder_stage (
.aluOpSource1(aluOpSource1_next),
.aluOpSource2(aluOpSource2_next),
.aluDest(aluDest_next),
+ .aluCarrySource(aluCarrySource_next),
.regDest(regDest_next),
.regSetH(regSetH_next),
.regSetL(regSetL_next),
@@ -47,7 +49,7 @@ module decoder_stage (
.imm(imm_next)
);
- wire [32:0] control_signals_next;
+ wire [34:0] control_signals_next;
ctrl_encode encode_inst (
.aluOp(aluOp_next),
@@ -56,6 +58,7 @@ module decoder_stage (
.aluOpSource1(aluOpSource1_next),
.aluOpSource2(aluOpSource2_next),
.aluDest(aluDest_next),
+ .aluCarrySource(aluCarrySource_next),
.regDest(regDest_next),
.regSetH(regSetH_next),
.regSetL(regSetL_next),
diff --git a/tests/alu b/tests/alu
index 474acbb..d271a0c 100644
--- a/tests/alu
+++ b/tests/alu
@@ -1,8 +1,10 @@
# X op Y = RESULT ZERO CARRY
#
# Operations:
-# + : add
-# - : subtract
+# + : add (x+y)
+# ++ : add with carry (x+y+1)
+# - : subtract (x-y)
+# -- : subtract with borrow (x-y-1)
# * : multiply
# / : divide
# & : and
@@ -17,9 +19,12 @@
# ->> : right shift extended with most significant bit
# >>> : right rotate
-0x0123 + 0x1234 = 0x1357 Z=0 C=0
-0x0123 - 0x1234 = 0xeeef Z=0 C=1
-0x0123 - 0x0123 = 0x0000 Z=1 C=0
+0x0123 + 0x1234 = 0x1357 Z=0 C=0
+0x0123 ++ 0x1234 = 0x1358 Z=0 C=0
+0x0123 - 0x1234 = 0xeeef Z=0 C=1
+0x0123 -- 0x1234 = 0xeeee Z=0 C=1
+0x0123 - 0x0123 = 0x0000 Z=1 C=0
+0x0123 -- 0x0123 = 0xffff Z=0 C=1
0x0123 * 0x1234 = 0xb11c Z=0 C=0
0x3e58 / 0x0078 = 0x0085 Z=0 C=0
0xaf74 & 0x7cc7 = 0x2c44 Z=0 C=0