2021-05-05 cannon矩阵乘法 verilog设计

矩阵乘法设计

0 实验目的

以Verilog设计硬件4x4矩阵乘法器。可选用:
Cannon乘法、Fox乘法、Systolic乘法、DNS乘法等任何算法。
module Matrix4x4(input clk, input A[3:0][3:0][7:0], input B[3:0][3:0][7:0], output S[3:0][3:0][7:0]);
进一步讨论以硬件方式计算NxN矩阵乘法器设计。可先以软件模拟(以调用4x4矩阵计算函数,计算NxN矩阵)。也可认为相当于增加一条复杂指令。利用ISE进行仿真,并提交ISE工程。

1 实验原理

Cannon算法
在这里插入图片描述

verilog实现4x4乘法,采用4个运算单元并行计算,每个单元计算2x2的矩阵,移入操作采用状态机实现,因为对于4个运算单元,仅有1次初值赋值与一次逻辑移动,因此不必用循环移位器,可以直接修改第二次计算的输入值。

由于verilog不支持输入数组范围作为参数,因此将数组打包为1维(其他解决方法不清楚)

2 实验内容

代码如下:

2x2乘法器:

module Mat2x2(A,B,S);

input [31:0]A;
input [31:0]B;
output wire [31:0]S;

assign S[7:0]= A[7:0]* B[7:0] +  A[15:8]* B[23:16];
assign S[15:8]=A[7:0]* B[15:8] +  A[15:8]* B[31:24];
assign S[23:16]= A[23:16]* B[7:0] +  A[31:24]* B[23:16];
assign S[31:24]= A[23:16]* B[15:8] +  A[31:24]* B[31:24];

endmodule

4x4 cannon 乘法器

module Matrix4x4( clk,  A, B,  S);
input clk;

input [7:0] A[0:3][0:3];
input [7:0] B[0:3][0:3];
reg [127:0]tempA;
reg [127:0]tempB;
reg [127:0]tempS;
reg [127:0]result = 0;
reg [31:0]clkdiv = 0;
reg [3:0]State = 0;
output reg [7:0] S[0:3][0:3];
integer i = 0;
integer j = 0;
// 4 x 2x2 matrix multiplier
Mat2x2 m1(tempA[31:0] ,tempB[31:0] ,tempS[31:0] );
Mat2x2 m2(tempA[63:32], tempB[63:32] ,tempS[63:32]);
Mat2x2 m3(tempA[95:64], tempB[95:64] ,tempS[95:64]);
Mat2x2 m4(tempA[127:96],tempB[127:96],tempS[127:96]);
// clock divider
always@(posedge clk)begin
    clkdiv <= 1'b1 + clkdiv;
