Add multiplication encoding

This commit is contained in:
Florian Zaruba 2017-07-26 17:48:14 +02:00
parent 6560ef9520
commit ed3a4ea13b
2 changed files with 94 additions and 79 deletions

View file

@ -222,22 +222,31 @@ module decoder (
// Reg-Reg Operations
// --------------------------
OPCODE_OP: begin
instruction_o.fu = ALU;
instruction_o.fu = (instr.rtype.funct7 == 7'b000_0001) ? MULT : ALU;
instruction_o.rs1 = instr.rtype.rs1;
instruction_o.rs2 = instr.rtype.rs2;
instruction_o.rd = instr.rtype.rd;
unique case ({instr.rtype.funct7, instr.rtype.funct3})
{6'b00_0000, 3'b000}: instruction_o.op = ADD; // Add
{6'b10_0000, 3'b000}: instruction_o.op = SUB; // Sub
{6'b00_0000, 3'b010}: instruction_o.op = SLTS; // Set Lower Than
{6'b00_0000, 3'b011}: instruction_o.op = SLTU; // Set Lower Than Unsigned
{6'b00_0000, 3'b100}: instruction_o.op = XORL; // Xor
{6'b00_0000, 3'b110}: instruction_o.op = ORL; // Or
{6'b00_0000, 3'b111}: instruction_o.op = ANDL; // And
{6'b00_0000, 3'b001}: instruction_o.op = SLL; // Shift Left Logical
{6'b00_0000, 3'b101}: instruction_o.op = SRL; // Shift Right Logical
{6'b10_0000, 3'b101}: instruction_o.op = SRA; // Shift Right Arithmetic
{7'b000_0000, 3'b000}: instruction_o.op = ADD; // Add
{7'b010_0000, 3'b000}: instruction_o.op = SUB; // Sub
{7'b000_0000, 3'b010}: instruction_o.op = SLTS; // Set Lower Than
{7'b000_0000, 3'b011}: instruction_o.op = SLTU; // Set Lower Than Unsigned
{7'b000_0000, 3'b100}: instruction_o.op = XORL; // Xor
{7'b000_0000, 3'b110}: instruction_o.op = ORL; // Or
{7'b000_0000, 3'b111}: instruction_o.op = ANDL; // And
{7'b000_0000, 3'b001}: instruction_o.op = SLL; // Shift Left Logical
{7'b000_0000, 3'b101}: instruction_o.op = SRL; // Shift Right Logical
{7'b010_0000, 3'b101}: instruction_o.op = SRA; // Shift Right Arithmetic
// Multiplications
{7'b000_0001, 3'b000}: instruction_o.op = MUL;
{7'b000_0001, 3'b001}: instruction_o.op = MULH;
{7'b000_0001, 3'b010}: instruction_o.op = MULHSU;
{7'b000_0001, 3'b011}: instruction_o.op = MULHU;
{7'b000_0001, 3'b100}: instruction_o.op = DIV;
{7'b000_0001, 3'b101}: instruction_o.op = DIVU;
{7'b000_0001, 3'b110}: instruction_o.op = REM;
{7'b000_0001, 3'b111}: instruction_o.op = REMU;
default: begin
illegal_instr = 1'b1;
end
@ -256,12 +265,16 @@ module decoder (
if (~instr.instr[28])
unique case ({instr.rtype.funct7, instr.rtype.funct3})
{6'b00_0000, 3'b000}: instruction_o.op = ADDW; // addw
{6'b10_0000, 3'b000}: instruction_o.op = SUBW; // subw
{6'b00_0000, 3'b001}: instruction_o.op = SLLW; // sllw
{6'b00_0000, 3'b101}: instruction_o.op = SRLW; // srlw
{6'b10_0000, 3'b101}: instruction_o.op = SRAW; // sraw
// multiplications
{7'b000_0000, 3'b000}: instruction_o.op = ADDW; // addw
{7'b010_0000, 3'b000}: instruction_o.op = SUBW; // subw
{7'b000_0000, 3'b001}: instruction_o.op = SLLW; // sllw
{7'b000_0000, 3'b101}: instruction_o.op = SRLW; // srlw
{7'b010_0000, 3'b101}: instruction_o.op = SRAW; // sraw
// Multiplications
{7'b000_0001, 3'b000}: instruction_o.op = MULW;
{7'b000_0001, 3'b100}: instruction_o.op = DIVW;
{7'b000_0001, 3'b110}: instruction_o.op = REMW;
{7'b000_0001, 3'b111}: instruction_o.op = REMUW;
default: illegal_instr = 1'b1;
endcase

View file

@ -36,77 +36,79 @@ module mult
output logic mult_ready_o,
output logic [TRANS_ID_BITS-1:0] mult_trans_id_o
);
// MUL and MULH is a two cycle instructions
logic signed [63:0] result_mult;
logic signed [63:0] result_multh;
enum logic {FIRST_CYCLE, SECOND_CYCLE} multCS, multNS;
logic [TRANS_ID_BITS-1:0] mult_trans_q, mult_trans_n;
// // MUL and MULH is a two cycle instructions
// logic signed [63:0] result_mult;
// logic signed [63:0] result_multh;
// enum logic {FIRST_CYCLE, SECOND_CYCLE} multCS, multNS;
// logic [TRANS_ID_BITS-1:0] mult_trans_q, mult_trans_n;
assign mult_trans_id_o = mult_trans_q;
assign result_o = is_low_part_i ? result_mult : result_multh;
// assign mult_trans_id_o = mult_trans_q;
// assign result_o = is_low_part_i ? result_mult : result_multh;
mult_datapath
mult_dp
(
.operand_a_i (operand_a_i ),
.operand_b_i (operand_b_i ),
.sign_a_i (sign_a_i ),
.sign_b_i (sign_b_i ),
.result_low_o (result_mult ),
.result_high_o (result_multh )
);
// mult_datapath
// mult_dp
// (
// .operand_a_i (operand_a_i ),
// .operand_b_i (operand_b_i ),
// .sign_a_i (sign_a_i ),
// .sign_b_i (sign_b_i ),
// .result_low_o (result_mult ),
// .result_high_o (result_multh )
// );
always_comb begin
mult_valid_o = 1'b0;
mult_ready_o = 1'b0;
multNS = multCS;
mult_trans_n = mult_trans_q;
unique case (multCS)
FIRST_CYCLE: begin
mult_valid_o = 1'b0;
mult_ready_o = 1'b0;
multNS = mult_valid_i ? SECOND_CYCLE : multCS;
end
SECOND_CYCLE: begin
multNS = FIRST_CYCLE;
mult_valid_o = 1'b1;
mult_ready_o = 1'b1;
end
default:;
endcase
end
// always_comb begin
// mult_valid_o = 1'b0;
// mult_ready_o = 1'b0;
// multNS = multCS;
// mult_trans_n = mult_trans_q;
// unique case (multCS)
// FIRST_CYCLE: begin
// mult_valid_o = 1'b0;
// mult_ready_o = 1'b0;
// multNS = mult_valid_i ? SECOND_CYCLE : multCS;
// end
// SECOND_CYCLE: begin
// multNS = FIRST_CYCLE;
// mult_valid_o = 1'b1;
// mult_ready_o = 1'b1;
// end
// default:;
// endcase
// end
always_ff @(posedge clk_i or negedge rst_ni) begin
if(~rst_ni) begin
multCS <= FIRST_CYCLE;
end else begin
multCS <= multNS;
mult_trans_n <= mult_trans_q;
end
end
// always_ff @(posedge clk_i or negedge rst_ni) begin
// if(~rst_ni) begin
// multCS <= FIRST_CYCLE;
// end else begin
// multCS <= multNS;
// mult_trans_n <= mult_trans_q;
// end
// end
// Check if we need sign extension
endmodule
module mult_datapath
(
input logic [63:0] operand_a_i,
input logic [63:0] operand_b_i,
input logic sign_a_i,
input logic sign_b_i,
output logic [63:0] result_low_o,
output logic [63:0] result_high_o
);
// module mult_datapath
// (
// input logic [63:0] operand_a_i,
// input logic [63:0] operand_b_i,
// input logic sign_a_i,
// input logic sign_b_i,
// output logic [63:0] result_low_o,
// output logic [63:0] result_high_o
// );
logic signed [129:0] mult_result;
logic signed [64:0] operand_a_ext;
logic signed [64:0] operand_b_ext;
// logic signed [129:0] mult_result;
// logic signed [64:0] operand_a_ext;
// logic signed [64:0] operand_b_ext;
assign operand_a_ext = $signed({sign_a_i & operand_a_i[63], operand_a_i});
assign operand_b_ext = $signed({sign_b_i & operand_b_i[63], operand_b_i});
// assign operand_a_ext = $signed({sign_a_i & operand_a_i[63], operand_a_i});
// assign operand_b_ext = $signed({sign_b_i & operand_b_i[63], operand_b_i});
assign mult_result = operand_a_ext * operand_b_ext;
// assign mult_result = operand_a_ext * operand_b_ext;
assign result_low_o = $signed(mult_result[ 63: 0]);
assign result_high_o = $signed(mult_result[127:64]);
// assign result_low_o = $signed(mult_result[ 63: 0]);
// assign result_high_o = $signed(mult_result[127:64]);
endmodule
// endmodule