【IC设计】基于Verilog的8层矩阵乘法设计

该文描述了一个Verilog项目,用于实现16x16矩阵乘法并进行低位截断和高位饱和处理,适用于深度学习中的多层感知机计算。文章详细阐述了矩阵元素的格式、截断规则以及实现过程,包括读取矩阵数据、实例化乘法模块和处理截断操作。

项目要求

基本要求

输入有9个矩阵,权重矩阵有8个,分别是Weight I0~I7,Input矩阵I -1
8个矩阵都是都是16行*16列的,且矩阵中的每个元素是16位补码形式的有符号定点数(1位符号位,6位整数位,9位小数位)
在这里插入图片描述
要求将Weight I0依次乘以Input I-1 ,Weight I1 ,Weight I2 ,Weight I3 ,Weight I4, Weight I5, Weight I6 , Weight I7,依次得到Input I0 ,Input I1 ,Input I2 ,Input I3 ,Input I4 ,Input I5 ,Input I6 ,Input I7
最终输出Input I7

截断要求

对于矩阵AB=C,C矩阵的第i行第j列元素是A的第i行和B的第j列进行乘加运算得到的,
由于矩阵的元素是16位,两个16位元素相乘结果需要用2
16-1=31位表示,再考虑相加,因此需要31+4=35位来表示。
在这个项目中不考虑相加后会超过31位的情况,只用31位表示。
对于Weight I0 * Input I-1=Input I0,Input I0中的每个元素都是31位的,有1位符号位,18位小数,12位整数,要求截断为16位再作为下一层的输入。
在这里插入图片描述
A[15:0]*B[15:0]=C_31[30:0] 要将C_31[30:0]转为C_16[15:0]需要考虑低位截断高位饱和操作:

低位截断

低位C_31[8:0]截断,要考虑C_31[8]的四舍五入,
如果符号位为0,则向前进1,
如果符号位为1,直接截断。
这个操作的正确性证明如下:
在这里插入图片描述

高位饱和

C[15:9]能表示的范围在[-64:63],如果C_31[30:24]超过该范围,产生上/下溢,C_16[14:9]则取能表示的最大/最小值
如果符号位为0,C_31[29:24]存在1则上溢,
如果符号位为1,C_31[29:24]存在0则下溢。

参考结果

这里给出第一层和最后一层(第八层)的输出作为参考,需要注意的是矩阵AB和BA结果是不同的,这里第一层的结果是Weight I0在左边乘以Input -1 ,得到的Input 0
在这里插入图片描述
在这里插入图片描述

项目实现

实现思路

如图所示,其中标记绿色的是调用$readmemh从文件中直接读取的,项目实现思路如下:

  1. 首先,使用$readmemh从文件中读取
    Weight I0,Input I-1 ,Weight I1 ,Weight I2 ,Weight I3 ,Weight I4, Weight I5, Weight I6 , Weight I7
    存储到对应的二维数组中,然后将这些二维数组转为一维数组(因为Verilog模块的端口不能使用多维数组)。

  2. 接着,实例化第一个16*16的模块matrix_multiplier_16,输入I_16_1d和W0_2d,得到相乘的结果I0_31_1d,将其转为二维矩阵I0_31_2d,然后按照截断要求转为I0_16_2d

  3. 下面,反复实例化matrix_multiplier_16,每次将上一层计算结果和对应的Weight矩阵作为输入,得到相乘的结果,最终结果是第八层的输出I7_16_2d。

在这里插入图片描述

实现代码

