1, FPGA device, using three 18bit x 18 bit multiplier to implement 32bit float multiplier

2, comparing to Altera float multiplyer IP

   (1)  just half of the LEs were used

(2)  nearly same accuracy

VS2013, simulation by C

/////////////////////////////////////////////////////////////////////////

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <ios>
#include <iostream>

typedef unsigned int uint;
typedef unsigned long long uint64;
typedef long long int64;

uint GetBits(const float& v, int nstart, int cnt){
    uint bits = 0;
    uint vv;
    memcpy(&vv, &v, sizeof(v));
    //printf("%f, 0x%h) << std::endl; ", v, vv);
    for(int i = cnt - 1; i >= 0; i--){
        int idx = nstart + i;
        uint t = 1 << idx;

bits <<= 1;
        int b = (vv >> idx) & 1;
        bits |= b;
        //printf("%d", b);
    }
    //printf("\n");
    return bits;
}

int64 HighestOne(int64 v){
    int idx = -1;
    for(int i = sizeof(v)* 8 - 1; i >= 0; i--){
        if((v >> i) & 1){
            idx = i;
            break;
        }
    }
    return idx;
}

template<typename T1, typename T2>
void SetBit(T1& src, int src_idx, T2& dst, int dst_idx){
    int v = (src >> src_idx) & 1;
    if(v)
        dst |= v << dst_idx;
}

template<typename T1, typename T2>
void SetBits(T1& src, int src_idx, T2& dst, int dst_idx, int count){
    for(int i = 0; i < count; i++){
        SetBit(src, src_idx + i, dst, dst_idx + i);
    }
}

float fpmul(float a, float b){
    int64 s1 = GetBits(a, 31, 1);
    int64 s2 = GetBits(b, 31, 1);
    int64 e1 = GetBits(a, 23, 8);
    int64 e2 = GetBits(b, 23, 8);
    int64 f1 = GetBits(a, 0, 23);
    int64 f2 = GetBits(b, 0, 23);
    int64 a1 = GetBits(a, 14, 9);
    int64 a2 = GetBits(b, 14, 9);
    int64 b1 = GetBits(a, 5, 9);
    int64 b2 = GetBits(b, 5, 9);

//sum = 1 + f1 + f2 + [ (a1*a2) + (a1*b2 + a2*b1)*2^(-9) + (c1*a2 + b1*b2 + a1*c2)*2^(-18) + 0]               
    int64 sum = int64(1 << 23)
        + (f1 + f2)
        + (int64(a1 * a2) << (28 - 23))
        + (int64(a1*b2 + a2*b1) >> (9 - (28 - 23)));
    int nHightIndx = HighestOne(sum);

uint val = 0;
    SetBits(sum, nHightIndx - 23, val, 0, 23);

int e = e1 - 127 + e2 - 127 + 127 + (nHightIndx - 23);
    int s = ((s1 + s2) & 1) ? (1) : (0);

SetBits(e, 0, val, 23, 8);
    SetBit(s, 0, val, 31);

//val = 0x4023d702;
    float v;
    memcpy(&v, &val, sizeof(v));

return v;
}

void Test_fpmul(){
    //float v1 = 0.056984*0.056984;
    //float v = fpmul(0.056984, 0.056984);
    for(int i = -1000; i < 1000; i++){
        float a = -0.23 + i*0.0003;
        float b = 0.19 + i*0.0003;
        float v = fpmul(a, b);
        printf("a(%e), b(%e), a*b=%e, my_fmul=%e\n", a, b, (a*b), v);
    }
}

inline float Hex2Float(uint val){
    float v = 0;
    memcpy(&v, &val, sizeof(val));
    return v;
}

#define HEX2FLOAT(_x)  Hex2Float((0x##_x))

