diff --git a/rtl/alu.v b/rtl/alu.v index 486ff0a..8e7ed9d 100644 --- a/rtl/alu.v +++ b/rtl/alu.v @@ -3,17 +3,22 @@ module alu (input [31:0] in_a, in_b, output reg [31:0] out); `include "alu_func.vh" + + reg signed [31:0] s_in_a; + reg signed [31:0] s_in_b; always@ (*) begin + s_in_a = in_a; + s_in_b = in_b; case (op_code) ADD : out <= in_a + in_b; SUB : out <= in_a - in_b; SLL : out <= in_a << in_b; - SLT : out <= ((in_a[31] != in_b[31]) ? in_a[31] == 1'b1 : in_a < in_b) ? 1 : 0; + SLT : out <= (s_in_a < s_in_b) ? 1 : 0; SLTU : out <= (in_a < in_b) ? 1 : 0; XOR : out <= in_a ^ in_b; SRL : out <= in_a >> in_b; - SRA : out <= in_a >>> in_b; + SRA : out <= s_in_a >>> in_b; OR : out <= in_a | in_b; AND : out <= in_a & in_b; default : out <= 32'b0; diff --git a/tb/tb_alu.v b/tb/tb_alu.v index f05ad3a..3abc655 100644 --- a/tb/tb_alu.v +++ b/tb/tb_alu.v @@ -17,22 +17,58 @@ module tb_alu (); ); initial begin - // ALU - Add + // ALU - add + op_code = ADD; in_a = 32'b0; in_b = 32'b0; - op_code = ADD; `assert("alu : 0 + 0", out, 0) in_a = 32'b1; `assert("alu : 1 + 0", out, 1) in_b = 32'b1; `assert("alu : 1 + 1", out, 2) - op_code = 4'b0001; + in_a = 32'b0; + `assert("alu : 0 + 1", out, 1) + in_a = 32'b1111; + in_b = 32'b1111; + `assert("alu : 15 + 15", out, 30) + in_a = 32'b11111111111111111111111111111111; + in_b = 32'b00000000000000000000000000000000; + `assert("alu : 0 + -1", out, 32'b11111111111111111111111111111111) + in_a = 32'b11111111111111111111111111111111; + in_b = 32'b00000000000000000000000000000001; + `assert("alu : 1 + -1", out, 0) + in_a = 32'b10000000000000000000000000000000; + in_b = 32'b11111111111111111111111111111111; + `assert("alu : MIN_INT + -1", out, 32'b01111111111111111111111111111111) + + // ALU - sub + op_code = SUB; + in_a = 32'b0; + in_b = 32'b0; + `assert("alu : 0 - 0", out, 0) + in_a = 32'b1; + `assert("alu : 1 - 0", out, 1) + in_b = 32'b1; `assert("alu : 1 - 1", out, 0) + in_a = 32'b0; + `assert("alu : 0 - 1", out, 32'b11111111111111111111111111111111) + in_a = 32'b11111; + in_b = 32'b1111; + `assert("alu : 31 - 15", out, 16) + in_a = 32'b11111111111111111111111111111111; + in_b = 32'b00000000000000000000000000000000; + `assert("alu : -1 - 0", out, 32'b11111111111111111111111111111111) + in_a = 32'b11111111111111111111111111111111; + in_b = 32'b00000000000000000000000000000001; + `assert("alu : -1 - 1", out, 32'b11111111111111111111111111111110) + in_a = 32'b10000000000000000000000000000000; + in_b = 32'b11111111111111111111111111111111; + `assert("alu : MIN_INT - -1", out, 32'b10000000000000000000000000000001) // ALU - left shift + op_code = SLL; in_a = 32'b1; in_b = 32'b1; - op_code = SLL; `assert("alu : 1 << 1", out, 2) in_b = 32'b10; `assert("alu : 1 << 2", out, 4) @@ -46,9 +82,9 @@ module tb_alu (); `assert("alu : 3 << 31", out, 32'b00000000000000000000000000000000) // ALU - less than + op_code = SLT; in_a = 32'b0; in_b = 32'b0; - op_code = SLT; `assert("alu : 0 < 0", out, 0) in_b = 32'b10; `assert("alu : 0 << 2", out, 1) @@ -64,9 +100,9 @@ module tb_alu (); `assert("alu : MIN_INT << MIN_INT + 1", out, 1) // ALU - xor + op_code = XOR; in_a = 32'b0; in_b = 32'b0; - op_code = XOR; `assert("alu : 0 ^ 0", out, 32'b00000000000000000000000000000000) in_a = 32'b1; `assert("alu : 1 ^ 0", out, 32'b00000000000000000000000000000001) @@ -84,9 +120,9 @@ module tb_alu (); `assert("alu : 00000011001000010001000011000000 ^ 10101111001011101110111111111011", out, 32'b10101100000011111111111100111011) // ALU - right shift + op_code = SRL; in_a = 32'b1; in_b = 32'b1; - op_code = SRL; `assert("alu : 1 >> 1", out, 0) in_a = 32'b10; `assert("alu : 2 >> 1", out, 1) @@ -102,24 +138,64 @@ module tb_alu (); in_b = 32'b11111; `assert("alu : 1000..111 >> 31", out, 32'b00000000000000000000000000000001) - // // ALU - logical right shift - // in_a = 32'b1; - // in_b = 32'b1; - // op_code = 4'b0110; - // `assert("alu : 1 >> 1", out, 0) - // in_a = 32'b10; - // `assert("alu : 2 >> 1", out, 1) - // in_a = 32'b11; - // `assert("alu : 3 >> 2", out, 1) - // in_a = 32'b11110; - // in_b = 32'b1; - // `assert("alu : 30 >> 1", out, 32'b1111) - // in_a = 32'b10000000000000000000000000000000; - // in_b = 32'b11111; - // `assert("alu : 1000...000 >> 31", out, 32'b00000000000000000000000000000001) - // in_a = 32'b10000000111100000000000111111111; - // in_b = 32'b11111; - // `assert("alu : 1000..111 >> 31", out, 32'b00000000000000000000000000000001) + // ALU - arithmetic right shift + op_code = SRA; + in_a = 32'b1; + in_b = 32'b1; + `assert("alu : 1 >>> 1", out, 0) + in_a = 32'b10; + `assert("alu : 2 >>> 1", out, 1) + in_a = 32'b11; + `assert("alu : 3 >>> 2", out, 1) + in_a = 32'b11110; + in_b = 32'b1; + `assert("alu : 30 >>> 1", out, 32'b1111) + in_a = 32'b10000000000000000000000000000000; + in_b = 32'b11111; + `assert("alu : 1000...000 >>> 31", out, 32'b11111111111111111111111111111111) + in_a = 32'b10000000111100000000000111111111; + in_b = 32'b11111; + `assert("alu : 1000..111 >>> 31", out, 32'b11111111111111111111111111111111) + + // ALU - or + op_code = OR; + in_a = 32'b0; + in_b = 32'b0; + `assert("alu : 0 | 0", out, 32'b00000000000000000000000000000000) + in_a = 32'b1; + `assert("alu : 1 | 0", out, 32'b00000000000000000000000000000001) + in_a = 32'b0; + in_b = 32'b1; + `assert("alu : 0 | 1", out, 32'b00000000000000000000000000000001) + in_a = 32'b11111111111111111111111111111111; + in_b = 32'b11111111111111111111111111111111; + `assert("alu : MAX_INT | MAX_INT", out, 32'b11111111111111111111111111111111) + in_a = 32'b00000000000000000000000000000000; + in_b = 32'b11111111111111111111111111111111; + `assert("alu : 0 | MAX_INT", out, 32'b11111111111111111111111111111111) + in_a = 32'b00000011001000010001000011000000; + in_b = 32'b10101111001011101110111111111011; + `assert("alu : 00000011001000010001000011000000 | 10101111001011101110111111111011", out, 32'b10101111001011111111111111111011) + + // ALU - and + op_code = AND; + in_a = 32'b0; + in_b = 32'b0; + `assert("alu : 0 & 0", out, 32'b00000000000000000000000000000000) + in_a = 32'b1; + `assert("alu : 1 & 0", out, 32'b00000000000000000000000000000000) + in_a = 32'b0; + in_b = 32'b1; + `assert("alu : 0 & 1", out, 32'b00000000000000000000000000000000) + in_a = 32'b11111111111111111111111111111111; + in_b = 32'b11111111111111111111111111111111; + `assert("alu : MAX_INT & MAX_INT", out, 32'b11111111111111111111111111111111) + in_a = 32'b00000000000000000000000000000000; + in_b = 32'b11111111111111111111111111111111; + `assert("alu : 0 & MAX_INT", out, 32'b00000000000000000000000000000000) + in_a = 32'b00000011001000010001000011000000; + in_b = 32'b10101111001011101110111111111011; + `assert("alu : 00000011001000010001000011000000 & 10101111001011101110111111111011", out, 32'b00000011001000000000000011000000) `end_message end