blob: e846a46b0d6d3742f3534f3880c256097eacec49 [file] [log] [blame]
module riscv_fpu (
clk,
rst_n,
operand_a_i,
operand_b_i,
rounding_mode_i,
operator_i,
enable_i,
stall_i,
result_o,
fpu_ready_o,
result_valid_o
);
parameter C_RM = 2;
parameter C_RM_NEAREST = 2'h0;
parameter C_RM_TRUNC = 2'h1;
parameter C_RM_PLUSINF = 2'h2;
parameter C_RM_MINUSINF = 2'h3;
parameter C_PC = 5;
parameter C_OP = 32;
parameter C_MANT = 23;
parameter C_EXP = 8;
parameter C_BIAS = 127;
parameter C_HALF_BIAS = 63;
parameter C_LEADONE_WIDTH = 7;
parameter C_MANT_PRENORM = C_MANT+1;
parameter C_EXP_ZERO = 8'h00;
parameter C_EXP_ONE = 8'h01;
parameter C_EXP_INF = 8'hff;
parameter C_MANT_ZERO = 23'h0;
parameter C_MANT_NAN = 23'h400000;
parameter C_CMD = 4;
parameter C_FPU_ADD_CMD = 4'h0;
parameter C_FPU_SUB_CMD = 4'h1;
parameter C_FPU_MUL_CMD = 4'h2;
parameter C_FPU_DIV_CMD = 4'h3;
parameter C_FPU_I2F_CMD = 4'h4;
parameter C_FPU_F2I_CMD = 4'h5;
parameter C_FPU_SQRT_CMD = 4'h6;
parameter C_FPU_NOP_CMD = 4'h7;
parameter C_FPU_FMADD_CMD = 4'h8;
parameter C_FPU_FMSUB_CMD = 4'h9;
parameter C_FPU_FNMADD_CMD = 4'hA;
parameter C_FPU_FNMSUB_CMD = 4'hB;
parameter C_RM_NEAREST_MAX = 3'h4;
parameter C_EXP_PRENORM = C_EXP+2;
parameter C_MANT_ADDIN = C_MANT+4;
parameter C_MANT_ADDOUT = C_MANT+5;
parameter C_MANT_SHIFTIN = C_MANT+3;
parameter C_MANT_SHIFTED = C_MANT+4;
parameter C_MANT_INT = C_OP-1;
parameter C_INF = 32'h7fffffff;
parameter C_MINF = 32'h80000000;
parameter C_EXP_SHIFT = C_EXP_PRENORM;
parameter C_SHIFT_BIAS = 9'd127;
parameter C_UNKNOWN = 8'd157;
parameter C_PADMANT = 16'b0;
parameter C_MANT_NoHB_ZERO = 23'h0;
parameter C_MANT_PRENORM_IND = 6;
parameter F_QNAN =32'h7FC00000;
parameter C_FFLAG = 5;
input wire clk;
input wire rst_n;
input wire [C_OP - 1:0] operand_a_i;
input wire [C_OP - 1:0] operand_b_i;
input wire [C_RM - 1:0] rounding_mode_i;
input wire [C_CMD - 1:0] operator_i;
input wire enable_i;
input wire stall_i;
output wire [C_OP - 1:0] result_o;
output reg fpu_ready_o;
output wire result_valid_o;
localparam CYCLES = 2;
wire [C_OP - 1:0] operand_a_q;
wire [C_OP - 1:0] operand_b_q;
wire [C_RM - 1:0] rounding_mode_q;
wire [C_CMD - 1:0] operator_q;
reg [1:0] valid_count_q;
reg [1:0] valid_count_n;
assign result_valid_o = (valid_count_q == 1 ? 1'b1 : 1'b0);
always @(*) begin
valid_count_n = valid_count_q;
fpu_ready_o = 1'b1;
if (enable_i) begin
valid_count_n = valid_count_q + 1;
fpu_ready_o = 1'b0;
if (valid_count_q == 1) begin
fpu_ready_o = 1'b1;
valid_count_n = 2'd0;
end
end
end
always @(posedge clk or negedge rst_n)
if (~rst_n)
valid_count_q <= 1'b0;
else if (enable_i && ~stall_i)
valid_count_q <= valid_count_n;
fpu_core fpcore(
.Clk_CI(clk),
.Rst_RBI(rst_n),
.Enable_SI(enable_i),
.Operand_a_DI(operand_a_i),
.Operand_b_DI(operand_b_i),
.RM_SI(rounding_mode_i),
.OP_SI(operator_i),
.Stall_SI(stall_i),
.Result_DO(result_o),
.OF_SO(),
.UF_SO(),
.Zero_SO(),
.IX_SO(),
.IV_SO(),
.Inf_SO()
);
endmodule