当前位置:网站首页>Vivado IP核之复数浮点数除法 Floating-point
Vivado IP核之复数浮点数除法 Floating-point
2022-07-29 05:25:00 【迎风打盹儿】
Vivado IP核之复数浮点数除法 Floating-point
前言
随着制造工艺的不断发展,现场可编程逻辑门阵列(FPGA)的集成度越来越高,应用也越来越广,其中在对数字信号进行处理时必然要用到一些数学处理类的IP核。最近正在研究空域自适应抗干扰技术研究的FPGA硬件实现,其中不免要用到一些IP核,今天介绍如何运用vivado当中的Floating-point这个IP核实现复数浮点数除法,希望对各位的学习能起到一定的帮助作用。
提示:以下是本篇文章正文内容,均为作者本人原创,写文章实属不易,希望各位在转载时附上本文链接。
一、复数浮点数除法示例
为了后面仿真便于分析结果,在此我们就列举复数浮点数除法的例子,仿真时直接用下面的例子进行仿真,来验证仿真结果是否正确。
example:设浮点数a=32'h4057AE14+j32'h400F5C29,即a=3.37+j2.24,浮点数b=32'h3FE51EB8+j32'hC039999A,即b=1.79-j2.9,则a/b=32'hBD236E2F+32'h3F97E5C9,即a/b=-0.0399+j1.1867,注意该结果只保留了四位小数。
二、Floating-point IP核配置步骤
关于Floating-point IP核的加减乘除如何配置在前面的文章都已经讲解过,不会的同学看我前面的文章,此处不再赘述。
三、整体思路
根据公式
,我们先用六个并行乘法器计算ac,bd,ad,bc,cc,dd的结果,然后再用一个减法器和两个加法器并行计算bc-ad和ac+bd、cc+dd,最后再用两个除法器并行计算
和
即可。在我的IP核配置中,乘法器IP核延时为8个时钟,加法器与减法器IP核延时为11个时钟,除法器IP核延时为28个时钟,为了确保万无一失,在我的代码中,对于数据有效信号Valid多给了一两个时钟。整个顶层代码中,计数cnt尤为重要,很多中间变量的变化都取决于cnt的数值。代码中我注释的地方也比较多,本次设计思路也不难,相信大家能看懂的。
四、仿真
1.顶层代码
建立一个顶层模块,命名为float_complex_div。
代码如下:
`timescale 1ns / 1ps
//
// Company: cq university
// Engineer: clg
// Create Date: 2022/07/26 12:30:21
// Design Name:
// Module Name: float_complex_div
// Project Name:
// Target Devices:
// Tool Versions: 2017.4
// Description:
// Dependencies:
// Revision:1.0
// Revision 0.01 - File Created
// Additional Comments:
//
//计算公式: (a+bi)/(c+di)=( ac+bd+(bc-ad)i )/(c^2+b^2)
module float_complex_div(
input clk, // 输入时钟信号
input rst_n, //输入复位信号
input start, //输入开始信号
input [31:0] re_a, //输入被除数a的实部
input [31:0] im_a, //输入被除数a的虚部
input [31:0] re_b, //输入除数b的实部
input [31:0] im_b, //输入除数b的虚部
output reg over, //输出计算完成信号
output reg [31:0] re_res, //输出计算结果的实部
output reg [31:0] im_res //输出计算结果的虚部
);
//reg define
reg [5:0] cnt; //过程计数标志
reg valid1; //乘有效信号
reg valid2; //加减有效信号
reg valid3; //除有效信号
//wire define
wire [31:0] result1; //结果1
wire [31:0] result2; //结果2
wire [31:0] result3; //结果3
wire [31:0] result4; //结果4
wire [31:0] result5; //结果5
wire [31:0] result6; //结果6
wire [31:0] result7; //结果7
wire [31:0] result8; //结果8
wire [31:0] result9; //结果9
wire [31:0] result10; //结果10
wire [31:0] result11; //结果11
always @(posedge clk or negedge rst_n)
if(!rst_n)
cnt<=0;
else if(start==1)
begin
if(cnt<6'd56)
cnt<=cnt+1;
else
cnt<=0;
end
else if(start==0)
cnt<=0;
always @(posedge clk or negedge rst_n)
if(!rst_n)
valid1<=0;
else if(6'd0<cnt<=6'd9)
valid1<=1;
else
valid1<=0;
always @(posedge clk or negedge rst_n)
if(!rst_n)
valid2<=0;
else if(6'd12<cnt<=6'd24)
valid2<=1;
else
valid2<=0;
always @(posedge clk or negedge rst_n)
if(!rst_n)
valid3<=0;
else if(6'd24<cnt<=6'd53)
valid3<=1;
else
valid3<=0;
always @(posedge clk or negedge rst_n)
if(!rst_n)
begin over<=0;re_res<=0;im_res<=0; end
else if(cnt==6'd55)
begin over<=1;re_res<=result10;im_res<=result11; end
else
begin over<=0;re_res<=0;im_res<=0; end
float_mul_ip u1_float_mul_ip( //乘法器1 计算ac
.aclk(clk),
.s_axis_a_tvalid(valid1),
.s_axis_a_tdata(re_a),
.s_axis_b_tvalid(valid1),
.s_axis_b_tdata(re_b),
.m_axis_result_tvalid(),
.m_axis_result_tdata(result1)
);
float_mul_ip u2_float_mul_ip( //乘法器2 计算bd
.aclk(clk),
.s_axis_a_tvalid(valid1),
.s_axis_a_tdata(im_a),
.s_axis_b_tvalid(valid1),
.s_axis_b_tdata(im_b),
.m_axis_result_tvalid(),
.m_axis_result_tdata(result2)
);
float_mul_ip u3_float_mul_ip( //乘法器3 计算ad
.aclk(clk),
.s_axis_a_tvalid(valid1),
.s_axis_a_tdata(re_a),
.s_axis_b_tvalid(valid1),
.s_axis_b_tdata(im_b),
.m_axis_result_tvalid(),
.m_axis_result_tdata(result3)
);
float_mul_ip u4_float_mul_ip( //乘法器4 计算bc
.aclk(clk),
.s_axis_a_tvalid(valid1),
.s_axis_a_tdata(im_a),
.s_axis_b_tvalid(valid1),
.s_axis_b_tdata(re_b),
.m_axis_result_tvalid(),
.m_axis_result_tdata(result4)
);
float_mul_ip u5_float_mul_ip( //乘法器5 计算c*c
.aclk(clk),
.s_axis_a_tvalid(valid1),
.s_axis_a_tdata(re_b),
.s_axis_b_tvalid(valid1),
.s_axis_b_tdata(re_b),
.m_axis_result_tvalid(),
.m_axis_result_tdata(result5)
);
float_mul_ip u6_float_mul_ip( //乘法器6 计算d*d
.aclk(clk),
.s_axis_a_tvalid(valid1),
.s_axis_a_tdata(im_b),
.s_axis_b_tvalid(valid1),
.s_axis_b_tdata(im_b),
.m_axis_result_tvalid(),
.m_axis_result_tdata(result6)
);
float_sub_ip u1_float_sub_ip( //减法器 计算bc-ad
.aclk(clk),
.s_axis_a_tvalid(valid2),
.s_axis_a_tdata(result4),
.s_axis_b_tvalid(valid2),
.s_axis_b_tdata(result3),
.m_axis_result_tvalid(),
.m_axis_result_tdata(result7)
);
float_add_ip u1_float_add_ip( //加法器1 计算ac+bd
.aclk(clk),
.s_axis_a_tvalid(valid2),
.s_axis_a_tdata(result1),
.s_axis_b_tvalid(valid2),
.s_axis_b_tdata(result2),
.m_axis_result_tvalid(),
.m_axis_result_tdata(result8)
);
float_add_ip u2_float_add_ip( //加法器2 计算cc+dd
.aclk(clk),
.s_axis_a_tvalid(valid2),
.s_axis_a_tdata(result5),
.s_axis_b_tvalid(valid2),
.s_axis_b_tdata(result6),
.m_axis_result_tvalid(),
.m_axis_result_tdata(result9)
);
float_div_ip u1_float_div_ip( //除法器1 计算(ac+bd)/(cc+dd)
.aclk(clk),
.s_axis_a_tvalid(valid3),
.s_axis_a_tdata(result8),
.s_axis_b_tvalid(valid3),
.s_axis_b_tdata(result9),
.m_axis_result_tvalid(),
.m_axis_result_tdata(result10)
);
float_div_ip u2_float_div_ip( //除法器2 计算(bc-ad)/(cc+dd)
.aclk(clk),
.s_axis_a_tvalid(valid3),
.s_axis_a_tdata(result7),
.s_axis_b_tvalid(valid3),
.s_axis_b_tdata(result9),
.m_axis_result_tvalid(),
.m_axis_result_tdata(result11)
);
endmodule
2.仿真代码
建立一个仿真模块,命名为float_complex_div_tb,用来仿真顶层模块。
代码如下:
`timescale 1ns / 1ps
//
// Company: cq university
// Engineer: clg
// Create Date: 2022/07/26 13:32:30
// Design Name:
// Module Name: float_complex_div_tb
// Project Name:
// Target Devices:
// Tool Versions: 2017.4
// Description:
// Dependencies:
// Revision:1.0
// Revision 0.01 - File Created
// Additional Comments:
//
module float_complex_div_tb();
reg clk; // 输入时钟信号
reg rst_n; //输入复位信号
reg start; //输入开始信号
reg [31:0] re_a; //输入因数a的实部
reg [31:0] im_a; //输入因数a的虚部
reg [31:0] re_b; //输入因数b的实部
reg [31:0] im_b; //输入因数b的虚部
wire over; //输出计算完成信号
wire [31:0] re_res; //输出计算结果的实部
wire [31:0] im_res; //输出计算结果的虚部
float_complex_div u1_float_complex_div( //例化顶层模块
.clk(clk),
.rst_n(rst_n),
.start(start),
.re_a(re_a),
.im_a(im_a),
.re_b(re_b),
.im_b(im_b),
.over(over),
.re_res(re_res),
.im_res(im_res)
);
always #5 clk=~clk;
initial begin
clk=1'b0;rst_n=1'b1;start=1'b0;
#5; rst_n=1'b0;
#10; rst_n=1'b1;
start=1'b1;
re_a=32'h4057ae14;
im_a=32'h400f5c29;
re_b=32'h3fe51eb8;
im_b=32'hc039999a;
#560 start=1'b0;
end
endmodule五、仿真结果分析
仿真结果如图1所示,对比前面所列举复数浮点数除法的例子,可知该模块成功实现了复数浮点数的除法。该结果为32'hBD23891A+j32'h3F97E634,即-0.039925672+j1.1867127,如果保留四位小数就为-0.0399+j1.1867,这与本文开始介绍的例子是符合的。

