参考:Vivado IP核之复数浮点数乘法 Floating-point_vivado ip核 复数求模-CSDN博客
floating point IP核I只有multiple ,没有 complex multiple
然后 complex multiple 的IP核下面只有定点的,不支持浮点,所以需要写一个浮点数的复数乘法模块。
`timescale 1ns / 1ps
// 计算公式 (a+bi)(c+di)=ac-bd+(ad+bc)i
// 计算公式(a_re + i*a_im)(b_re + i*b_im)
// =(a_re*b_re) + i*(a_re*b_im) + i*(a_im*b_re) - (a_im*b_im)
// =(a_re*b_re) - (a_im*b_im) + i*(a_re*b_im) + i*(a_im*b_re)
module float_complex_mul
(
input clk, // 输入时钟信号
// 我做流水线其实不需要rst_n来复位,
// 但是我需要一个输入的全局valid来给四个乘法器确认输入数据
// 这个值的输入到时候可以设置为fixed2float的
input s_float_complex_valid,
// input rst_n, //输入复位信号
// input start, //输入开始信号
input [31:0] a_im, //输入因数a的虚部
input [31:0] a_re, //输入因数a的实部
input [31:0] b_im, //输入因数b的虚部
input [31:0] b_re, //输入因数b的实部
// output reg over, //输出计算完成信号
output [31:0] im_res, //输出计算结果的虚部
output [31:0] re_res, //输出计算结果的实部
output m_axis_result_tvalid
);
// //reg define
// reg [4:0] cnt; //过程计数标志
// reg valid1; //乘有效信号
// reg valid2; //加减有效信号
// result_valid信号
wire mul_ip_result_valid_1;
wire mul_ip_result_valid_2;
wire mul_ip_result_valid_3;
wire mul_ip_result_valid_4;
//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
// always @(posedge clk or negedge rst_n)
// if(!rst_n)
// cnt<=0;
// else if(start==1)
// begin
// if(cnt<5'd27)
// 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(5'd0<cnt<=5'd9)
// valid1<=1;
// else
// valid1<=0;
// always @(posedge clk or negedge rst_n)
// if(!rst_n)
// valid2<=0;
// else if(5'd12<cnt<=5'd24)
// valid2<=1;
// else
// valid2<=0;
// always @(posedge clk or negedge rst_n)
// if(!rst_n)
// begin over<=0;re_res<=0;im_res<=0; end
// else if(cnt==5'd26)
// begin over<=1;re_res<=result5;im_res<=result6; end
// else
// begin over<=0;re_res<=0;im_res<=0; end
// 计算公式(a_re + i*a_im)(b_re + i*b_im)
// =(a_re*b_re) - (a_im*b_im) + i*(a_re*b_im) + i*(a_im*b_re)
// 第一个乘法器,计算(a_re*b_re)
float_mul_ip u1_float_mul_ip
(
.aclk(clk),
.s_axis_a_tvalid(s_float_complex_valid),
.s_axis_a_tdata(a_re),
.s_axis_b_tvalid(s_float_complex_valid),
.s_axis_b_tdata(b_re),
.m_axis_result_tvalid(mul_ip_result_valid_1),
.m_axis_result_tdata(result1)
);
// 计算公式(a_re + i*a_im)(b_re + i*b_im)
// =(a_re*b_re) - (a_im*b_im) + i*(a_re*b_im) + i*(a_im*b_re)
// 第二个乘法器,计算(a_im*b_im)
float_mul_ip u2_float_mul_ip
(
.aclk(clk),
.s_axis_a_tvalid(s_float_complex_valid),
.s_axis_a_tdata(a_im),
.s_axis_b_tvalid(s_float_complex_valid),
.s_axis_b_tdata(b_im),
.m_axis_result_tvalid(mul_ip_result_valid_2),
.m_axis_result_tdata(result2)
);
// 计算公式(a_re + i*a_im)(b_re + i*b_im)
// =(a_re*b_re) - (a_im*b_im) + i*(a_re*b_im) + i*(a_im*b_re)
// 第三个乘法器,计算(a_re*b_im)
float_mul_ip u3_float_mul_ip
(
.aclk(clk),
.s_axis_a_tvalid(s_float_complex_valid),
.s_axis_a_tdata(a_re),
.s_axis_b_tvalid(s_float_complex_valid),
.s_axis_b_tdata(b_im),
.m_axis_result_tvalid(mul_ip_result_valid_3),
.m_axis_result_tdata(result3)
);
// 计算公式(a_re + i*a_im)(b_re + i*b_im)
// =(a_re*b_re) - (a_im*b_im) + i*(a_re*b_im) + i*(a_im*b_re)
// 第四个乘法器,计算(a_im*b_re)
float_mul_ip u4_float_mul_ip
(
.aclk(clk),
.s_axis_a_tvalid(s_float_complex_valid),
.s_axis_a_tdata(a_im),
.s_axis_b_tvalid(s_float_complex_valid),
.s_axis_b_tdata(b_re),
.m_axis_result_tvalid(mul_ip_result_valid_4),
.m_axis_result_tdata(result4)
);
wire s_axi_sub_valid;
assign s_axi_sub_valid = mul_ip_result_valid_4 ;
reg s_axi_add_valid;
// 加减法的valid信号可以从乘法器的valid来
// 每个加法的值,来自两个乘法器,我可以拉出四个result_valid信号
// 计算公式(a_re + i*a_im)(b_re + i*b_im)
// =(a_re*b_re) - (a_im*b_im) + i*(a_re*b_im) + i*(a_im*b_re)
// 计算实部,(a_re*b_re) - (a_im*b_im)
float_sub_ip u1_float_sub_ip
( //减法器 计算ac-bd
.aclk(clk),
.s_axis_a_tvalid(s_axi_sub_valid),
.s_axis_a_tdata(result1),
.s_axis_b_tvalid(s_axi_sub_valid),
.s_axis_b_tdata(result2),
.m_axis_result_tvalid(m_axis_result_tvalid),
.m_axis_result_tdata(result5)
);
float_add_ip u1_float_add_ip
( //加法器 计算ad+bc
.aclk(clk),
.s_axis_a_tvalid(s_axi_sub_valid),
.s_axis_a_tdata(result3),
.s_axis_b_tvalid(s_axi_sub_valid),
.s_axis_b_tdata(result4),
.m_axis_result_tvalid(),
.m_axis_result_tdata(result6)
);
assign re_res = result5;
assign im_res = result6;
// always @(posedge clk) begin
// if (m_axis_result_tvalid) begin
// re_res <= result5;
// im_res <= result6;
// end
// end
endmodule