inline void Verify(){
    float s;
    std::cout << HEX2FLOAT(3fc30f28) << " x " << HEX2FLOAT(3fc30f28) << std::endl;
    std::cout << HEX2FLOAT(00000000) << std::endl;
    std::cout << "--------------------------------" << std::endl;
    //
    //
    std::cout << HEX2FLOAT(40a7a9fc) << " x " << HEX2FLOAT(40a7a9fc) << std::endl;
    std::cout << HEX2FLOAT(40800000) << std::endl;
    std::cout << "--------------------------------" << std::endl;
    //
    //
    std::cout << HEX2FLOAT(4251954d) << " x " << HEX2FLOAT(4251954d) << std::endl;
    std::cout << HEX2FLOAT(4014a012) << std::endl;
    std::cout << "--------------------------------" << std::endl;
    //
    //
    std::cout << HEX2FLOAT(4402fd52) << " x " << HEX2FLOAT(4402fd52) << std::endl;
    std::cout << HEX2FLOAT(41db9e50) << std::endl;
    std::cout << "--------------------------------" << std::endl;
    //
    //
    std::cout << HEX2FLOAT(4251954d) << " x " << HEX2FLOAT(4402fd52) << std::endl;
    std::cout << HEX2FLOAT(452b9514) << std::endl;
    std::cout << "--------------------------------" << std::endl;
    //
    //
    std::cout << HEX2FLOAT(3f07929f) << " x " << HEX2FLOAT(3f07929f) << std::endl;
    std::cout << HEX2FLOAT(48860c65) << std::endl;
    std::cout << "--------------------------------" << std::endl;
    //
    //
    std::cout << HEX2FLOAT(bf07929f) << " x " << HEX2FLOAT(4402fd52) << std::endl;
    std::cout << HEX2FLOAT(46d67a53) << std::endl;
    std::cout << "--------------------------------" << std::endl;
    //
    //
    std::cout << HEX2FLOAT(4380650b) << " x " << HEX2FLOAT(4380650b) << std::endl;
    std::cout << HEX2FLOAT(3e8f97e9) << std::endl;
    std::cout << "--------------------------------" << std::endl;

std::cout << HEX2FLOAT(3da1ab4b) << " x " << HEX2FLOAT(3da1ab4b) << std::endl;
    std::cout << HEX2FLOAT(c38abd2d) << std::endl;
    std::cout << "--------------------------------" << std::endl;

std::cout << HEX2FLOAT(3da1ab4b) << " x " << HEX2FLOAT(3f07929f) << std::endl;
    std::cout << HEX2FLOAT(4780ca5b) << std::endl;
    std::cout << "--------------------------------" << std::endl;

std::cout << HEX2FLOAT(3da1ab4b) << " x " << HEX2FLOAT(00000000) << std::endl;
    std::cout << HEX2FLOAT(3bcc31b9) << std::endl;
    std::cout << "--------------------------------" << std::endl;

std::cout << HEX2FLOAT(3bbab9a5) << " x " << HEX2FLOAT(3bbab9a5) << std::endl;
    std::cout << HEX2FLOAT(3d2b3bca) << std::endl;
    std::cout << "--------------------------------" << std::endl;

std::cout << HEX2FLOAT(3bbab9a5) << " x " << HEX2FLOAT(3da1ab4b) << std::endl;
    std::cout << HEX2FLOAT(7e21ab4b) << std::endl;
    std::cout << "--------------------------------" << std::endl;

std::cout << HEX2FLOAT(3bbab9a5) << " x " << HEX2FLOAT(3da1ab4b) << std::endl;
    std::cout << HEX2FLOAT(3808323b) << std::endl;
    std::cout << "--------------------------------" << std::endl;

std::cout << HEX2FLOAT(3bbab9a5) << " x " << HEX2FLOAT(3da1ab4b) << std::endl;
    std::cout << HEX2FLOAT(39ebd749) << std::endl;
    std::cout << "--------------------------------" << std::endl;

std::cout << HEX2FLOAT(3bbab9a5) << " x " << HEX2FLOAT(3da1ab4b) << std::endl;
    std::cout << HEX2FLOAT(39ebd749) << std::endl;
    std::cout << "--------------------------------" << std::endl;

std::cout << HEX2FLOAT(3bbab9a5) << " x " << HEX2FLOAT(3da1ab4b) << std::endl;
    std::cout << HEX2FLOAT(39ebd749) << std::endl;
    std::cout << "--------------------------------" << std::endl;

std::cout << HEX2FLOAT(3bbab9a5) << " x " << HEX2FLOAT(3da1ab4b) << std::endl;
    std::cout << HEX2FLOAT(39ebd749) << std::endl;
    std::cout << "--------------------------------" << std::endl;

std::cout << HEX2FLOAT(3bbab9a5) << " x " << HEX2FLOAT(3da1ab4b) << std::endl;
    std::cout << HEX2FLOAT(39ebd749) << std::endl;
    std::cout << "--------------------------------" << std::endl;

std::cout << HEX2FLOAT(3bbab9a5) << " x " << HEX2FLOAT(3da1ab4b) << std::endl;
    std::cout << HEX2FLOAT(39ebd749) << std::endl;
    std::cout << "--------------------------------" << std::endl;

}