end
always@(posedge clkdiv[2])begin
    case(State)
        0: begin 
        //initial
                tempB[31:0] <= {B[1][1],B[1][0],B[0][1],B[0][0]}    ;
                tempB[63:32] <={B[1][3],B[1][2],B[0][3],B[0][2]}   ;
                tempB[95:64] <= {B[1][1],B[1][0],B[0][1],B[0][0]} ; 
                tempB[127:96] <={B[1][3],B[1][2],B[0][3],B[0][2]}    ;
                tempA[31:0] <= {A[1][1],A[1][0],A[0][1],A[0][0]};
                tempA[63:32] <= {A[1][1],A[1][0],A[0][1],A[0][0]};  
                tempA[95:64] <= {A[3][1],A[3][0],A[2][1],A[2][0]};
                tempA[127:96]<=  {A[3][1],A[3][0],A[2][1],A[2][0]};
                State <= State + 1;
        end
        // 第一项加入 因为单个元素只有8位,因此不能直接128位一起加,而要8位8位的加
        1: begin
            result[7:0]     <= result [7:0]     + tempS[7:0]     ;
            result[15:8]    <= result [15:8]    + tempS[15:8]    ;
            result[23:16]   <= result [23:16]   + tempS[23:16]   ;
            result[31:24]   <= result [31:24]   + tempS[31:24]   ;
            result[39:32]   <= result [39:32]   + tempS[39:32]   ;
            result[47:40]    <=result [47:40]   + tempS[47:40]   ;
            result[55:48]   <= result [55:48]   + tempS[55:48]   ;
            result[63:56]   <= result [63:56]   + tempS[63:56]   ;
            result[71:64]   <= result [71:64]   + tempS[71:64]   ;
            result[79:72]    <=result [79:72]   + tempS[79:72]   ;
            result[87:80]   <= result [87:80]   + tempS[87:80]   ;
            result[95:88]   <= result [95:88]   + tempS[95:88]   ;
            result[103:96]   <=result [103:96]  + tempS[103:96]  ;
            result[111:104] <= result [111:104] + tempS[111:104] ;
            result[119:112] <= result [119:112] + tempS[119:112] ;
            result[127:120] <= result [127:120] + tempS[127:120] ;


            State <= State + 1;
        end
        // shift 1 block 2x2块移位通过直接写对应索引得到
        2: begin
            tempB[31:0] <= {B[3][1],B[3][0],B[2][1],B[2][0]};
            tempB[63:32] <= {B[3][3],B[3][2],B[2][3],B[2][2]};
            tempB[95:64] <= {B[3][1],B[3][0],B[2][1],B[2][0]};
            tempB[127:96] <=  {B[3][3],B[3][2],B[2][3],B[2][2]};
            tempA[31:0] <= {A[1][3],A[1][2],A[0][3],A[0][2]};
            tempA[63:32] <= {A[1][3],A[1][2],A[0][3],A[0][2]};
            tempA[95:64] <={A[3][3],A[3][2],A[2][3],A[2][2]};
            tempA[127:96]<=  {A[3][3],A[3][2],A[2][3],A[2][2]};
            State <= State +1;
        end
        3: begin
			// 第二项加入
            result[7:0]     <= result [7:0]     + tempS[7:0]     ;
            result[15:8]    <= result [15:8]    + tempS[15:8]    ;
            result[23:16]   <= result [23:16]   + tempS[23:16]   ;
            result[31:24]   <= result [31:24]   + tempS[31:24]   ;
            result[39:32]   <= result [39:32]   + tempS[39:32]   ;
            result[47:40]    <=result [47:40]   + tempS[47:40]   ;
            result[55:48]   <= result [55:48]   + tempS[55:48]   ;
            result[63:56]   <= result [63:56]   + tempS[63:56]   ;
            result[71:64]   <= result [71:64]   + tempS[71:64]   ;
            result[79:72]    <=result [79:72]   + tempS[79:72]   ;
            result[87:80]   <= result [87:80]   + tempS[87:80]   ;
            result[95:88]   <= result [95:88]   + tempS[95:88]   ;
            result[103:96]   <=result [103:96]  + tempS[103:96]  ;
            result[111:104] <= result [111:104] + tempS[111:104] ;
            result[119:112] <= result [119:112] + tempS[119:112] ;
            result[127:120] <= result [127:120] + tempS[127:120] ;
            State <= State +1;
        end
        4: begin
            //result 移位输入到S寄存器中
            for(i = 0;i<2;i=i+1)begin
                for(j=0;j<2;j=j+1)begin
                    #5
                    S[i*2+0][j*2+0] <= result[7:0];
                    S[i*2+0][j*2+1] <= result[15:8];
                    S[i*2+1][j*2+0] <= result[23:16];
                    S[i*2+1][j*2+1] <= result[31:24];
                    #5 result <= (result>>32);
                end
            end
            State<=State+1;
        end
        
        endcase
end

endmodule

3 实验结果

4x4 cannon:

结果正确
在这里插入图片描述

4 总结与讨论

NxN乘法器?

NxN乘法器可以参照4x4用2x2的乘法器拓展得到,每次拓展一倍可采用相似构造。即8x8用4个4x4实现,其中4x4由4个2x2实现。而由于乘法分块的性质,对于非2的整数次幂尺寸的矩阵,可以在输入的多余位补零,结果取相应尺寸即可。

这样的优点是节约了硬件资源,去除了移位器的实现,不用存储输入到寄存器,同时也具有模块化的简便性。

但是对于实验中给出的接口,考虑到verilog对数组的实现不是很支持,system verilog也仅是支持输入参数,但不支持范围索引,因此采用之前打包为一维数组的方式来存储矩阵会使得接口通用性更高,便于拓展。

如果对于除了2x2的每一层都采用cannon算法,对于我的实现,每一层需要4个时钟周期(4个状态),因此对于nxn矩阵,时间复杂度大概为 O ( 4 log ⁡ n ) O(4\log n) O(4logn)。而对软件实现的nxn方阵乘法,则需要 O ( n 3 ) O(n^3) O(n3)的复杂度,显然是巨大的飞跃。而同时cannon算法也减少了存储的花费,对于单个计算单元,不用额外存储其他计算单元的输入,只需每次传入不同的值即可,可以通过寄存器+状态机实现。

示例:对于

A =

1 2 9 1 2
3 4 0 3 3
5 6 7 2 2
7 8 1 2 4
2 2 9 8 1

B=

1 2 3 2 9
3 4 3 4 3
1 6 0 0 4
0 4 3 4 1
2 9 8 6 3

A*B =

在这里插入图片描述

拓展到8x8 cannon乘法器,包含4个4x4cannon乘法器,而4x4cannon乘法器由包含2x2传统乘法器:

A =

1 2 9 1 2 0 0 0
3 4 0 3 3 0 0 0
5 6 7 2 2 0 0 0
7 8 1 2 4 0 0 0
2 2 9 8 1 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0

B=

1 2 3 2 9 0 0 0
3 4 3 4 3 0 0 0
1 6 0 0 4 0 0 0
0 4 3 4 1 0 0 0
2 9 8 6 3 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0

A*B =

在这里插入图片描述

  • 7
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值