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

📄 fp_int_to_float.v

📁 nios里面用自定义指令集来实现三角函数
💻 V
字号:
//Legal Notice: (C)2006 Altera Corporation. All rights reserved.  Your
//use of Altera Corporation's design tools, logic functions and other
//software and tools, and its AMPP partner logic functions, and any
//output files any of the foregoing (including device programming or
//simulation files), and any associated documentation or information are
//expressly subject to the terms and conditions of the Altera Program
//License Subscription Agreement or other applicable license agreement,
//including, without limitation, that your use is for the sole purpose
//of programming logic devices manufactured by Altera and sold by Altera
//or its authorized distributors.  Please refer to the applicable
//agreement for further details.

// synthesis translate_off
`timescale 1ns / 1ps
// synthesis translate_on

// turn off superfluous verilog processor warnings 
// altera message_level Level1 
// altera message_off 10034 10035 10036 10037 10230 10240 10030 

module fp_int_to_float(
	reset,
	clk,
	clk_en,
	input_data,
	unsigned_operation,  // input_unsigned 0 for signed int, 1 for unsigned int
	output_data
);


	/* floating point unit paramterization, base latency is 1, setting each below to true adds 1 to the latency */
	parameter ENABLE_INPUT_PIPELINING = "false";
	parameter ENABLE_OUTPUT_PIPELINING = "false";
	parameter ENABLE_INTERNAL_PIPELINING = "false";
	parameter DATA_WIDTH = 32;   // maximum of 64
	parameter EXPONENT_WIDTH = 8;  // use 11 for double precision
	parameter MANTISSA_WIDTH = 23;  // use 52 for double precision
	localparam BIAS_FACTOR = {(EXPONENT_WIDTH-1){1'b1}};  // 127 for SP, 1023 for DP
	localparam SHIFT_WIDTH = 64 + 1 + MANTISSA_WIDTH;  // 64 (treat input as 64 bit data) + implied 1 + MANTISSA_WIDTH
	localparam ROUNDING_WIDTH = (DATA_WIDTH >= (MANTISSA_WIDTH + 1))? (DATA_WIDTH - (MANTISSA_WIDTH + 1)) : 0;  // need to keep the bits that shift out of the mantissa, if mantissa is larger no rounding is necessary

	input reset;
	input clk;
	input clk_en;
	input [DATA_WIDTH-1:0] input_data;
	input unsigned_operation;
	output [EXPONENT_WIDTH + MANTISSA_WIDTH:0] output_data;
	wire [EXPONENT_WIDTH + MANTISSA_WIDTH:0] output_data; 
	

	/* input data pipelining */
	reg [DATA_WIDTH-1:0] input_data_d1;
	wire [DATA_WIDTH-1:0] input_integer;
	reg unsigned_operation_d1;
	wire input_unsigned;

	/* output data pipelining */
	wire [EXPONENT_WIDTH + MANTISSA_WIDTH:0] temp_output_data;
	reg [EXPONENT_WIDTH + MANTISSA_WIDTH:0] temp_output_data_d1;
	
	
	
	/* treat all inputs as 64 bit data */
	wire [63:0] sign_extended_input;
	wire [63:0] absolute_input;
	reg [63:0] absolute_input_d1;
	

	wire [SHIFT_WIDTH-1 + ROUNDING_WIDTH:0] stage_A; // prime the inputs into the shifting logic
	wire [SHIFT_WIDTH-1 + ROUNDING_WIDTH:0] stage_B;  // holds the value after the first shift
	wire [SHIFT_WIDTH-1 + ROUNDING_WIDTH:0] stage_C;  // holds the value after the final shift
	reg [SHIFT_WIDTH-1 + ROUNDING_WIDTH:0] stage_C_d1;
	wire [5:0] leading_zeros;  // how many zeros starting from the left of the long long
	reg [5:0] leading_zeros_d1;
	wire [6:0] shift_distance;
	wire [EXPONENT_WIDTH-1:0] biased_exp;  // holds the biased exponential
	reg [EXPONENT_WIDTH-1:0] biased_exp_d1;
	wire [EXPONENT_WIDTH-1:0] final_biased_exp;  // holds the final biased exponential (rounding can cause this to increase by 1)
	wire [MANTISSA_WIDTH-1:0] final_mantissa;  // holds the final value of the mantissa after rounding
	reg sign_bit;
	reg sign_bit_d1;
	reg input_unsigned_d1;
	reg input_unsigned_d2;

	/* these will be used to control the priority encoder logic (that finds the number
	   of leading zeros in the unsigned input */
	wire [6:0] result [7:0];  // the values for result range between 0-63 (one per first stage mux)
	wire [8:0] is_Zero; // if all the inputs into the first stage mux are zero this will be high (the 9th one is the second stage)
	reg is_Zero_d1; // sync this so that it lines up with leading_zeros_d1
	reg is_Zero_d2;
	wire enable_rounding;  // will be using round to nearest



	always @(posedge clk or posedge reset)
	begin
		if(reset == 1)
		begin
			input_data_d1 <= 0;
			unsigned_operation_d1 <= 0;
		end
		else
		begin
			if(clk_en == 1)
			begin
				input_data_d1 <= input_data;
				unsigned_operation_d1 <= unsigned_operation;
			end
		end
	end

	// this generate statement will optimize away input registers depending on ENABLE_INPUT_PIPELINING
	generate
	if(ENABLE_INPUT_PIPELINING == "true")
	begin
		assign input_integer = input_data_d1;
		assign input_unsigned = unsigned_operation_d1;
	end
	else
	begin
		assign input_integer = input_data;
		assign input_unsigned = unsigned_operation;
	end
	endgenerate



	/* sign extend input to a 64 bit value and create an unsigned copy */
	assign sign_extended_input = (input_unsigned == 1)? {{(64-DATA_WIDTH){1'b0}} , input_integer} :  // unsigned data so fill upper bits with 0
											{{(64-DATA_WIDTH){input_integer[DATA_WIDTH-1]}} , input_integer};  // signed data so fill upper bits with the input sign bit
	assign absolute_input = ((input_unsigned == 0) && (sign_extended_input[63] == 1))? ((~sign_extended_input) + 1) : sign_extended_input;
	

	/* internal pipeling registers */
	always @(posedge clk or posedge reset)
	begin
		if(reset == 1)
		begin
			sign_bit <= 0;
			sign_bit_d1 <= 0;
			input_unsigned_d1 <= 0;
			input_unsigned_d2 <= 0;
			absolute_input_d1 <= 0;
			stage_C_d1 <= 0;
			biased_exp_d1 <= 0;
		end
		else
		begin
			if(clk_en == 1)
			begin
				sign_bit <= input_integer[DATA_WIDTH-1];
				sign_bit_d1 <= sign_bit;
				input_unsigned_d1 <= input_unsigned;
				input_unsigned_d2 <= input_unsigned_d1;
				absolute_input_d1 <= absolute_input;
				stage_C_d1 <= stage_C;
				biased_exp_d1 <= biased_exp;
			end
		end
	end

	/* priority encoding to find the leading zero.  The input is broken into eight pieces (of 8 bits)
	   and the leading zero is found in each.  The "is_Zero" bit from each is used for the final
	   assignment of leading_zeros based on a one hot priority encoding (parallel implementation).
	   Think of this as a replacement of a 64 input (7 bit inputs) mux into two stages of mux logic.
	*/
	eight_one_hot first_mux
	( .select(absolute_input[63:56]), .result(result[0]), .is_Zero(is_Zero[0]));
	defparam first_mux.START_VALUE = 0;

	eight_one_hot second_mux
	( .select(absolute_input[55:48]), .result(result[1]), .is_Zero(is_Zero[1]));
	defparam second_mux.START_VALUE = 8;

	eight_one_hot third_mux
	( .select(absolute_input[47:40]), .result(result[2]), .is_Zero(is_Zero[2]));
	defparam third_mux.START_VALUE = 16;

	eight_one_hot fourth_mux
	( .select(absolute_input[39:32]), .result(result[3]), .is_Zero(is_Zero[3]));
	defparam fourth_mux.START_VALUE = 24;
	
	eight_one_hot fifth_mux
	( .select(absolute_input[31:24]), .result(result[4]), .is_Zero(is_Zero[4]));
	defparam fifth_mux.START_VALUE = 32;
	
	eight_one_hot sixth_mux
	( .select(absolute_input[23:16]), .result(result[5]), .is_Zero(is_Zero[5]));
	defparam sixth_mux.START_VALUE = 40;
	
	eight_one_hot seventh_mux
	( .select(absolute_input[15:8]), .result(result[6]), .is_Zero(is_Zero[6]));
	defparam seventh_mux.START_VALUE = 48;
	
	eight_one_hot eighth_mux
	( .select(absolute_input[7:0]), .result(result[7]), .is_Zero(is_Zero[7]));
	defparam eighth_mux.START_VALUE = 56;
	
	/* stick the first stage back together (9th mux using the first eight as inputs).
	   Remember if is_Zero is 1 then the leading one isn't contained in that particular
	   group of eight.
	*/
	assign leading_zeros = (is_Zero[0] == 0) ? result[0] :
							(is_Zero[1] == 0) ? result[1] :
							(is_Zero[2] == 0) ? result[2] :
							(is_Zero[3] == 0) ? result[3] :
							(is_Zero[4] == 0) ? result[4] :
							(is_Zero[5] == 0) ? result[5] :
							(is_Zero[6] == 0) ? result[6] : result[7];
							
	assign is_Zero[8] = (is_Zero[7:0] == 8'b11111111)? 1 : 0;  // this is one if absolute_input was zero

	
	/* register the priority encoder results */						
	always @(posedge clk or posedge reset)
	begin
		if(reset == 1)
		begin
			leading_zeros_d1 <= 0;
			is_Zero_d1 <= 0;
			is_Zero_d2 <= 0;
		end
		else
		begin
			if(clk_en == 1)
			begin
				leading_zeros_d1 <= leading_zeros;
				is_Zero_d1 <= is_Zero[8];
				is_Zero_d2 <= is_Zero_d1;
			end
		end
	end


	
	/* a.k.a. furthest 1 from the right */
	assign shift_distance = 64 - leading_zeros_d1;

	
	/* the exponent is one less than the shift distance */
	assign biased_exp = shift_distance - 1 + BIAS_FACTOR;
	
	/* now that the shift distance is know time to barrelshift the long long.
	   The format is absoulte_input:0:mantissa.  The zero in the middle is the placeholder
	   for the implied '1' mantissa bit (i.e. the leading one) */
	assign stage_A = {{absolute_input_d1, 1'b0}, {(MANTISSA_WIDTH+ROUNDING_WIDTH){1'b0}}};
	
	assign stage_B = (shift_distance[5:3] == 0)? stage_A:
					(shift_distance[5:3] == 1)? stage_A >> 8:
					(shift_distance[5:3] == 2)? stage_A >> 16:
					(shift_distance[5:3] == 3)? stage_A >> 24:
					(shift_distance[5:3] == 4)? stage_A >> 32:
					(shift_distance[5:3] == 5)? stage_A >> 40:
					(shift_distance[5:3] == 6)? stage_A >> 48: stage_A >> 56;
					
	assign stage_C = (shift_distance[2:0] == 0)? stage_B:
					(shift_distance[2:0] == 1)? stage_B >> 1:
					(shift_distance[2:0] == 2)? stage_B >> 2:
					(shift_distance[2:0] == 3)? stage_B >> 3:
					(shift_distance[2:0] == 4)? stage_B >> 4:
					(shift_distance[2:0] == 5)? stage_B >> 5:
					(shift_distance[2:0] == 6)? stage_B >> 6: stage_B >> 7;
					
	generate
	if(ROUNDING_WIDTH > 0)
	begin
		if(ENABLE_INTERNAL_PIPELINING == "true")
		begin
			assign enable_rounding = (stage_C_d1[ROUNDING_WIDTH-1:0] > (1 << (ROUNDING_WIDTH-1)))? 1:  // round up regardless
									((stage_C_d1[ROUNDING_WIDTH-1:0] == (1 << (ROUNDING_WIDTH-1))) & (stage_C_d1[ROUNDING_WIDTH] == 1))? 1: 0; // it's a tie but we are rounding towards even, otherwise don't round
		end
		else
		begin
			assign enable_rounding = (stage_C[ROUNDING_WIDTH-1:0] > (1 << (ROUNDING_WIDTH-1)))? 1:  // round up regardless
									((stage_C[ROUNDING_WIDTH-1:0] == (1 << (ROUNDING_WIDTH-1))) & (stage_C[ROUNDING_WIDTH] == 1))? 1: 0; // it's a tie but we are rounding towards even, otherwise don't round
		end
	end
	else
	begin
		assign enable_rounding = 0;  // mantissa is large enough to hold input
	end
	endgenerate


	generate
	if(ENABLE_INTERNAL_PIPELINING == "true")
	begin

		assign final_mantissa = (enable_rounding == 1)? (stage_C_d1[MANTISSA_WIDTH+ROUNDING_WIDTH-1:ROUNDING_WIDTH] + 1) : stage_C_d1[MANTISSA_WIDTH+ROUNDING_WIDTH-1:ROUNDING_WIDTH];  // the bits we lost rounded us up
		assign final_biased_exp = ((enable_rounding == 1) & (stage_C_d1[MANTISSA_WIDTH+ROUNDING_WIDTH-1:ROUNDING_WIDTH] == {MANTISSA_WIDTH{1'b1}}))? (biased_exp_d1 + 1) : biased_exp_d1;  // rounding up caused the mantissa to roll over and our implied 1 just moved up a digit

		assign temp_output_data = (is_Zero_d2 == 1)? 0 : /* special case where zero was passed to this hardware */
						(input_unsigned_d2 == 0) ? {{sign_bit_d1, final_biased_exp}, final_mantissa} : /* signed case */
						{{1'b0, final_biased_exp},final_mantissa}; /* unsigned case */

	end
	else
	begin
		assign final_mantissa = (enable_rounding == 1)? (stage_C[MANTISSA_WIDTH+ROUNDING_WIDTH-1:ROUNDING_WIDTH] + 1) : stage_C[MANTISSA_WIDTH+ROUNDING_WIDTH-1:ROUNDING_WIDTH];  // the bits we lost rounded us up
		assign final_biased_exp = ((enable_rounding == 1) & (stage_C[MANTISSA_WIDTH+ROUNDING_WIDTH-1:ROUNDING_WIDTH] == {MANTISSA_WIDTH{1'b1}}))? (biased_exp + 1) : biased_exp;  // rounding up caused the mantissa to roll over and our implied 1 just moved up a digit


		assign temp_output_data = (is_Zero_d1 == 1)? 0 : /* special case where zero was passed to this hardware */
						(input_unsigned_d1 == 0) ? {{sign_bit, final_biased_exp}, final_mantissa} : /* signed case */
						{{1'b0, final_biased_exp},final_mantissa}; /* unsigned case */
	end
	endgenerate




	always @(posedge clk or posedge reset)
	begin
		if(reset == 1)
		begin
			temp_output_data_d1 <= 0;
		end
		else
		begin
			if(clk_en == 1)
			begin
				temp_output_data_d1 <= temp_output_data;
			end
		end
	end


	// this will be synthesized away the output registers depending on ENABLE_OUTPUT_PIPELINING
	generate
	if(ENABLE_OUTPUT_PIPELINING == "true")
	begin
		assign output_data = temp_output_data_d1;
	end
	else
	begin
		assign output_data = temp_output_data;
	end
	endgenerate

endmodule


/* this mux finds the leading zero amungst eight inputs.  If all zeros are feed into
   this block are zero the result is START_VALUE+7 and is_Zero will be one.  The 2nd stage mux
   that combines these blocks together will ignore the value START_VALUE+7 if is_Zero
   is one */
module eight_one_hot (
	select,
	result,
	is_Zero);
	
	parameter START_VALUE = 0;
	
	input [7:0] select;
	wire [5:0] result;
	output [5:0] result;
	wire is_Zero;
	output is_Zero;
	
	assign result = (select[7] == 1)? START_VALUE :
					(select[6] == 1)? START_VALUE + 1 :
					(select[5] == 1)? START_VALUE + 2 :
					(select[4] == 1)? START_VALUE + 3 :
					(select[3] == 1)? START_VALUE + 4 :
					(select[2] == 1)? START_VALUE + 5 :
					(select[1] == 1)? START_VALUE + 6 : START_VALUE + 7;
	
	assign is_Zero = (select == 8'b00000000)? 1 : 0;
endmodule

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -