📄 fp_float_to_int.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_float_to_int (
reset,
clk,
clk_en,
operandA,
result
);
// default to single precision and no pipelining, latency is 0, 1, 2 depending on the number of "true" set below
parameter ENABLE_INPUT_PIPELINING = "false";
parameter ENABLE_OUTPUT_PIPELINING = "false";
parameter ENABLE_INTERNAL_PIPELINING = "false"; // recommend setting to true on Stratix II (smaller and faster)
parameter MANTISSA_WIDTH = 23; // 23 for single precision, 52 for double precision
parameter EXPONENT_WIDTH = 8; // 8 for single precision, 11 for double precision
localparam DATA_WIDTH_FLOAT = MANTISSA_WIDTH + EXPONENT_WIDTH + 1; // 32 for single precision, 64 for double precision
localparam DATA_WIDTH_INT = 32; // fixed since it's an int as an output
localparam BIAS_FACTOR = {(EXPONENT_WIDTH-1){1'b1}};
localparam SHIFT_WIDTH = DATA_WIDTH_INT + MANTISSA_WIDTH;
// inputs A and B will be either registered or non-registered operandA and operandB
input [DATA_WIDTH_FLOAT-1:0] operandA;
reg [DATA_WIDTH_FLOAT-1:0] operandA_d1;
wire [DATA_WIDTH_FLOAT-1:0] A;
input reset;
input clk;
input clk_en;
/* float/double to int/unsigned int logic */
wire [SHIFT_WIDTH-1:0] stage_A; // prime the inputs into the shifting logic
wire [SHIFT_WIDTH-1:0] stage_B; // holds the value after the first shift
wire [SHIFT_WIDTH-1:0] stage_C; // holds the value after the final shift
wire [SHIFT_WIDTH-1:0] temp_stage_C;
reg [SHIFT_WIDTH-1:0] temp_stage_C_d1;
wire [SHIFT_WIDTH-1:0] stage_C_twos_compliment; // holds the two's complement value of stage_C
wire [EXPONENT_WIDTH-1:0] biased_exp; // holds the biased exponential
reg [EXPONENT_WIDTH-1:0] temp_biased_exp;
reg [EXPONENT_WIDTH-1:0] biased_exp_d1;
wire [EXPONENT_WIDTH-1:0] unbiased_exp; // holds the exponential minus the bias factor
reg [EXPONENT_WIDTH-1:0] temp_unbiased_exp;
reg [EXPONENT_WIDTH-1:0] unbiased_exp_d1;
/* logic to create conditions for special cases
and the unsigned/signed modes */
wire sb; // sign bit
reg temp_sb;
reg sb_d1;
wire NaN; // decodes the input NaN condition
reg temp_NaN;
reg NaN_d1;
wire Inf; // decodes the input +/- infinity condition
reg temp_Inf;
reg Inf_d1;
wire Denormal; // decodes the input denormal condition (too small)
reg temp_Denormal;
reg Denormal_d1;
// output result will be either registered or non-register temp_result
output [DATA_WIDTH_INT-1:0] result;
wire [DATA_WIDTH_INT-1:0] result;
wire [DATA_WIDTH_INT-1:0] temp_result;
reg [DATA_WIDTH_INT-1:0] temp_result_d1;
always @ (posedge clk or posedge reset)
begin
if (reset)
begin
// this will be synthesized away if input pipelining is not enabled
operandA_d1 <= 0;
temp_sb <= 0;
temp_NaN <= 0;
temp_Inf <= 0;
temp_Denormal <= 0;
temp_biased_exp <= 0;
temp_unbiased_exp <= 0;
// this will be synthesized away if internal pipelining is not enabled
sb_d1 <= 0;
NaN_d1 <= 0;
Inf_d1 <= 0;
Denormal_d1 <= 0;
biased_exp_d1 <= 0;
unbiased_exp_d1 <= 0;
temp_stage_C_d1 <= 0;
end
else
begin
if (clk_en)
begin
// first register stage
operandA_d1 <= operandA;
temp_sb <= operandA[DATA_WIDTH_FLOAT-1];
temp_NaN <= (operandA[DATA_WIDTH_FLOAT-2:MANTISSA_WIDTH] == {EXPONENT_WIDTH{1'b1}}) & (operandA[MANTISSA_WIDTH-1:0] != 0);
temp_Inf <= (operandA[DATA_WIDTH_FLOAT-2:MANTISSA_WIDTH] == {EXPONENT_WIDTH{1'b1}}) & (operandA[MANTISSA_WIDTH-1:0] == 0);
temp_Denormal <= operandA[DATA_WIDTH_FLOAT-2:MANTISSA_WIDTH] == 0;
temp_biased_exp <= operandA[DATA_WIDTH_FLOAT-2:MANTISSA_WIDTH];
temp_unbiased_exp <= biased_exp - BIAS_FACTOR;
// internal register stage
sb_d1 <= sb;
NaN_d1 <= NaN;
Inf_d1 <= Inf;
Denormal_d1 <= Denormal;
biased_exp_d1 <= biased_exp;
unbiased_exp_d1 <= unbiased_exp;
temp_stage_C_d1 <= temp_stage_C;
end
end
end
// this generate statement will optimize away input registers depending on ENABLE_INPUT_PIPELINING
generate
if(ENABLE_INPUT_PIPELINING == "true")
begin
assign A = operandA_d1;
assign sb = temp_sb;
assign NaN = temp_NaN;
assign Inf = temp_Inf;
assign Denormal = temp_Denormal;
assign biased_exp = temp_biased_exp;
assign unbiased_exp = temp_unbiased_exp;
end
else
begin
assign A = operandA;
assign sb = operandA[DATA_WIDTH_FLOAT-1];
assign NaN = (operandA[DATA_WIDTH_FLOAT-2:MANTISSA_WIDTH] == {EXPONENT_WIDTH{1'b1}}) & (operandA[MANTISSA_WIDTH-1:0] != 0);
assign Inf = (operandA[DATA_WIDTH_FLOAT-2:MANTISSA_WIDTH] == {EXPONENT_WIDTH{1'b1}}) & (operandA[MANTISSA_WIDTH-1:0] == 0);
assign Denormal = operandA[DATA_WIDTH_FLOAT-2:MANTISSA_WIDTH] == 0;
assign biased_exp = operandA[DATA_WIDTH_FLOAT-2:MANTISSA_WIDTH];
assign unbiased_exp = biased_exp - BIAS_FACTOR;
end
endgenerate
/*************************************************************************************/
/* This is where the actual float --> int conversion takes place */
// 31 zeros, 1 one, mantissa (23 or 52 bits)
assign stage_A = {{{(DATA_WIDTH_INT-1){1'b0}}, 1'b1}, A[MANTISSA_WIDTH-1:0]};
// handle the shift distance portion that's a multiple of 8
assign stage_B = (unbiased_exp[4:3] == 2'b00)? stage_A:
(unbiased_exp[4:3] == 2'b01)? stage_A << 8 :
(unbiased_exp[4:3] == 2'b10)? stage_A << 16 : stage_A << 24;
// handle the remaining shift distance portion between 0 to 7
assign temp_stage_C = (unbiased_exp[2:0] == 3'b000)? stage_B:
(unbiased_exp[2:0] == 3'b001)? stage_B << 1 :
(unbiased_exp[2:0] == 3'b010)? stage_B << 2 :
(unbiased_exp[2:0] == 3'b011)? stage_B << 3 :
(unbiased_exp[2:0] == 3'b100)? stage_B << 4 :
(unbiased_exp[2:0] == 3'b101)? stage_B << 5 :
(unbiased_exp[2:0] == 3'b110)? stage_B << 6 : stage_B << 7;
assign stage_C_twos_compliment = (sb == 0)? stage_C[SHIFT_WIDTH-1:SHIFT_WIDTH-32] :
((~stage_C[SHIFT_WIDTH-1:SHIFT_WIDTH-32]) + 1); // convert to 2s compliment
/*************************************************************************************/
// will optimize away the internal registers depending on ENABLE_INTERNAL_PIPELINING
generate
if(ENABLE_INTERNAL_PIPELINING == "true")
begin
assign stage_C = temp_stage_C_d1;
assign temp_result = ((NaN_d1 == 1) | (Denormal_d1 == 1) | (biased_exp_d1 < BIAS_FACTOR))? 0 : // Zero and denormal are caught along with NaN and numbers with negative exponents (-1 < input < 1)
((Inf_d1 == 1) & (sb_d1 == 0))? 32'h7FFFFFFF : // +infinity saturates to maximum value
((Inf_d1 == 1) & (sb_d1 == 1))? 32'h80000000 : // -infinity saturates to minimum value
((biased_exp_d1 > (BIAS_FACTOR + 30)) & (sb_d1 == 0))? 32'h7FFFFFFF : // too large positive input saturates to maximum value
((biased_exp_d1 > (BIAS_FACTOR + 30)) & (sb_d1 == 1))? 32'h80000000 : // too large negative input saturates to maximum negative value
stage_C_twos_compliment; // we already know the answer is in the range [-2^30, 2^30 -1] so a 2's compliment answer is good enough for float-->unsigned int/int
end
else
begin
assign stage_C = temp_stage_C;
assign temp_result = ((NaN == 1) | (Denormal == 1) | (biased_exp < BIAS_FACTOR))? 0 : // Zero and denormal are caught along with NaN and numbers with negative exponents (-1 < input < 1)
((Inf == 1) & (sb == 0))? 32'h7FFFFFFF : // +infinity saturates to maximum value
((Inf == 1) & (sb == 1))? 32'h80000000 : // -infinity saturates to minimum value
((biased_exp > (BIAS_FACTOR + 30)) & (sb == 0))? 32'h7FFFFFFF : // too large positive input saturates to maximum value
((biased_exp > (BIAS_FACTOR + 30)) & (sb == 1))? 32'h80000000 : // too large negative input saturates to maximum negative value
stage_C_twos_compliment; // we already know the answer is in the range [-2^30, 2^30 -1] so a 2's compliment answer is good enough for float-->unsigned int/int
end
endgenerate
always @ (posedge clk or posedge reset)
begin
if (reset)
begin
temp_result_d1 <= 0;
end
else
begin
if (clk_en)
begin
temp_result_d1 <= temp_result;
end
end
end
// this will be synthesized away the output registers depending on ENABLE_OUTPUT_PIPELINING
generate
if(ENABLE_OUTPUT_PIPELINING == "true")
begin
assign result = temp_result_d1;
end
else
begin
assign result = temp_result;
end
endgenerate
endmodule
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -