zoukankan      html  css  js  c++  java
  • FPGA浮点数定点数的处理

    http://blog.chinaaet.com/justlxy/p/5100053166大佬博客,讲的非常有条理的

    1,基础知识

    (1)定点数的基础认知:

    首先例如一个16位的数表示的定点数的范围是:(MAX:16‘d32767 MIN: -32767#2^15-1#’)最高位符号位,三位整数位,其余的12位是小数位的话,那么

    它的精度有小数部分决定:1/4096=0.0244140625

    可表示数的范围为:(0.0244140625*4095)=0.999755859375,然后加上整数的最大表示值7,即极限最大值为7.999755859375。

    (2)浮点数的认知

    浮点数就是指整数和小数位数不确定的数字的表达,实际上采用的就是咱们常用的科学计数法。如1.23*10^2采用的是基数(10),指数(2),尾数(1.23)以及一个符号位来表示。这里实际上是采用指数方法实现了小数点的浮动。

    在 IEEE 标准中,浮点数是将特定长度的连续字节的所有二进制位分割为特定宽度的符号域,指数域和尾数域三个域,其中保存的值分别用于表示给定二进制浮点数中的符号,指数和尾数。这样,通过尾数和可以调节的指数(所以称为"浮点")就可以表达给定的数值了。具体的格式参见下面的图例:

     IEEE Floating Point Standard (IEEE754浮点数表示法标准)

     IEEE Floating Point Standard (IEEE754浮点数表示法标准)

    上图中可以看出S表示符号位,EXponent表示指数位,也就是“浮动”的指数位,指数的范围在32位的系统中(0-2^8 -1)/2 也就是0-127,在double型位2^11位浮动指数。

    2.FPGA浮点数的定点化

    首先明确输入的浮点数是什么格式的:其次明白要输出的定点数又是怎样的,最后两者之间的转换也就明了了:

    输入的浮点数是::f[31:0]表示一个单精度32位浮点数,f[31]是符号位,其为‘0’表示正数、为‘1’表示负数;f[30:23]这8位为指数位,为了能表示负指数,将在实际指数的基础上加上127得到的结果存入f[30:23];f[22:0]表示小数位(尾数),类似科学计数法,不过采用了省略整数位(2进制的科学计数法整数位必定是1)1。那么这个浮点数要转换成定点数,就需要先判断指数位与127的关系,小于127,则说明该指数位是正数,那么转化成定点数的话就需要将{8'd1,float_in[22:0]}右移127-float_in[30:23]位,否则左移float_in[30:23]-127位。

    代码稍微贴一下

    module float2fixed_pipeline
        (
        input [31:0] float_in,
        input enable,
        input clk,
        input rst,
        output reg [31:0] fixed_out,
        output reg valid
        );
    
         reg [30:0] M_copy;
        reg [4:0] shift_value;
        reg shift_direction;        //0, shift left; 1, shift right
        reg sign;                   //符号位
        reg valid_count;
    
        
        // Pipeline level 1
        always @ (posedge clk or posedge rst) begin //synchronous enable and asynchronous reset
            if(rst) begin
                shift_value <= 5'd0;
                shift_direction <= 1'b0;
                sign <= 1'b0;
                M_copy <= 31'd0;
            end
            else if(enable) begin
                sign <= float_in[31];
                M_copy <= {8'd1,float_in[22:0]};
                
                if(float_in[30:23] <= 8'd127) begin    //E <= 127,shfit {1'b1,M} right to get I(指数) and F(小数)
                    shift_direction <= 1'b1;
                    shift_value <= 8'd127 - float_in[30:23];
                end
                else begin                            //E > 127,shfit {1'b1,M} left to get I and F
                    shift_direction <= 1'b0;
                    shift_value <= float_in[30:23] - 8'd127;//2^7-1
                end         
            end
            else begin        //enable = 0, Maintain the previous value
                shift_value <= shift_value;
                shift_direction <= shift_direction;
                sign <= sign;
                M_copy <= M_copy;
            end
        end
        
        // Output logic
        always @ (posedge clk or posedge rst) begin //synchronous enable and asynchronous reset
            if(rst) begin
                fixed_out <= 32'd0;
            end
            else if(enable) begin 
                if(shift_direction) begin        //E <= 127,shfit {1'b1,M} right to get I and F
                    fixed_out <= {sign,M_copy >> shift_value};
                end
                else begin                        //E > 127,shfit {1'b1,M} left to get I and F
                    fixed_out <= {sign,M_copy << shift_value};
                end
            end
            else begin        //enable = 0, Maintain the previous value
                fixed_out <= fixed_out;
            end
        end
        
    
        // The valid output logic
        always @ (posedge clk or posedge rst) begin    //asynchronous reset
            if(rst) begin
                valid <= 1'b0;
                valid_count <= 1'd0;
            end
            else if(enable) begin
                if(valid_count == 1'd1) begin    //Maintain valid as ture unless reset
                    valid <= 1'b1;
                    valid_count <= valid_count;
                end
                else begin
                    valid_count <= 1'b1;
                    valid <= 1'b0;
                end
            end
            else begin        //enable = 0, Maintain the previous value
                valid <= valid;
                valid_count <= valid_count;
            end
        end    
        
    endmodule

    3.FPGA定点数的浮点化

    也是想明白输入的定点数格式为最高位是符号位,然后紧接着8位整数位,最后是23位小数位。我们需要注意的是转换后的输出的浮点数最高位符号位,然后是8位的指数位,最后是23位小数位,其表达的浮点数的大小为

    ,将小数位从高到低依次存入f[22:0]的从高到低的位数,不足23位则在末尾补0,例如小数位只有“10011001”则f[22:0]="10011001000000000000000",这样就可以用23位存储空间表示24位的数据,变相增加了精度。另外还有一些特殊编码,如无穷大、0、NAN和非正规数,这里没有考虑,待以后用到再细究吧。

    手算整理思路:

    首先是浮点数的指数位的确定:看定点数整数部分的最高非零位的位置N,那么exp=N-1,

    然后是浮点数的小数位的确定:这里用到了127这个所谓的偏置数以及流水线的设计方法:

    // Output logic
        always @ (posedge clk or posedge rst) begin //synchronous enable and asynchronous reset
            if(rst) begin
                float_out <= 32'd0;
            end
            else if(enable) begin
                if(fixed_shift_reg3[22] == 1'b1) begin
                    float_out <= {fixed_shift_reg3[23],8'd127 - shift_count3 - 8'd1 + ((shift_direction3) ? 8'd8 : 8'd0),fixed_shift_reg3[21:0],1'd0};
                end
                else if(fixed_shift_reg3[21] == 1'b1) begin
                    float_out <= {fixed_shift_reg3[23],8'd127 - shift_count3 - 8'd2 + ((shift_direction3) ? 8'd8 : 8'd0),fixed_shift_reg3[20:0],2'd0};
                end
                else if(fixed_shift_reg3[20] == 1'b1) begin
                    float_out <= {fixed_shift_reg3[23],8'd127 - shift_count3 - 8'd3 + ((shift_direction3) ? 8'd8 : 8'd0),fixed_shift_reg3[19:0],3'd0};
                end
                else begin    //The fixed-point input is zero, -0 will be cast to 0 too.
                    float_out <= {1'b0,8'd127,23'd0};
                end        
            end
            else begin        //enable = 0, Maintain the previous value
                float_out <= float_out;
            end
        end

    小数位的移动在三级流水线中分别根据的是fixed_in[22:11],fixed_shift_reg1[22:17],fixed_shift_reg1[22:20].不等于0的时候不移位,直接拼接,等于0的时候分别移位12,6,3位,将每级流水线中的移位次数记录下来为shift_count3.。。。。。。

    关于流水线的verilog基础还是不扎实,所以下一篇接上流水线的解剖~

  • 相关阅读:
    ES的基本用法
    Elasticsearch安装部署
    jquery-layer弹框在火狐浏览器中弹框不显示的问题
    MySQL中横表和竖表相互转换
    echarts--迁徙图特性简介
    Lucene入门案例一
    Lucene入门简介
    SpringMVC中的拦截器
    SpringMVC中Json数据格式转换
    SpringMVC中的文件上传
  • 原文地址:https://www.cnblogs.com/Dinging006/p/9450577.html
Copyright © 2011-2022 走看看