matrix_multiplier_16.v
`timescale 1ns / 1ps
//输入端口A矩阵,B矩阵是16行16列,每个元素16位有符号定点数(1位符号位,6位整数位,9位小数位)
//输出端口Result矩阵是A*B的结果,是16行16列,每个元素是31位有符号定点数(1位符号位,12位整数位,18位小数位)
//Verilog模块的端口只能是一维数组,所以每次调用该模块要保证输入的矩阵已经被转化成了一维长数组
module matrix_multiplier_16(A,B,Result);
       input  [16*16*16-1:0] A;
       input  [16*16*16-1:0] B;
       output   [16*16*31-1:0] Result;
       
       reg  [16*16*31-1:0] reg_result;
       reg signed [15:0] A1[0:15][0:15];
       reg signed [15:0] B1[0:15][0:15];
       reg signed [30:0] Res1[0:15][0:15];

       integer i,j,k;
       
       always@(A or B) begin
         //在模块内将一维转二维,方便计算
         for(i=0;i<16;i=i+1) begin
             for(j=0;j<16;j=j+1) begin
                 A1[i][j]=A[i*16*16+j*16+:16];
                 B1[i][j]=B[i*16*16+j*16+:16];
             end
         end
         
         //初始化结果为0
         for(i=0;i<16;i=i+1) begin
             for(j=0;j<16;j=j+1) begin
                 Res1[i][j]=31'd0;
             end
         end
         
         //使用矩阵相乘的定义计算Res1矩阵的结果
         //Res1[i][j]是A的第i行和B的第j列相乘再相加的结果
         for(i=0;i<16;i=i+1)begin
    		 for(j=0;j<16;j=j+1)begin
	   		   for(k=0;k<16;k=k+1)begin
	   		        //A1[i][k]和B1[k][j]都是补码形式的有符号定点数
	   		        //A[补码]*B[补码]=(A*B)[补码] 
	   		        Res1[i][j]=Res1[i][j]+A1[i][k]*B1[k][j];
			   end
			 end
		 end
		 
		 //将二维转回一维,将Res1[0][0]存储在reg_result的最高位,Res[i][j]前面有i*16+j个数据,每个31位,因此转为1维的索引是
		 //16*16*31-1-(i*16+j)*31
		 //这里涉及到一个语法:A[7:3]和A[7-:4]是等价的 同理A[0+:3]和A[0:2]等价
		 for(i=0;i<16;i=i+1)begin
		     for(j=0;j<16;j=j+1)begin
		         //When 2d converted to 1d,it is stored from high bit to low bit.
		         reg_result[16*16*31-1-((i*16+j)*31) -: 31]=Res1[i][j];
		     end
		 end
		 
       end
       assign Result=reg_result;
      
endmodule

tb_mm_mlp.v

命名为tb_mm_mlp是因为mm是matrix multiplier,mlp是多层感知机,深度学习中多层感知机的计算实际上就是矩阵乘法加激活函数。

`timescale 1ns/1ps
`define FILE_INPUT 1
`define PRINT_A_B_OUTPUT 1

module tb_mm_mlp();

       reg signed [15:0] I_16_2d[0:15][0:15]; 
       reg [16*16*16-1:0] I_16_1d;
       
       reg signed [15:0] I0_16_2d[0:15][0:15];
       reg signed [15:0] I1_16_2d[0:15][0:15];
       reg signed [15:0] I2_16_2d[0:15][0:15];
       reg signed [15:0] I3_16_2d[0:15][0:15];
       reg signed [15:0] I4_16_2d[0:15][0:15];
       reg signed [15:0] I5_16_2d[0:15][0:15];
       reg signed [15:0] I6_16_2d[0:15][0:15];
       reg signed [15:0] I7_16_2d[0:15][0:15];
       
       reg [16*16*16-1:0] I0_16_1d;
       reg [16*16*16-1:0] I1_16_1d;
       reg [16*16*16-1:0] I2_16_1d;
       reg [16*16*16-1:0] I3_16_1d;
       reg [16*16*16-1:0] I4_16_1d;
       reg [16*16*16-1:0] I5_16_1d;
       reg [16*16*16-1:0] I6_16_1d;
       reg [16*16*16-1:0] I7_16_1d;
       
       reg signed [15:0] W0_2d[0:15][0:15];
       reg signed [15:0] W1_2d[0:15][0:15]; 
       reg signed [15:0] W2_2d[0:15][0:15]; 
       reg signed [15:0] W3_2d[0:15][0:15]; 
       reg signed 
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

农民真快落

我琢磨着也没人给我打赏呀。。

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

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

打赏作者

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

抵扣说明:

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

余额充值