void main(){
    Test_fpmul();
    Verify();
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

////////////////////////////// Verilog Implement ///////////////////////////

//`define _DEBUG
module my_fpmul(clk, rst_n, dataa, datab, result
`ifdef _DEBUG
        ,_a1 ,_b1 ,_a2 ,_b2, _e1, _e2
        ,_ss
        ,_sum
        , _se
        ,_sf1f2
        ,_sa1a2
        ,_sa1b2
        ,_sa2b1
`endif
        );

input  clk;
input  rst_n;
input  [31:0] dataa;
input  [31:0] datab;
output [31:0] result;

`ifdef _DEBUG
output [8:0]_a1;
output [8:0]_b1;
output [8:0]_a2;
output [8:0]_b2;
output [8:0]_e1;
output [8:0]_e2;
output _ss;
output [26:0]_sum;
output [8:0]_se;
output [24:0]_sf1f2;
output [22:0]_sa1a2;
output [18:0]_sa1b2;
output [18:0]_sa2b1;
`endif

//clk 1
reg [31:0]datac = 32'h0;
reg s1          = 1'b0;
reg s2          = 1'b0;
reg [8:0]e1     = 8'b0;
reg [8:0]e2     = 8'b0;
reg [22:0]f1    = 23'b0;
reg [22:0]f2    = 23'b0;
reg [17:0]a1     = 18'b0;
reg [17:0]a2     = 18'b0;
reg [17:0]b1     = 18'b0;
reg [17:0]b2     = 18'b0;

//clk 2
reg ss = 1'b0;
reg [24:0]sf1f2 = 25'b0;
reg [22:0]sa1a2 = 23'b0;
reg [18:0]sa1b2 = 19'b0;
reg [18:0]sa2b1 = 19'b0;
reg [26:0]sum   = 32'b0;
reg [8:0]se    = 9'b0;

////clk 3
reg  sss = 1'b0;
reg [7:0]sse   = 8'b0;
reg [22:0]ssum = 23'b0;

//pipline step 1
always@(posedge clk or negedge rst_n) begin
    if (!rst_n) datac <= 32'h0;
    else begin
        s1 <= dataa[31:31];
        s2 <= datab[31:31];
        e1 <= dataa[30:23];
        e2 <= datab[30:23];
        f1 <= dataa[22:0];
        f2 <= datab[22:0];
        a1 <= {9'b0, dataa[22:14]};
        a2 <= {9'b0, datab[22:14]};
        b1 <= {9'b0, dataa[13:5]};
        b2 <= {9'b0, datab[13:5]};
    end
end

//pipline step 2
always@(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        ss <= 1'b0;
        se <= 1'b0;
        sum <= 27'b0;
    end else begin
        ss <= s1^s2;
        se <= e1 + e2 - 8'd127;        
        sf1f2 = (24'b1 << 23) + (f1 + f2);
        sa1a2 = {a1*a2,5'b0};
        sa1b2 = a1*b2;
        sa2b1 = a2*b1;    
        sum <= sf1f2 + sa1a2 + ((sa1b2 + sa2b1)>>3'd4);
        //sum <= (26'b1 << 23) + (f1 + f2) + {a1*a2,5'b0} + {{9'b0, a1}*{9'b0, a2}, 5'b0} + {9'b0, a1}*{9'b0, b2} + {9'b0, a2}*{9'b0, b1};
    end
end

//pipline step 3
always@(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        sss <= 1'b0;
        sse <= 8'b0;
        ssum <= 23'b0;
    end else begin    
        sss <= ss;
        if (sum[25]) begin
            sse <= se + 2'd2;
            ssum <= sum[24:2];
        end else if (sum[24]) begin
            sse <= se + 2'd1;
            ssum <= sum[23:1];
        end else begin
            sse <= se;
            ssum <= sum[22:0];
        end
    end
end

assign result = {sss, sse, ssum};

`ifdef _DEBUG
assign _e1 = e1;
assign _e2 = e2;
assign _a1 = a1;
assign _b1 = b1;
assign _a2 = a2;
assign _b2 = b2;
assign _ss = ss;
assign _sum = sum;
assign _se = se;
assign _sf1f2 = sf1f2;
assign _sa1a2 = sa1a2;
assign _sa1b2 = sa1b2;
assign _sa2b1 = sa2b1;
`endif

endmodule

//////////////////////////////////////////////////////////////////////////////

/////////////////////////////Test Bench////////////////////////////////////

//`define _DEBUG

`timescale 1 ns/ 1 ps
module my_fpmul_vlg_tst();
// constants                                           
// general purpose registers
reg eachvec;
// test vector input registers
reg clk;
reg [31:0] dataa;
reg [31:0] datab;
reg rst_n;
// wires                                               
wire [31:0]  result;

`ifdef _DEBUG
wire [8:0]  _a1, _b1, _a2, _b2;
wire[8:0]_e1;
wire[8:0]_e2;
wire _ss;
wire [26:0]_sum;
wire [8:0]_se;
wire [24:0]_sf1f2;
wire [22:0]_sa1a2;
wire [18:0]_sa1b2;
wire [18:0]_sa2b1;
`endif

// assign statements (if any)                          
my_fpmul i1 (
// port map - connection between master ports and signals/registers   
    .clk(clk),
    .rst_n(rst_n),    
    .dataa(dataa),
    .datab(datab),
    .result(result)
`ifdef _DEBUG
    ,._a1(_a1) , ._b1(_b1) , ._a2(_a2) , ._b2(_b2), ._e1(_e1), ._e2(_e2)
    ,._ss(_ss) , ._sum(_sum)    , ._se(_se)
    ,._sf1f2(_sf1f2)
        ,._sa1a2(_sa1a2)
        ,._sa1b2(_sa1b2)
        ,._sa2b1(_sa2b1)
`endif
);

initial begin
    rst_n = 1;
    clk   = 0;
    forever #10 clk = ~clk;
end

initial begin
    repeat(30)
    begin
        #7
        $display("%x * %x : ", dataa, datab);
        #5
        $display("%x", result);
        #8
        $display("\n");
    end    
end

initial begin
    //dataa<=32'h3bbab9a5; //0.0056984  
    //datab<=32'h3bbab9a5; //0.0056984

dataa <= 32'b0;
    datab <= 32'b0;    
    #5;  
    dataa<=32'h3fc30f28; //1.5239  
    datab<=32'h3fc30f28;  
    #20;  
    dataa<=32'h40a7a9fc; //5.2395  
    datab<=32'h40a7a9fc;  
    #20;  
    dataa<=32'h4251954d; //52.3958  
    datab<=32'h4251954d;  
    #20;  
    dataa<=32'h4402fd52; //523.9581  
    datab<=32'h4402fd52;  
    #20;  
    dataa<=32'h4251954d; //52.3958  
    datab<=32'h4402fd52; //523.9581  
    #20;  
    dataa<=32'h3f07929f; //0.529581  
    datab<=32'h3f07929f;  
    #20;  
    dataa<=32'hbf07929f; //-0.529581  
    datab<=32'h4402fd52; //523.9581  
    #20;  
    dataa<=32'h4380650b; //256.7894  
    datab<=32'h4380650b;   
    #20;  
    dataa<=32'h3da1ab4b; //0.07894  
    datab<=32'h3da1ab4b;   
    #20;  
    dataa<=32'h3da1ab4b; //0.07894  
    datab<=32'h3f07929f; //0.529581  
    #20;  
    dataa<=32'h3da1ab4b; //0.07894  
    datab<=32'h0; //0.529581  
    #20;  
    dataa<=32'h3bbab9a5; //0.0056984  
    datab<=32'h3bbab9a5; //0.0056984  
    #20;  
    dataa<=32'h3bbab9a5; //0.0056984  
    datab<=32'h3da1ab4b; //0.07894

#2000
     $stop;
     //$finish;
    
end

endmodule
//////////////////////////////////////////////////////////////////////////////////////////////

FPGA, Float 32bit, multiplyier by Verilog的更多相关文章

  1. 基于FPGA的cordic算法的verilog初步实现

    最近在看cordic算法,由于还不会使用matlab,真是痛苦,一系列的笔算才大概明白了这个算法是怎么回事.于是尝试用verilog来实现.用verilog实现之前先参考软件的程序,于是先看了此博文h ...

  2. 【FPGA】高斯白噪声的Verilog实现

    本文章主要讨论高斯白噪声的FPGA实现.简单的方法可以采用在Matlab中产生服从一定均值和方差的I.Q两路噪声信号.然后将两组数据存在FPGA中进行回放,以此来产生高斯白噪声.这种方法优点是产生方法 ...

  3. FPGA编程—组合逻辑编码器等verilog实现

    本篇博客主要实现对组合逻辑电路的一些常用模块的实现.组合逻辑中,包括译码器,编码器,输入输出选择器,数值比较器,算法单元等.  先来实现编码器,最常用的8-3编码器,这里先讲一下要用到的case ,c ...

  4. FPGA实战操作(1) -- SDRAM(Verilog实现)

    对SDRAM基本概念的介绍以及芯片手册说明,请参考上一篇文章SDRAM操作说明. 1. 说明 如图所示为状态机的简化图示,过程大概可以描述为:SDRAM(IS42S16320D)上电初始化完成后,进入 ...

  5. 134-基于TMS320C6678、FPGA XC5VSX95T的一路Full模式Camera Link图像理平台

    基于TMS320C6678.FPGA XC5VSX95T的一路Full模式Camera Link图像理平台 一.板卡概述 该板卡采用TI公司新一代DSP TMS320C6678,结合FPGA,型号为X ...

  6. 自顶而下设计FPGA

    对IC设计而言,FPGA设计层级大致包括:系统级和行为级,RTL级,门级和晶体管级.然而更普遍的情况,FPGA只是用作实时数据采集控制.某些快速处理算法.PCIe\DDR3等高速数据通道,甚至某些简单 ...

  7. C中的Float分析

    C/C++中, 浮点数,float以及 double 在内存中是怎样存储的? 假如,我有32-bit 8bit 8bit 8bit 0 0 0 0 0 1 1 1 1 对于整形int,我们可以很快得出 ...

  8. 基于FPGA的IIR滤波器

    基于FPGA的IIR滤波器                                                         by方阳 版权声明:本文为博主原创文章,转载请指明转载地址 ...

  9. 学习cordic算法所得(流水线结构、Verilog标准)

    最近学习cordic算法,并利用FPGA实现,在整个学习过程中,对cordic算法原理.FPGA中流水线设计.Verilog标准有了更加深刻的理解. 首先,cordic算法的基本思想是通过一系列固定的 ...

随机推荐

  1. linux c编程:进程控制(四)进程调度

    当系统中有多个进程到时候,哪个进程先执行,哪个进程后执行是由进程的优先级决定的.进程的优先级是由nice值决定的.nice值越小,优先级越高.可以看做越友好那么调度优先级越低.进程可以通过nice函数 ...

  2. CentOS7安装MySQL8.0小计

    之前讲配置文件和权限的时候有很多MySQL8的知识,有同志说安装不太一样,希望发个文,我这边简单演示一下 1.环境安装 下载MySQL提供的CentOS7的yum源 官方文档:<https:// ...

  3. Symfony 使用KnpTimeBundle

    使用time_diff时出现:diff.ago.hour; 解决:1:引入"knplabs/knp-time-bundle": "^1.7",https://g ...

  4. [转载]设计模式的UML图

    1.抽象工厂(Abstract Factory)模式 意图:为特定的客户(或情况)提供特定系列的对象. 2.类的适配器(Adapter)模式 意图:将一个类的接口转换成客户希望的另外一个接口. 3.对 ...

  5. Iptalbes练习题(一)

    实验环境: KVM 虚拟机 centos6.7 test1:192.168.124.87  test2:192.168.124.94 场景一: 要求:1.对所有地址开放本机的tcp(80.22.10- ...

  6. 运行“cordova build android” - 无法找到属性android:fontVariationSettings和android:ttcIndex

    :app:processArm64DebugResourcesC:\Users\xfcao\.gradle\caches\transforms-1\files-1.1\xwalk_core_libra ...

  7. HDU - 1134 Game of Connections 【DP】

    题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=1134 题意 给出一个n 然后有2n个点 给两个点连一条边,最后连N条边,要求所有的边不能够交叉 问最多 ...

  8. DEV开发之控件NavBarControl

    右键点击RunDesigner弹出如下界面鼠标先点击3或4,1,,然后点击1或2进行相应的新增或删除操作,3是分组,4是项目,4可以直接拖动到相应的分组3.属性caption:显示的名称4.NavBa ...

  9. table-cell笔记

    display:table-cell可将元素设为类似于table的td一样的布局,在垂直居中.两行自适应布局.等高布局下有很高的利用价值 详见: http://www.zhangxinxu.com/w ...

  10. 用Delphi模拟键盘输入

    在Windows大行其道的今天,windows界面程序受到广大用户的欢迎.对这些程序的操作不外乎两种,键盘输入控制和鼠标输入控制.有时,对于繁杂的,或重复性的操作,我们能否通过编制程序来代替手工输入, ...