总结
本次介绍了复数浮点数的除法。
边栏推荐
- 计算机网络面试题
- Leetcode 977. Square of ordered array
- Mathematical modeling experience
- [beauty of software engineering - column notes] 19 | as a programmer, you should have product awareness
- 虹科分享 | 为什么说EtherCAT是提高控制系统性能的最佳解决方案?
- 只让电脑运行某个程序设置
- Official tutorial redshift 09 camera
- Operating system interview questions
- Ue5 light shadow basic shadow full resolution sawtooth shadow solution lumen
- Leetcode scribble notes 763. Divide the letter range (medium)
猜你喜欢

Leetcode 1. sum of two numbers

Leetcode 7. integer inversion

Leetcode 9. palindromes

Leetcode 13. Roman numeral to integer

Redshift restore SP effect - SP map export settings and map import configuration

虹科教您 | 想进入TSN领域?虹科教您如何搭建TSN测试系统

Leetcode 83. delete duplicate elements in the sorting linked list

LeetCode #19.删除链表的倒数第N个结点

LeetCode #167.两数之和 II - 输入有序数组

Vivado IP核之浮点数开方 Floating-point
随机推荐
Unity初学2——瓦片的制作以及世界的交互(2d)
服务器135、137、138、139、445等端口解释和关闭方法
[leetcode brush questions] array 3 - divide and conquer
电脑鼠标右键单击总是转圈圈怎么回事
Leetcode 14. longest public prefix
使用STP生成树协议解决网络中的二层环路问题
LeetCode #35.搜索插入位置
Leetcode 35. search insertion location
钓鱼邮件处置
Leetcode 26. delete duplicates in the ordered array
Official tutorial redshift 04 rendering parameters
虹科分享 | 带你全面了解“CAN总线错误”(四)——在实践中生产和记录CAN错误
右值引用和移动构造
Leetcode 13. Roman numeral to integer
虹科分享 | 带您全面认识“CAN总线错误”(一)——CAN总线错误与错误帧
单链表面试题
leetcode刷题笔记 605. Can Place Flowers (Easy) 605.种花问题
Abstract classes and interfaces
LeetCode #3.无重复字符的最长子串
虹科为您分享EtherCAT demo,教您如何从其他协议快速过渡到EtherCAT工业总线