📄 fp_double_to_single.v
字号:
module fp_double_to_single (
clk,
clk_en,
reset,
data_in,
data_out
);
parameter ENABLE_OUTPUT_PIPELINING = "true";
localparam EXPONENT_CONVERSION = 1023 - 127; // double precision are biased with 1023, single precision is biased by 127
localparam MANTISSA_SHIFT_DISTANCE = 52 - 23; // need to align the 23 bit mantissa (SP) to the upper bits of the 52 bit mantissa (DP)
localparam GUARD_BITS = 7; // this is 8 for double precion
input clk;
input clk_en;
input reset;
input [63:0] data_in;
wire [31:0] data_out;
output [31:0] data_out;
wire new_sign_bit;
wire [7:0] new_exponent;
wire [23 + GUARD_BITS - 1: 0] fraction; // this is the mantissa + guard bits
wire enable_rounding;
wire [22:0] new_mantissa;
wire [31:0] new_output;
wire input_is_NaN;
wire input_is_Inf;
wire input_too_big;
wire input_is_Denormal;
wire input_too_small;
// output pipeline signals
wire [31:0] temp_output;
reg [31:0] temp_output_d1;
// using the upper 23+7 = 30 bits of the mantissa from the double input mantissa. Any bits that we loose will determine if a '1' is orded into the guard bits
assign fraction = (data_in[21:0] != 0)? (data_in[51:22]) | 1 : data_in[51:22];
assign enable_rounding = ((fraction[7] == 1) & (fraction[6:0] == 7'b1000000)) | // it's a tie, only round up if the mantissa lsb is 1 (round to nearest)
(fraction[6:0] > 7'b1000000); // the guard bits are past the even point so round up regardless
assign new_sign_bit = data_in[63];
assign new_mantissa = (enable_rounding == 1)? fraction[29:7] + 1 : fraction[29:7];
assign new_exponent = ((enable_rounding == 1) & (new_mantissa == 0))? (data_in[62:52] - EXPONENT_CONVERSION + 1) : // we rounded up and the mantissa is 0 so it rolled (decimal place moved), must increment the exponent by 1
(data_in[62:52] - EXPONENT_CONVERSION);
assign new_output = {new_sign_bit, {new_exponent, new_mantissa}};
assign input_is_NaN = (data_in[62:52] == 12'b111111111111) & (data_in[51:0] != 0);
assign input_is_Inf = (data_in[62:52] == 12'b111111111111) & (data_in[51:0] == 0);
assign input_too_big = (data_in[62:52] >= (8'b11111111 + EXPONENT_CONVERSION)); // doesn't matter if it's really infinity (mantissa = 0), this is the largest exponential that fits in single precision format
assign input_is_Denormal = (data_in[62:52] == 0) & (data_in[51:0] != 0);
assign input_too_small = (data_in[62:52] < (8'b00000000 + EXPONENT_CONVERSION));
assign temp_output = ((input_is_Inf == 1) | (input_too_big == 1))? {new_sign_bit, 31'h7F800000} : // either the input is infinity or the single precision format will not hold the value that is too big
(input_is_NaN == 1)? {new_sign_bit, 31'h7FC00000} : // input is NaN so output is NaN (exponent maxed out, mantissa msb set)
((input_is_Denormal == 1) | (input_too_small == 1))? 0 : new_output; // the input is denormal or the single preicison format will not hold such a small value
always @ (posedge clk)
begin
if(reset == 1)
begin
temp_output_d1 <= 0;
end
else
begin
if(clk_en == 1)
begin
temp_output_d1 <= temp_output;
end
end
end
generate // when false the registered temp_ouptput will be optimized away
if(ENABLE_OUTPUT_PIPELINING == "true")
begin
assign data_out = temp_output_d1;
end
else
begin
assign data_out = temp_output;
end
endgenerate
endmodule
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -