⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fp_double_to_single.v

📁 nios里面用自定义指令集来实现三角函数
💻 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 + -