92 lines
3.3 KiB
Verilog
92 lines
3.3 KiB
Verilog
`include "VX_define.vh"
|
|
|
|
module VX_alu_unit #(
|
|
parameter CORE_ID = 0
|
|
) (
|
|
input wire clk,
|
|
input wire reset,
|
|
|
|
// Inputs
|
|
VX_alu_req_if alu_req_if,
|
|
|
|
// Outputs
|
|
VX_exu_to_cmt_if alu_commit_if
|
|
);
|
|
reg [`NUM_THREADS-1:0][31:0] alu_result;
|
|
|
|
wire [`NUM_THREADS-1:0][31:0] addsub_result;
|
|
wire [`NUM_THREADS-1:0] less_result;
|
|
wire [`NUM_THREADS-1:0][31:0] shift_result;
|
|
reg [`NUM_THREADS-1:0][31:0] misc_result;
|
|
|
|
wire [`ALU_BITS-1:0] alu_op = `ALU_OP(alu_req_if.op);
|
|
wire [`NUM_THREADS-1:0][31:0] alu_in1 = alu_req_if.rs1_data;
|
|
wire [`NUM_THREADS-1:0][31:0] alu_in2 = alu_req_if.rs2_data;
|
|
|
|
wire [`NUM_THREADS-1:0][31:0] alu_in1_PC = alu_req_if.rs1_is_PC ? {`NUM_THREADS{alu_req_if.curr_PC}} : alu_in1;
|
|
wire [`NUM_THREADS-1:0][31:0] alu_in2_imm = alu_req_if.rs2_is_imm ? {`NUM_THREADS{alu_req_if.imm}} : alu_in2;
|
|
|
|
wire negate_add = (alu_op == `ALU_SUB);
|
|
wire signed_less = (alu_op == `ALU_SLT);
|
|
wire signed_shift = (alu_op == `ALU_SRA);
|
|
|
|
for (genvar i = 0; i < `NUM_THREADS; i++) begin
|
|
wire [32:0] addsub_in1 = {alu_in1_PC[i], 1'b1};
|
|
wire [32:0] addsub_in2 = {alu_in2_imm[i], 1'b0} ^ {33{negate_add}};
|
|
`IGNORE_WARNINGS_BEGIN
|
|
wire [32:0] addsub_addd = addsub_in1 + addsub_in2;
|
|
`IGNORE_WARNINGS_END
|
|
assign addsub_result[i] = addsub_addd[32:1];
|
|
end
|
|
|
|
for (genvar i = 0; i < `NUM_THREADS; i++) begin
|
|
wire [32:0] less_in1 = {signed_less & alu_in1[i][31], alu_in1[i]};
|
|
wire [32:0] less_in2 = {signed_less & alu_in2_imm[i][31], alu_in2_imm[i]};
|
|
assign less_result[i] = $signed(less_in1) < $signed(less_in2);
|
|
end
|
|
|
|
for (genvar i = 0; i < `NUM_THREADS; i++) begin
|
|
wire [32:0] shift_in1 = {signed_shift & alu_in1[i][31], alu_in1[i]};
|
|
`IGNORE_WARNINGS_BEGIN
|
|
wire [32:0] shift_value = $signed(shift_in1) >>> alu_in2_imm[i][4:0];
|
|
`IGNORE_WARNINGS_END
|
|
assign shift_result[i] = shift_value[31:0];
|
|
end
|
|
|
|
for (genvar i = 0; i < `NUM_THREADS; i++) begin
|
|
always @(*) begin
|
|
case (alu_op)
|
|
`ALU_AND: misc_result[i] = alu_in1[i] & alu_in2_imm[i];
|
|
`ALU_OR: misc_result[i] = alu_in1[i] | alu_in2_imm[i];
|
|
`ALU_XOR: misc_result[i] = alu_in1[i] ^ alu_in2_imm[i];
|
|
//`ALU_SLL,
|
|
default: misc_result[i] = alu_in1[i] << alu_in2_imm[i][4:0];
|
|
endcase
|
|
end
|
|
end
|
|
|
|
for (genvar i = 0; i < `NUM_THREADS; i++) begin
|
|
always @(*) begin
|
|
case (`ALU_OP_CLASS(alu_op))
|
|
0: alu_result[i] = addsub_result[i];
|
|
1: alu_result[i] = {31'b0, less_result[i]};
|
|
2: alu_result[i] = shift_result[i];
|
|
default: alu_result[i] = misc_result[i];
|
|
endcase
|
|
end
|
|
end
|
|
|
|
VX_generic_register #(
|
|
.N(1 + `ISTAG_BITS + (`NUM_THREADS * 32))
|
|
) alu_reg (
|
|
.clk (clk),
|
|
.reset (reset),
|
|
.stall (0),
|
|
.flush (0),
|
|
.in ({alu_req_if.valid, alu_req_if.issue_tag, alu_result}),
|
|
.out ({alu_commit_if.valid, alu_commit_if.issue_tag, alu_commit_if.data})
|
|
);
|
|
|
|
assign alu_req_if.ready = 1'b1;
|
|
|
|
endmodule |