diff --git a/rtl/alu.v b/rtl/alu.v index 5c47920..486ff0a 100644 --- a/rtl/alu.v +++ b/rtl/alu.v @@ -2,17 +2,20 @@ module alu (input [31:0] in_a, in_b, input [3:0] op_code, output reg [31:0] out); + `include "alu_func.vh" + always@ (*) begin case (op_code) - 4'b0000 : out <= in_a + in_b; - 4'b0001 : out <= in_a - in_b; - 4'b0010 : out <= in_a << in_b; - 4'b0011 : out <= (in_a < in_b) ? 1 : 0; - 4'b0100 : out <= in_a ^ in_b; - 4'b0101 : out <= in_a >> in_b; - 4'b0111 : out <= in_a >>> in_b; - 4'b1000 : out <= in_a | in_b; - 4'b1001 : out <= in_a & in_b; + 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; + 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; + OR : out <= in_a | in_b; + AND : out <= in_a & in_b; default : out <= 32'b0; endcase end diff --git a/rtl/alu_func.vh b/rtl/alu_func.vh new file mode 100644 index 0000000..8b4142c --- /dev/null +++ b/rtl/alu_func.vh @@ -0,0 +1,10 @@ +parameter [3:0] ADD = 4'b0000; +parameter [3:0] SUB = 4'b0001; +parameter [3:0] SLL = 4'b0010; +parameter [3:0] SLT = 4'b0011; +parameter [3:0] SLTU = 4'b0100; +parameter [3:0] XOR = 4'b0101; +parameter [3:0] SRL = 4'b0110; +parameter [3:0] SRA = 4'b0111; +parameter [3:0] OR = 4'b1000; +parameter [3:0] AND = 4'b1001; \ No newline at end of file diff --git a/rtl/decoder.v b/rtl/decoder.v index debc358..46b74aa 100644 --- a/rtl/decoder.v +++ b/rtl/decoder.v @@ -10,19 +10,19 @@ module decoder (input [31:0] instruction, output reg pc_is_jmp, alu_not); `include "op_code.vh" +`include "alu_func.vh" function [3:0] get_alu_func(input [2:0] op_code, input arithmetic); begin case (op_code) - 3'b000 : get_alu_func = arithmetic ? 4'b0001 : 4'b0000; - 3'b001 : get_alu_func = 4'b0010; - 3'b010 : get_alu_func = 4'b0011; - 3'b011 : get_alu_func = 4'b0011; - 3'b100 : get_alu_func = 4'b0100; - 3'b101 : get_alu_func = arithmetic ? 4'b0111 : 4'b0101; - 3'b110 : get_alu_func = 4'b1000; - 3'b111 : get_alu_func = 4'b1010; - 3'b111 : get_alu_func = 4'b1011; + 3'b000 : get_alu_func = arithmetic ? SUB : ADD; + 3'b001 : get_alu_func = SLL; + 3'b010 : get_alu_func = SLT; + 3'b011 : get_alu_func = SLTU; + 3'b100 : get_alu_func = XOR; + 3'b101 : get_alu_func = arithmetic ? SRA : SRL; + 3'b110 : get_alu_func = OR; + 3'b111 : get_alu_func = AND; default : get_alu_func= 4'b0000; endcase end @@ -31,15 +31,14 @@ endfunction function [3:0] get_alu_func_imm(input [2:0] op_code, input arithmetic); begin case (op_code) - 3'b000 : get_alu_func_imm = 4'b0000; - 3'b001 : get_alu_func_imm = 4'b0010; - 3'b010 : get_alu_func_imm = 4'b0011; - 3'b011 : get_alu_func_imm = 4'b0100; - 3'b100 : get_alu_func_imm = 4'b0101; - 3'b101 : get_alu_func_imm = arithmetic ? 4'b1000 : 4'b0111; - 3'b110 : get_alu_func_imm = 4'b1001; - 3'b111 : get_alu_func_imm = 4'b1010; - 3'b111 : get_alu_func_imm = 4'b1011; + 3'b000 : get_alu_func_imm = ADD; + 3'b001 : get_alu_func_imm = SLL; + 3'b010 : get_alu_func_imm = SLT; + 3'b011 : get_alu_func_imm = SLTU; + 3'b100 : get_alu_func_imm = XOR; + 3'b101 : get_alu_func_imm = arithmetic ? SRA : SRL; + 3'b110 : get_alu_func_imm = OR; + 3'b111 : get_alu_func_imm = AND; default : get_alu_func_imm = 4'b0000; endcase end diff --git a/tb/tb_alu.v b/tb/tb_alu.v index d0d14f1..f05ad3a 100644 --- a/tb/tb_alu.v +++ b/tb/tb_alu.v @@ -2,6 +2,8 @@ `include "tb_tools.vh" module tb_alu (); + `include "../rtl/alu_func.vh" + reg [31:0] in_a; reg [31:0] in_b; reg [3:0] op_code; @@ -15,9 +17,10 @@ module tb_alu (); ); initial begin + // ALU - Add in_a = 32'b0; in_b = 32'b0; - op_code = 4'b0000; + op_code = ADD; `assert("alu : 0 + 0", out, 0) in_a = 32'b1; `assert("alu : 1 + 0", out, 1) @@ -26,6 +29,98 @@ module tb_alu (); op_code = 4'b0001; `assert("alu : 1 - 1", out, 0) + // ALU - left shift + 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) + in_a = 32'b11; + `assert("alu : 3 << 2", out, 12) + in_b = 32'b11110; + `assert("alu : 3 << 30", out, 32'b11000000000000000000000000000000) + in_b = 32'b11111; + `assert("alu : 3 << 31", out, 32'b10000000000000000000000000000000) + in_b = 32'b100000; + `assert("alu : 3 << 31", out, 32'b00000000000000000000000000000000) + + // ALU - less than + 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) + in_a = 32'b11; + `assert("alu : 3 < 2", out, 0) + in_b = 32'b11111111111111111111111111111111; + in_a = 32'b11111111111111111111111111111111; + `assert("alu : -1 < -1", out, 0) + in_b = 32'b0; + `assert("alu : -1 < 0", out, 1) + in_a = 32'b10000000000000000000000000000000; + in_b = 32'b10000000000000000000000000000001; + `assert("alu : MIN_INT << MIN_INT + 1", out, 1) + + // ALU - 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) + 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'b00000000000000000000000000000000) + 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'b10101100000011111111111100111011) + + // ALU - right shift + 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) + 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 - 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) + `end_message end