FPGA----Verilog复数运算

1、好久没写文章了,有点手生,大家尽量看。本文章代码实现了32位浮点数(即一个复数为64位)的复数计算,且本人实现了32*32复数矩阵的求逆运算,需要的请查看作者资料邮箱。

2、Verilog复数运算

实验任务:实现A=1*4(虚数位32位、实数位32位),B=4*1(虚数位32位、实数位32位)全浮点数复数矩阵计算。本代码并行度高、代码复用性强。

实验软硬件:ZCU106、Vivado 2019.1

实验知识:(a+bi)*(c+di)=(ac-bd) + (bc+ad)i。因此需要4个乘法器,一个减法器,一个加法器。因此需要两步计算即可完成复数乘法计算。网上的变换可以变换为只需要3个乘法器,5个加法器,但是计算时间并没有降低,因此不采用此方法。

实验过程:

①建立工程,complex_multiply。

②添加乘法IP核与加法IP核

③复制代码

`timescale 1ns / 1ps
//
// Company: 东北电力大学
// Engineer: Yang Zheng 
// 
// Create Date: 2022/02/09 23:09:55
// Design Name: 
// Module Name: complex_add_compute
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module complex_add_compute
#(
    DW =32//位宽
)(
    input   clk,
    input   rst,
    input   [(DW * 2)-1:0]   complex_add_compute_input_A,//高32位是实部,低32位是虚部
    input   [(DW * 2)-1:0]   complex_add_compute_input_B,//高32位是实部,低32位是虚部
    output  [(DW * 2)-1:0]   complex_add_compute_output,//高32位是实部,低32位是虚部

    input   complex_add_input_valid,//输入开始求解信号
    output  complex_add_output_valid,//输出求解完毕信号
    output  complex_add_valid_en//输出此模块可用信号
    );
    reg [(DW)-1:0]   output_real = 'd0;
    reg [(DW)-1:0]   output_imag = 'd0;
    assign complex_add_compute_output = {output_real,output_imag};
    reg complex_add_output_valid_r = 1'b0;
    reg complex_add_valid_en_r = 1'b1;
    assign complex_add_output_valid = complex_add_output_valid_r;
    assign complex_add_valid_en = complex_add_valid_en_r;
    //初始化输入
    reg compute_reshape = 1'b0;
    reg [(DW)-1:0]  complex_compute_a = 'd0;
    reg [(DW)-1:0]  complex_compute_b = 'd0;
    reg [(DW)-1:0]  complex_compute_c = 'd0;
    reg [(DW)-1:0]  complex_compute_d = 'd0;
    always @(posedge clk or negedge rst) begin
        if (!rst) begin
            //复位
            compute_reshape <= 1'b0;
            complex_compute_a <= 'd0;
            complex_compute_b <= 'd0;
            complex_compute_c <= 'd0;
            complex_compute_d <= 'd0;
            output_real <= 'd0;
            output_imag <= 'd0;
        end
        else if(complex_add_input_valid == 1'b1 && compute_reshape == 1'b0) begin
            complex_compute_a <=complex_add_compute_input_A[(DW * 2)-1:DW];
            complex_compute_b <=complex_add_compute_input_A[(DW)-1:0];
            complex_compute_c <=complex_add_compute_input_B[(DW * 2)-1:DW];
            complex_compute_d <=complex_add_compute_input_B[(DW)-1:0];

            complex_add_valid_en_r <= 1'b0;
            compute_reshape <= 1'b1;
        end
    end

    //例化模块
    /*例化2个加法器模块*/
    reg aresetn_add = 1'b0;
    always @(negedge rst) begin
        if (!rst) begin
            aresetn_add <= 1'b1;
        end
    end
    reg add_a_tvalid_1 = 1'b0;
    reg add_b_tvalid_1 = 1'b0;
    reg  [31:0] add_a_tdata_1 = 32'b0;
    reg  [31:0] add_b_tdata_1 = 32'b0;
    wire [31:0] add_result_tdata_1;
    complex_compute_add uut_complex_compute_add_1(
        .aclk(clk),
        .aresetn(aresetn_add),
        .s_axis_a_tvalid(add_a_tvalid_1),
        .s_axis_a_tdata(add_a_tdata_1),
        .s_axis_b_tvalid(add_b_tvalid_1),
        .s_axis_b_tdata(add_b_tdata_1),
        .m_axis_result_tvalid(add_result_tvalid_1),
        .m_axis_result_tdata(add_result_tdata_1)
    );
    reg add_a_tvalid_2 = 1'b0;
    reg add_b_tvalid_2 = 1'b0;
    reg  [31:0] add_a_tdata_2 = 32'b0;
    reg  [31:0] add_b_tdata_2 = 32'b0;
    wire [31:0] add_result_tdata_2;
    complex_compute_add uut_complex_compute_add_2(
        .aclk(clk),
        .aresetn(aresetn_add),
        .s_axis_a_tvalid(add_a_tvalid_2),
        .s_axis_a_tdata(add_a_tdata_2),
        .s_axis_b_tvalid(add_b_tvalid_2),
        .s_axis_b_tdata(add_b_tdata_2),
        .m_axis_result_tvalid(add_result_tvalid_2),
        .m_axis_result_tdata(add_result_tdata_2)
    );

    //状态机
    reg [1:0]   st_cur =  'd0;
    reg [1:0]   st_next = 'd0;
    parameter   IDLE  = 2'd0 ;
    parameter   ST1   = 2'd1 ;
    always @(posedge clk or negedge rst) begin
        if (!rst) begin
            st_cur <= 'd0;
            st_next <= 'd0;
        end
        else begin
            st_cur <= st_next;
        end
    end

    reg ST1_done = 1'b0;
    reg ST1_do = 1'b0;
    reg [2:0] aresetn_count = 3'b0;

    
    //状态切换
    always @(posedge clk) begin
        case (st_cur)
            IDLE: 
                if (complex_add_input_valid == 1'b1 && compute_reshape == 1'b1) begin
                    st_next <= ST1;
                    ST1_do <= 1'b0;
                end
            ST1:
                if (ST1_done) begin
                    /*加法器复位*/
                    aresetn_add <= 1'b0;
                    aresetn_count <= aresetn_count + 1'b1;
                    complex_add_output_valid_r <= 1'b1;
                    if (aresetn_count == 'd3) begin
                        aresetn_count <= 1'b0;
                        st_next <= IDLE;
                        aresetn_add <= 1'b1;
                        ST1_done <= 1'b0;
                        complex_add_valid_en_r <= 1'b1;
                        compute_reshape <= 1'b0;
                    end
                end
            default: st_next <= IDLE;
        endcase
    end
    //状态过程
    always @(posedge clk or negedge rst) begin
        if (!rst) begin
            
        end
        else begin
            if (st_cur == ST1 && ST1_done == 1'b0 && ST1_do == 1'b0) begin
            //计算a+c、b+d

                add_a_tvalid_1 <= 1'b1;
                add_b_tvalid_1 <= 1'b1;
                add_a_tdata_1 <= complex_compute_a;
                add_b_tdata_1 <= complex_compute_c;
                add_a_tvalid_2 <= 1'b1;
                add_b_tvalid_2 <= 1'b1;
                add_a_tdata_2 <= complex_compute_b;
                add_b_tdata_2 <= complex_compute_d;

                ST1_do <= 1'b1;
            end
        end
    end
    //状态输出
    //ST1 输出
    always @(posedge clk or negedge rst) begin
        if (!rst) begin
            ST1_done <= 1'b0;
        end
        else begin
            if (st_cur == ST1 && add_result_tvalid_1 == 1'b1 && add_result_tvalid_2 == 1'b1
            && ST1_done == 1'b0) begin
                ST1_done <= 1'b1;
                add_a_tvalid_1 <= 1'b0;              
                add_b_tvalid_1 <= 1'b0;   
                add_a_tvalid_2 <= 1'b0;              
                add_b_tvalid_2 <= 1'b0;

                output_real <= add_result_tdata_1;
                output_imag <= add_result_tdata_2;
            end
        end
    end

    //两个周期的高电平
    reg [1:0] complex_add_output_valid_r_count = 2'b0;
    always @(posedge clk or negedge rst) begin
        if (!rst) begin
            complex_add_output_valid_r_count <= 2'b0;
        end
        else begin
            if (complex_add_output_valid_r) begin
                complex_add_output_valid_r_count <= complex_add_output_valid_r_count + 1'b1;
                if (complex_add_output_valid_r_count == 'd2) begin
                    complex_add_output_valid_r <= 1'b0;
                    complex_add_output_valid_r_count <= 2'b0;
                end
            end
            
        end
    end
endmodule
`timescale 1ns / 1ps
//
// Company: 东北电力大学
// Engineer: Yang Zheng 
// 
// Create Date: 2022/02/09 18:06:18
// Design Name: 
// Module Name: complex_multiply_compute
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module complex_multiply_compute
#(
    DW =32//位宽
)(
    input   clk,
    input   rst,
    input   [(DW * 2)-1:0]   complex_multiply_compute_input_A,//高32位是实部,低32位是虚部
    input   [(DW * 2)-1:0]   complex_multiply_compute_input_B,//高32位是实部,低32位是虚部
    output  [(DW * 2)-1:0]   complex_multiply_compute_output,//高32位是实部,低32位是虚部

    input   complex_multiply_input_valid,//输入开始求解信号
    output  complex_multiply_output_valid,//输出求解完毕信号
    output  complex_multiply_valid_en//输出此模块可用信号
    );
    reg [(DW)-1:0]   output_real = 'd0;
    reg [(DW)-1:0]   output_imag = 'd0;
    assign complex_multiply_compute_output = {output_real,output_imag};
    reg complex_multiply_output_valid_r = 1'b0;
    reg complex_multiply_valid_en_r = 1'b1;
    assign complex_multiply_output_valid = complex_multiply_output_valid_r;
    assign complex_multiply_valid_en = complex_multiply_valid_en_r;
    //初始化输入
    reg compute_reshape = 1'b0;
    reg [(DW)-1:0]  complex_compute_a = 'd0;
    reg [(DW)-1:0]  complex_compute_b = 'd0;
    reg [(DW)-1:0]  complex_compute_c = 'd0;
    reg [(DW)-1:0]  complex_compute_d = 'd0;
    always @(posedge clk or negedge rst) begin
        if (!rst) begin
            //复位
            compute_reshape <= 1'b0;
            complex_compute_a <= 'd0;
            complex_compute_b <= 'd0;
            complex_compute_c <= 'd0;
            complex_compute_d <= 'd0;
            output_real <= 'd0;
            output_imag <= 'd0;
        end
        else if(complex_multiply_input_valid == 1'b1 && compute_reshape == 1'b0) begin
            complex_compute_a <=complex_multiply_compute_input_A[(DW * 2)-1:DW];
            complex_compute_b <=complex_multiply_compute_input_A[(DW)-1:0];
            complex_compute_c <=complex_multiply_compute_input_B[(DW * 2)-1:DW];
            complex_compute_d <=complex_multiply_compute_input_B[(DW)-1:0];

            complex_multiply_valid_en_r <= 1'b0;
            compute_reshape <= 1'b1;
        end
    end
    //例化模块
    /*例化4个乘法模块*/
    reg aresetn_multiply = 1'b0;
    always @(negedge rst) begin
        if (!rst) begin
            aresetn_multiply <= 1'b1;//2个低电平复位
        end
    end
    reg multiply_a_tvalid_1 = 1'b0;
    reg multiply_b_tvalid_1 = 1'b0;
    reg  [31:0] multiply_a_tdata_1 = 32'b0;
    reg  [31:0] multiply_b_tdata_1 = 32'b0;
    wire [31:0] multiply_result_tdata_1;
    complex_compute_multiply uut_complex_compute_multiply_1(
        .aclk(clk),
        .aresetn(aresetn_multiply),//低电平复位
        .s_axis_a_tvalid(multiply_a_tvalid_1),
        .s_axis_a_tdata(multiply_a_tdata_1),
        .s_axis_b_tvalid(multiply_b_tvalid_1),
        .s_axis_b_tdata(multiply_b_tdata_1),
        .m_axis_result_tvalid(multiply_result_tvalid_1),
        .m_axis_result_tdata(multiply_result_tdata_1)
    );

    reg multiply_a_tvalid_2 = 1'b0;
    reg multiply_b_tvalid_2 = 1'b0;
    reg  [31:0] multiply_a_tdata_2 = 32'b0;
    reg  [31:0] multiply_b_tdata_2 = 32'b0;
    wire [31:0] multiply_result_tdata_2;
    complex_compute_multiply uut_complex_compute_multiply_2(
        .aclk(clk),
        .aresetn(aresetn_multiply),//低电平复位
        .s_axis_a_tvalid(multiply_a_tvalid_2),
        .s_axis_a_tdata(multiply_a_tdata_2),
        .s_axis_b_tvalid(multiply_b_tvalid_2),
        .s_axis_b_tdata(multiply_b_tdata_2),
        .m_axis_result_tvalid(multiply_result_tvalid_2),
        .m_axis_result_tdata(multiply_result_tdata_2)
    );

    reg multiply_a_tvalid_3 = 1'b0;
    reg multiply_b_tvalid_3 = 1'b0;
    reg  [31:0] multiply_a_tdata_3 = 32'b0;
    reg  [31:0] multiply_b_tdata_3 = 32'b0;
    wire [31:0] multiply_result_tdata_3;
    complex_compute_multiply uut_complex_compute_multiply_3(
        .aclk(clk),
        .aresetn(aresetn_multiply),//低电平复位
        .s_axis_a_tvalid(multiply_a_tvalid_3),
        .s_axis_a_tdata(multiply_a_tdata_3),
        .s_axis_b_tvalid(multiply_b_tvalid_3),
        .s_axis_b_tdata(multiply_b_tdata_3),
        .m_axis_result_tvalid(multiply_result_tvalid_3),
        .m_axis_result_tdata(multiply_result_tdata_3)
    );

    reg multiply_a_tvalid_4 = 1'b0;
    reg multiply_b_tvalid_4 = 1'b0;
    reg  [31:0] multiply_a_tdata_4 = 32'b0;
    reg  [31:0] multiply_b_tdata_4 = 32'b0;
    wire [31:0] multiply_result_tdata_4;
    complex_compute_multiply uut_complex_compute_multiply_4(
        .aclk(clk),
        .aresetn(aresetn_multiply),//低电平复位
        .s_axis_a_tvalid(multiply_a_tvalid_4),
        .s_axis_a_tdata(multiply_a_tdata_4),
        .s_axis_b_tvalid(multiply_b_tvalid_4),
        .s_axis_b_tdata(multiply_b_tdata_4),
        .m_axis_result_tvalid(multiply_result_tvalid_4),
        .m_axis_result_tdata(multiply_result_tdata_4)
    );
    /*例化1个减法模块*/
    reg aresetn_subtract = 1'b0;
    always @(negedge rst) begin
        if (!rst) begin
            aresetn_subtract <= 1'b1;//2个低电平复位
        end
    end
    reg subtract_a_tvalid = 1'b0;
    reg subtract_b_tvalid = 1'b0;
    reg  [31:0] subtract_a_tdata = 32'b0;
    reg  [31:0] subtract_b_tdata = 32'b0;
    wire [31:0] subtract_result_tdata;
    complex_compute_subtract uut_complex_compute_subtract(
        .aclk(clk),
        .aresetn(aresetn_subtract),
        .s_axis_a_tvalid(subtract_a_tvalid),
        .s_axis_a_tdata(subtract_a_tdata),
        .s_axis_b_tvalid(subtract_b_tvalid),
        .s_axis_b_tdata(subtract_b_tdata),
        .m_axis_result_tvalid(subtract_result_tvalid),
        .m_axis_result_tdata(subtract_result_tdata)
    );
    /*例化1个加法模块*/
    reg aresetn_add = 1'b0;
    always @(negedge rst) begin
        if (!rst) begin
            aresetn_add <= 1'b1;//2个低电平复位
        end
    end
    reg add_a_tvalid = 1'b0;
    reg add_b_tvalid = 1'b0;
    reg  [31:0] add_a_tdata = 32'b0;
    reg  [31:0] add_b_tdata = 32'b0;
    wire [31:0] add_result_tdata;
    complex_compute_add uut_complex_compute_add(
        .aclk(clk),
        .aresetn(aresetn_add),
        .s_axis_a_tvalid(add_a_tvalid),
        .s_axis_a_tdata(add_a_tdata),
        .s_axis_b_tvalid(add_b_tvalid),
        .s_axis_b_tdata(add_b_tdata),
        .m_axis_result_tvalid(add_result_tvalid),
        .m_axis_result_tdata(add_result_tdata)
    );

    //状态机
    reg [1:0]   st_cur =  'd0;
    reg [1:0]   st_next = 'd0;
    parameter   IDLE  = 2'd0 ;
    parameter   ST1   = 2'd1 ;
    parameter   ST2   = 2'd2 ;
    always @(posedge clk or negedge rst) begin
        if (!rst) begin
            st_cur <= 'd0;
            st_next <= 'd0;
        end
        else begin
            st_cur <= st_next;
        end
    end

    reg ST1_done = 1'b0;
    reg ST2_done = 1'b0;
    reg [2:0] aresetn_count = 3'b0;

    reg ST1_do = 1'b0;
    reg ST2_do = 1'b0;
    //状态切换
    always @(posedge clk) begin
        case (st_cur)
            IDLE: 
                if (complex_multiply_input_valid == 1'b1 && compute_reshape == 1'b1) begin
                    st_next <= ST1;
                    ST1_do <= 1'b0;
                    ST2_do <= 1'b0;
                end
            ST1:
                if (ST1_done) begin
                    /*乘法器复位*/
                    aresetn_multiply <= 1'b0;
                    aresetn_count <= aresetn_count + 1'b1;
                    if (aresetn_count == 'd3) begin
                        aresetn_count <= 1'b0;
                        st_next <= ST2;
                        aresetn_multiply <= 1'b1;
                        ST1_done <= 1'b0;
                    end
                end
            ST2:
                if (ST2_done) begin
                /*加法器与减法器复位*/
                    aresetn_add <= 1'b0;
                    aresetn_subtract <= 1'b0;
                    aresetn_count <= aresetn_count + 1'b1;
                    complex_multiply_output_valid_r <= 1'b1;
                    if (aresetn_count == 'd3) begin
                        aresetn_count <= 1'b0;
                        st_next <= IDLE;
                        aresetn_add <= 1'b1;
                        aresetn_subtract <= 1'b1;
                        ST2_done <= 1'b0;
                        complex_multiply_valid_en_r <= 1'b1;
                        compute_reshape <= 1'b0;
                    end
                end
            default: st_next <= IDLE;
        endcase
    end
    reg [31:0] multiply_result [3:0];//记录乘法结果,防止乘法器复位结果被重置
    //状态过程
    always @(posedge clk or negedge rst) begin
        if (!rst) begin
            
        end
        else begin
            if (st_cur == ST1 && ST1_done == 1'b0 && ST1_do == 1'b0) begin
            //计算a*c、b*d、b*c、a*d

                multiply_a_tvalid_1 <= 1'b1;
                multiply_b_tvalid_1 <= 1'b1;
                multiply_a_tdata_1 <= complex_compute_a;
                multiply_b_tdata_1 <= complex_compute_c;
                multiply_a_tvalid_2 <= 1'b1;
                multiply_b_tvalid_2 <= 1'b1;
                multiply_a_tdata_2 <= complex_compute_b;
                multiply_b_tdata_2 <= complex_compute_d;
                multiply_a_tvalid_3 <= 1'b1;
                multiply_b_tvalid_3 <= 1'b1;
                multiply_a_tdata_3 <= complex_compute_b;
                multiply_b_tdata_3 <= complex_compute_c;
                multiply_a_tvalid_4 <= 1'b1;
                multiply_b_tvalid_4 <= 1'b1;
                multiply_a_tdata_4 <= complex_compute_a;
                multiply_b_tdata_4 <= complex_compute_d;

                ST1_do <= 1'b1;
            end
            else if(st_cur == ST2 && ST2_done == 1'b0 && ST2_do == 1'b0) begin
                //计算a*c-b*d、b*c+a*d
                

                subtract_a_tvalid <=  1'b1;
                subtract_b_tvalid <=  1'b1;
                subtract_a_tdata <=  multiply_result[0];
                subtract_b_tdata <=  multiply_result[1];

                add_a_tvalid <=  1'b1;
                add_b_tvalid <=  1'b1;
                add_a_tdata <=  multiply_result[2];
                add_b_tdata <=  multiply_result[3];

                ST2_do <= 1'b1;
            end
        end
    end
    //状态输出
    //ST1 输出
    always @(posedge clk or negedge rst) begin
        if (!rst) begin
            ST1_done <= 1'b0;
            multiply_result[0] <= 32'b0;
            multiply_result[1] <= 32'b0;
            multiply_result[2] <= 32'b0;
            multiply_result[3] <= 32'b0;
        end
        else begin
            if (st_cur == ST1 && multiply_result_tvalid_1 == 1'b1 && multiply_result_tvalid_2 == 1'b1
            && multiply_result_tvalid_3 == 1'b1 && multiply_result_tvalid_4 == 1'b1 && ST1_done == 1'b0) begin
                ST1_done <= 1'b1;
                multiply_a_tvalid_1 <= 1'b0;              
                multiply_b_tvalid_1 <= 1'b0;   
                multiply_a_tvalid_2 <= 1'b0;              
                multiply_b_tvalid_2 <= 1'b0;
                multiply_a_tvalid_3 <= 1'b0;              
                multiply_b_tvalid_3 <= 1'b0;   
                multiply_a_tvalid_4 <= 1'b0;              
                multiply_b_tvalid_4 <= 1'b0;

                {multiply_result[0],multiply_result[1],multiply_result[2],multiply_result[3]} <=
                {multiply_result_tdata_1,
                 multiply_result_tdata_2,
                 multiply_result_tdata_3,
                 multiply_result_tdata_4};
            end
        end
    end

    //ST2 输出
    always @(posedge clk or negedge rst) begin
        if (!rst) begin
            ST2_done <= 1'b0;
        end
        else begin
            if (st_cur == ST2 && add_result_tvalid == 1'b1 && subtract_result_tvalid == 1'b1
            && ST2_done == 1'b0) begin
                ST2_done <= 1'b1;
                add_a_tvalid <= 1'b0;           
                add_b_tvalid <= 1'b0;
                subtract_a_tvalid <= 1'b0;           
                subtract_b_tvalid <= 1'b0;

                output_real <= subtract_result_tdata;
                output_imag <= add_result_tdata;
            end
        end
    end

    //两个周期的高电平
    reg [1:0] complex_multiply_output_valid_r_count = 2'b0;
    always @(posedge clk or negedge rst) begin
        if (!rst) begin
            complex_multiply_output_valid_r_count <= 2'b0;
        end
        else begin
            if (complex_multiply_output_valid_r) begin
                complex_multiply_output_valid_r_count <= complex_multiply_output_valid_r_count + 1'b1;
                if (complex_multiply_output_valid_r_count == 'd2) begin
                    complex_multiply_output_valid_r <= 1'b0;
                    complex_multiply_output_valid_r_count <= 2'b0;
                end
            end
            
        end
    end
endmodule
`timescale 1ns / 1ps
//
// Company: 东北电力大学
// Engineer: Yang Zheng 
// 
// Create Date: 2022/02/09 16:40:48
// Design Name: 
// Module Name: complex_multiply_14_41
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module complex_multiply_14_41
#(
    M = 1,//矩阵变化就需要更改
    N = 4,//矩阵变化就需要更改
    DW =32//位宽
)(
    input   clk,
    input   rst,
    input   [(DW * M * N)*2-1:0]   complex_matrix_compute_input_A,//高32位是实部,低32位是虚部 1行4列 4个复数
    input   [(DW * N * M)*2-1:0]   complex_matrix_compute_input_B,//高32位是实部,低32位是虚部 4行1列 4个复数
    output  [(DW)*2-1:0]   complex_matrix_compute_output,//高32位是实部,低32位是虚部

    input   complex_matrix_multiply_input_valid,//输入开始求解信号
    output  complex_matrix_multiply_output_valid,//输出求解完毕信号
    output  complex_matrix_multiply_valid_en//输出此模块可用信号
    );

    reg [(DW)*2-1:0]   complex_matrix_compute_output_r = 'd0;
    assign complex_matrix_compute_output = complex_matrix_compute_output_r;

    reg complex_matrix_multiply_output_valid_r = 1'b0;
    reg complex_matrix_multiply_valid_en_r = 1'b1;
    assign complex_matrix_multiply_output_valid = complex_matrix_multiply_output_valid_r;
    assign complex_matrix_multiply_valid_en = complex_matrix_multiply_valid_en_r;

    //初始化输入
    reg compute_reshape = 1'b0;
    reg [(DW)*2-1:0]  complex_compute_a1 = 'd0;
    reg [(DW)*2-1:0]  complex_compute_a2 = 'd0;
    reg [(DW)*2-1:0]  complex_compute_a3 = 'd0;
    reg [(DW)*2-1:0]  complex_compute_a4 = 'd0;

    reg [(DW)*2-1:0]  complex_compute_b1 = 'd0;
    reg [(DW)*2-1:0]  complex_compute_b2 = 'd0;
    reg [(DW)*2-1:0]  complex_compute_b3 = 'd0;
    reg [(DW)*2-1:0]  complex_compute_b4 = 'd0;
    always @(posedge clk or negedge rst) begin
        if (!rst) begin
            //复位
            compute_reshape <= 1'b0;
            complex_compute_a1 <= 'd0;
            complex_compute_a2 <= 'd0;
            complex_compute_a3 <= 'd0;
            complex_compute_a4 <= 'd0;
            complex_compute_b1 <= 'd0;
            complex_compute_b2 <= 'd0;
            complex_compute_b3 <= 'd0;
            complex_compute_b4 <= 'd0;
            complex_matrix_compute_output_r <= 'd0;
        end
        else if(complex_matrix_multiply_input_valid == 1'b1 && compute_reshape == 1'b0) begin
            complex_compute_a1 <= complex_matrix_compute_input_A[(DW * 8)-1:(DW * 6)];
            complex_compute_a2 <= complex_matrix_compute_input_A[(DW * 6)-1:(DW * 4)];
            complex_compute_a3 <= complex_matrix_compute_input_A[(DW * 4)-1:(DW * 2)];
            complex_compute_a4 <= complex_matrix_compute_input_A[(DW * 2)-1:(DW * 0)];
            complex_compute_b1 <= complex_matrix_compute_input_B[(DW * 8)-1:(DW * 6)];
            complex_compute_b2 <= complex_matrix_compute_input_B[(DW * 6)-1:(DW * 4)];
            complex_compute_b3 <= complex_matrix_compute_input_B[(DW * 4)-1:(DW * 2)];
            complex_compute_b4 <= complex_matrix_compute_input_B[(DW * 2)-1:(DW * 0)];

            complex_matrix_multiply_valid_en_r <= 1'b0;
            compute_reshape <= 1'b1;
        end
    end

    //例化模块
    /*例化2个复数加法模块*/
    reg [63:0] complex_add_compute_input_A_1;
    reg [63:0] complex_add_compute_input_B_1;
    reg complex_add_input_valid_1;
    wire [63:0] complex_add_compute_output_1;
    complex_add_compute uut_complex_add_compute_1(
        .clk(clk),
        .rst(rst),
        .complex_add_compute_input_A(complex_add_compute_input_A_1),//高32位是实部,低32位是虚部
        .complex_add_compute_input_B(complex_add_compute_input_B_1),//高32位是实部,低32位是虚部
        .complex_add_compute_output(complex_add_compute_output_1),//高32位是实部,低32位是虚部
        .complex_add_input_valid(complex_add_input_valid_1),//输入开始求解信号
        .complex_add_output_valid(complex_add_output_valid_1),//输出求解完毕信号
        .complex_add_valid_en(complex_add_valid_en_1)//输出此模块可用信号
    );

    reg [63:0] complex_add_compute_input_A_2;
    reg [63:0] complex_add_compute_input_B_2;
    reg complex_add_input_valid_2;
    wire [63:0] complex_add_compute_output_2;
    complex_add_compute uut_complex_add_compute_2(
        .clk(clk),
        .rst(rst),
        .complex_add_compute_input_A(complex_add_compute_input_A_2),//高32位是实部,低32位是虚部
        .complex_add_compute_input_B(complex_add_compute_input_B_2),//高32位是实部,低32位是虚部
        .complex_add_compute_output(complex_add_compute_output_2),//高32位是实部,低32位是虚部
        .complex_add_input_valid(complex_add_input_valid_2),//输入开始求解信号
        .complex_add_output_valid(complex_add_output_valid_2),//输出求解完毕信号
        .complex_add_valid_en(complex_add_valid_en_2)//输出此模块可用信号
    );
    /*例化4个复数乘法器*/
    reg [63:0] complex_multiply_compute_input_A_1;
    reg [63:0] complex_multiply_compute_input_B_1;
    reg complex_multiply_input_valid_1;
    wire [63:0] complex_multiply_compute_output_1;
    complex_multiply_compute uut_complex_multiply_compute_1(
        .clk(clk),
        .rst(rst),
        .complex_multiply_compute_input_A(complex_multiply_compute_input_A_1),//高32位是实部,低32位是虚部
        .complex_multiply_compute_input_B(complex_multiply_compute_input_B_1),//高32位是实部,低32位是虚部
        .complex_multiply_compute_output(complex_multiply_compute_output_1),//高32位是实部,低32位是虚部
        .complex_multiply_input_valid(complex_multiply_input_valid_1),//输入开始求解信号
        .complex_multiply_output_valid(complex_multiply_output_valid_1),//输出求解完毕信号
        .complex_multiply_valid_en(complex_multiply_valid_en_1)//输出此模块可用信号
    );

    reg [63:0] complex_multiply_compute_input_A_2;
    reg [63:0] complex_multiply_compute_input_B_2;
    reg complex_multiply_input_valid_2;
    wire [63:0] complex_multiply_compute_output_2;
    complex_multiply_compute uut_complex_multiply_compute_2(
        .clk(clk),
        .rst(rst),
        .complex_multiply_compute_input_A(complex_multiply_compute_input_A_2),//高32位是实部,低32位是虚部
        .complex_multiply_compute_input_B(complex_multiply_compute_input_B_2),//高32位是实部,低32位是虚部
        .complex_multiply_compute_output(complex_multiply_compute_output_2),//高32位是实部,低32位是虚部
        .complex_multiply_input_valid(complex_multiply_input_valid_2),//输入开始求解信号
        .complex_multiply_output_valid(complex_multiply_output_valid_2),//输出求解完毕信号
        .complex_multiply_valid_en(complex_multiply_valid_en_2)//输出此模块可用信号
    );

    reg [63:0] complex_multiply_compute_input_A_3;
    reg [63:0] complex_multiply_compute_input_B_3;
    reg complex_multiply_input_valid_3;
    wire [63:0] complex_multiply_compute_output_3;
    complex_multiply_compute uut_complex_multiply_compute_3(
        .clk(clk),
        .rst(rst),
        .complex_multiply_compute_input_A(complex_multiply_compute_input_A_3),//高32位是实部,低32位是虚部
        .complex_multiply_compute_input_B(complex_multiply_compute_input_B_3),//高32位是实部,低32位是虚部
        .complex_multiply_compute_output(complex_multiply_compute_output_3),//高32位是实部,低32位是虚部
        .complex_multiply_input_valid(complex_multiply_input_valid_3),//输入开始求解信号
        .complex_multiply_output_valid(complex_multiply_output_valid_3),//输出求解完毕信号
        .complex_multiply_valid_en(complex_multiply_valid_en_3)//输出此模块可用信号
    );

    reg [63:0] complex_multiply_compute_input_A_4;
    reg [63:0] complex_multiply_compute_input_B_4;
    reg complex_multiply_input_valid_4;
    wire [63:0] complex_multiply_compute_output_4;
    complex_multiply_compute uut_complex_multiply_compute_4(
        .clk(clk),
        .rst(rst),
        .complex_multiply_compute_input_A(complex_multiply_compute_input_A_4),//高32位是实部,低32位是虚部
        .complex_multiply_compute_input_B(complex_multiply_compute_input_B_4),//高32位是实部,低32位是虚部
        .complex_multiply_compute_output(complex_multiply_compute_output_4),//高32位是实部,低32位是虚部
        .complex_multiply_input_valid(complex_multiply_input_valid_4),//输入开始求解信号
        .complex_multiply_output_valid(complex_multiply_output_valid_4),//输出求解完毕信号
        .complex_multiply_valid_en(complex_multiply_valid_en_4)//输出此模块可用信号
    );

    //状态机
    reg [1:0]   st_cur =  'd0;
    reg [1:0]   st_next = 'd0;
    parameter   IDLE  = 2'd0 ;
    parameter   ST1   = 2'd1 ;
    parameter   ST2   = 2'd2 ;
    parameter   ST3   = 2'd3 ;
    always @(posedge clk or negedge rst) begin
        if (!rst) begin
            st_cur <= 'd0;
            st_next <= 'd0;
        end
        else begin
            st_cur <= st_next;
        end
    end

    reg ST1_done = 1'b0;
    reg ST2_done = 1'b0;
    reg ST3_done = 1'b0;
    reg [2:0] aresetn_count = 3'b0;

    reg ST1_do = 1'b0;
    reg ST2_do = 1'b0;
    reg ST3_do = 1'b0;

    //状态切换
    always @(posedge clk) begin
        case (st_cur)
            IDLE: 
                if (complex_matrix_multiply_input_valid == 1'b1 && compute_reshape == 1'b1) begin
                    st_next <= ST1;
                    ST1_do <= 1'b0;
                    ST2_do <= 1'b0;
                    ST3_do <= 1'b0;
                    ST1_done <= 1'b0;
                    ST2_done <= 1'b0;
                    ST3_done <= 1'b0;
                end
            ST1:
                if (ST1_done) begin
                    /*乘法器复位*/
                    
                    if (complex_multiply_valid_en_1 == 1'b1 && complex_multiply_valid_en_2 == 1'b1
                        && complex_multiply_valid_en_3 == 1'b1 && complex_multiply_valid_en_4 == 1'b1) begin
                        
                        st_next <= ST2;
                    end
                end
            ST2:
                if (ST2_done) begin
                /*加法器复位*/
                    if (complex_add_valid_en_1 == 1'b1 && complex_add_valid_en_2 == 1'b1) begin
                        st_next <= ST3;
                    end
                end
            ST3:
                if (ST3_done) begin
                /*加法器复位*/
                    complex_matrix_multiply_output_valid_r <= 1'b1;
                    if (complex_add_valid_en_1 == 1'b1) begin
                        st_next <= IDLE;
                        complex_matrix_multiply_valid_en_r <= 1'b1;
                        compute_reshape <= 1'b0;
                    end
                end
            default: st_next <= IDLE;
        endcase
    end
    reg [63:0] multiply_result [3:0];//记录乘法结果,防止乘法器复位结果被重置
    reg [63:0] add_result [1:0];//记录乘法结果,防止加法器复位结果被重置
    //状态过程
    always @(posedge clk or negedge rst) begin
        if (!rst) begin
            
        end
        else begin
            if (st_cur == ST1 && ST1_done == 1'b0 && ST1_do == 1'b0 
            && complex_multiply_valid_en_1 == 1'b1 && complex_multiply_valid_en_2 == 1'b1
            && complex_multiply_valid_en_3 == 1'b1 && complex_multiply_valid_en_4 == 1'b1) begin
            //计算a1*b1、a2*b2、a3*b3、a4*b4

                complex_multiply_input_valid_1 <= 1'b1;
                complex_multiply_compute_input_A_1 <= complex_compute_a1;
                complex_multiply_compute_input_B_1 <= complex_compute_b1;
                complex_multiply_input_valid_2 <= 1'b1;
                complex_multiply_compute_input_A_2 <= complex_compute_a2;
                complex_multiply_compute_input_B_2 <= complex_compute_b2;
                complex_multiply_input_valid_3 <= 1'b1;
                complex_multiply_compute_input_A_3 <= complex_compute_a3;
                complex_multiply_compute_input_B_3 <= complex_compute_b3;
                complex_multiply_input_valid_4 <= 1'b1;
                complex_multiply_compute_input_A_4 <= complex_compute_a4;
                complex_multiply_compute_input_B_4 <= complex_compute_b4;

                ST1_do <= 1'b1;
            end
            else if(st_cur == ST2 && ST2_done == 1'b0 && ST2_do == 1'b0
            && complex_add_valid_en_1 == 1'b1 && complex_add_valid_en_2 == 1'b1) begin
                //计算a1*b1+a2*b2、a3*b3+a4*b4

                complex_add_input_valid_1 <= 1'b1;
                complex_add_compute_input_A_1 <= multiply_result[0];
                complex_add_compute_input_B_1 <= multiply_result[1];
                complex_add_input_valid_2 <= 1'b1;
                complex_add_compute_input_A_2 <= multiply_result[2];
                complex_add_compute_input_B_2 <= multiply_result[3];

                ST2_do <= 1'b1;
            end
            else if(st_cur == ST3 && ST3_done == 1'b0 && ST3_do == 1'b0
            && complex_add_valid_en_1 == 1'b1) begin
                //计算a1*b1+a2*b2+a3*b3+a4*b4

                complex_add_input_valid_1 <= 1'b1;
                complex_add_compute_input_A_1 <= add_result[0];
                complex_add_compute_input_B_1 <= add_result[1];

                ST3_do <= 1'b1;
            end
        end
    end
    //状态输出
    //ST1 输出
    always @(posedge clk or negedge rst) begin
        if (!rst) begin
            ST1_done <= 1'b0;
            multiply_result[0] <= 32'b0;
            multiply_result[1] <= 32'b0;
            multiply_result[2] <= 32'b0;
            multiply_result[3] <= 32'b0;
        end
        else begin
            if (st_cur == ST1 && complex_multiply_output_valid_1 == 1'b1 && complex_multiply_output_valid_2 == 1'b1
            && complex_multiply_output_valid_3 == 1'b1 && complex_multiply_output_valid_4 == 1'b1 && ST1_done == 1'b0) begin
                ST1_done <= 1'b1;
                complex_multiply_input_valid_1 <= 1'b0;              
                complex_multiply_input_valid_2 <= 1'b0;   
                complex_multiply_input_valid_3 <= 1'b0;              
                complex_multiply_input_valid_4 <= 1'b0;

                {multiply_result[0],multiply_result[1],multiply_result[2],multiply_result[3]} <=
                {complex_multiply_compute_output_1,
                 complex_multiply_compute_output_2,
                 complex_multiply_compute_output_3,
                 complex_multiply_compute_output_4};
            end
        end
    end

    //ST2 输出
    always @(posedge clk or negedge rst) begin
        if (!rst) begin
            ST2_done <= 1'b0;
            add_result[0] <= 32'b0;
            add_result[1] <= 32'b0;
        end
        else begin
            if (st_cur == ST2 && complex_add_output_valid_1 == 1'b1 && complex_add_output_valid_2 == 1'b1
            && ST2_done == 1'b0) begin
                ST2_done <= 1'b1;
                complex_add_input_valid_1 <= 1'b0;           
                complex_add_input_valid_2 <= 1'b0;
      
                {add_result[0],add_result[1]} <=
                {complex_add_compute_output_1,
                 complex_add_compute_output_2};
            end
        end
    end

    //ST3 输出
    always @(posedge clk or negedge rst) begin
        if (!rst) begin
            ST3_done <= 1'b0;
        end
        else begin
            if (st_cur == ST3 && complex_add_output_valid_1 == 1'b1 
            && ST3_done == 1'b0) begin
                ST3_done <= 1'b1;
                complex_add_input_valid_1 <= 1'b0;

                complex_matrix_compute_output_r <= complex_add_compute_output_1;
            end
        end
    end

    //两个周期的高电平
    reg [1:0] complex_multiply_output_valid_r_count = 2'b0;
    always @(posedge clk or negedge rst) begin
        if (!rst) begin
            complex_multiply_output_valid_r_count <= 2'b0;
        end
        else begin
            if (complex_matrix_multiply_output_valid_r) begin
                complex_multiply_output_valid_r_count <= complex_multiply_output_valid_r_count + 1'b1;
                if (complex_multiply_output_valid_r_count == 'd2) begin
                    complex_matrix_multiply_output_valid_r <= 1'b0;
                    complex_multiply_output_valid_r_count <= 2'b0;
                end
            end
            
        end
    end
endmodule

④testbench

`timescale 1ns / 1ps
//
// Company: 东北电力大学
// Engineer: Yang Zheng
// 
// Create Date: 2022/02/09 20:43:08
// Design Name: 
// Module Name: testbench
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module testbench(

    );
    reg clk;
    reg rst;
    
    always #5 clk =~ clk;
    initial begin
        clk = 1'b0;
        rst = 1'b0;
        #100;
        rst = 1'b1;
    end
    reg [63:0] complex_multiply_compute_input_A;
    reg [63:0] complex_multiply_compute_input_B;
    reg complex_multiply_input_valid;
    wire [63:0] complex_multiply_compute_output;
    complex_multiply_compute uut_complex_multiply_compute(
        .clk(clk),
        .rst(rst),
        .complex_multiply_compute_input_A(complex_multiply_compute_input_A),//高32位是实部,低32位是虚部
        .complex_multiply_compute_input_B(complex_multiply_compute_input_B),//高32位是实部,低32位是虚部
        .complex_multiply_compute_output(complex_multiply_compute_output),//高32位是实部,低32位是虚部
        .complex_multiply_input_valid(complex_multiply_input_valid),//输入开始求解信号
        .complex_multiply_output_valid(complex_multiply_output_valid),//输出求解完毕信号
        .complex_multiply_valid_en(complex_multiply_valid_en)//输出此模块可用信号
    );
    always @(posedge clk or negedge rst) begin
        if (!rst) begin
            //复位
        end
        else begin
        /*
        >> (2.6+7.5i)*(6.4-3.8i)

        ans =

        1.8056e+02 + 1.5248e+02i  (42348f5c+42187ae2i)

        >> 
        */
            if (complex_multiply_valid_en) begin
                complex_multiply_compute_input_A <= {32'h40266666,32'h40f00000};
                complex_multiply_compute_input_B <= {32'h40cccccd,32'hc0733333};
                complex_multiply_input_valid <= 1'b1;
            end
        end
    end

    reg [63:0] complex_add_compute_input_A;
    reg [63:0] complex_add_compute_input_B;
    reg complex_add_input_valid;
    wire [63:0] complex_add_compute_output;
    complex_add_compute uut_complex_add_compute(
        .clk(clk),
        .rst(rst),
        .complex_add_compute_input_A(complex_add_compute_input_A),//高32位是实部,低32位是虚部
        .complex_add_compute_input_B(complex_add_compute_input_B),//高32位是实部,低32位是虚部
        .complex_add_compute_output(complex_add_compute_output),//高32位是实部,低32位是虚部
        .complex_add_input_valid(complex_add_input_valid),//输入开始求解信号
        .complex_add_output_valid(complex_add_output_valid),//输出求解完毕信号
        .complex_add_valid_en(complex_add_valid_en)//输出此模块可用信号
    );
    always @(posedge clk or negedge rst) begin
        if (!rst) begin
            //复位
        end
        else begin
        
        /*>> (2.6+7.5i)+(6.4-3.8i) 

        ans =

        9.0000 + 3.7000i  (41100000+406ccccdi)
        */
            if (complex_add_valid_en) begin
                complex_add_compute_input_A <= {32'h40266666,32'h40f00000};
                complex_add_compute_input_B <= {32'h40cccccd,32'hc0733333};
                complex_add_input_valid <= 1'b1;
            end
        end
    end

    reg [32*4*2-1:0] complex_matrix_compute_input_A;
    reg [32*4*2-1:0] complex_matrix_compute_input_B;
    reg complex_matrix_multiply_input_valid;
    wire [63:0] complex_matrix_compute_output;
    complex_multiply_14_41 uut_complex_multiply_14_41(
        .clk(clk),
        .rst(rst),
        .complex_matrix_compute_input_A(complex_matrix_compute_input_A),//高32位是实部,低32位是虚部
        .complex_matrix_compute_input_B(complex_matrix_compute_input_B),//高32位是实部,低32位是虚部
        .complex_matrix_compute_output(complex_matrix_compute_output),//高32位是实部,低32位是虚部
        .complex_matrix_multiply_input_valid(complex_matrix_multiply_input_valid),//输入开始求解信号
        .complex_matrix_multiply_output_valid(complex_matrix_multiply_output_valid),//输出求解完毕信号
        .complex_matrix_multiply_valid_en(complex_matrix_multiply_valid_en)//输出此模块可用信号
    );
    always @(posedge clk or negedge rst) begin
        if (!rst) begin
            //复位
        end
        else begin
        /*
        >> (2.6+7.5i)*(6.4-3.8i)*4

        ans =

        1.8056e+02 + 1.5248e+02i  (43348f5c+43187ae2i)

        >> 
        */
            if (complex_matrix_multiply_valid_en) begin
                complex_matrix_compute_input_A <= {32'h40266666,32'h40f00000,32'h40266666,32'h40f00000,32'h40266666,32'h40f00000,32'h40266666,32'h40f00000};
                complex_matrix_compute_input_B <= {32'h40cccccd,32'hc0733333,32'h40cccccd,32'hc0733333,32'h40cccccd,32'hc0733333,32'h40cccccd,32'hc0733333};
                complex_matrix_multiply_input_valid <= 1'b1;
            end
        end
    end
endmodule

⑤结果

3、声明

代码全部由东北电力大学Yang Zheng亲自开发验证,开源也用于大家学习用途,版权归本人所有,转载时请注明出处,请不要用于任何商业用途!

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

发光的沙子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值