本代码实现了NxN矩阵和NxN矩阵的乘法,当然矩阵不一定非要是方阵,只需对代码稍作修改即可。
在本代码中,矩阵乘法是分块进行的,且在加载块矩阵和计算块矩阵部分和间加入乒乓操作,同时,也在计算块矩阵和写回块矩阵之间加入了乒乓操作,因此,数据传输(包括加载和写回)时间被掩盖,吞吐率得到提升。
下面是顶层模块的代码:

`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2020/11/17 21:51:58
// Design Name:
// Module Name: compute_mm
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//module compute_mm(               //O=A*B
input logic clk,
input logic rst,
input logic start,
input logic [15:0]dina,          //读取矩阵A
input logic [15:0]dinb,          //读取矩阵B
output logic [7:0]addra,
output logic [7:0]addrb,
output logic we,                 //结果写入O矩阵
output logic [7:0]addro,
output logic [15:0]douto,
output logic done);
parameter N = 16;
parameter Tn = 4;logic [15:0]buff_o1[0:Tn-1][0:Tn-1];
logic [15:0]buff_o2[0:Tn-1][0:Tn-1];
logic [7:0]block_row;
logic [7:0]block_col;
logic [7:0]pre_block_row;                 //compute block and store pre_block
logic [7:0]pre_block_col;logic pingpang;
logic pingpang_start;
logic pingpang_done;logic start_compute1;
logic start_compute2;
logic start_store1;
logic start_store2;
logic compute1_done;
logic compute2_done;
logic store1_done;
logic store2_done;
logic compute1_done_ff;
logic compute2_done_ff;
logic store1_done_ff;
logic store2_done_ff;logic we1;
logic we2;
logic [7:0]addro1;
logic [7:0]addro2;
logic [15:0]douto1;
logic [15:0]douto2;
logic [7:0]addra1;
logic [7:0]addra2;
logic [7:0]addrb1;
logic [7:0]addrb2;logic first_compute;
logic final_store;
logic busy;
//busy
always_ff@(posedge clk,posedge rst)
if(rst)busy<=1'b0;
else if(start)busy<=1'b1;
else if(done)busy<=1'b0;
//block_col
always_ff@(posedge clk,posedge rst)
if(rst)block_col<=8'd0;
else if(start)block_col<=8'd0;
else if(pingpang_done)if(block_col==N-Tn)block_col<=8'd0;elseblock_col<=block_col+Tn;
//block_row
always_ff@(posedge clk,posedge rst)
if(rst)block_row<=8'd0;
else if(start)block_row<=8'd0;
else if(pingpang_done&&block_col==N-Tn)block_row<=block_row+Tn;
//pre_block_row,pre_block_col
always_ff@(posedge clk,posedge rst)
if(rst)
beginpre_block_row<=8'd0;pre_block_col<=8'd0;
end
else if(pingpang_done)
beginpre_block_row<=block_row;pre_block_col<=block_col;
end
//pingpang
always_ff@(posedge clk,posedge rst)
if(rst)pingpang<=1'b0;
else if(start)pingpang<=1'b0;
else if(pingpang_done)pingpang<=~pingpang;
//pingpang_start
always_ff@(posedge clk,posedge rst)
if(rst)pingpang_start<=1'b0;
else if(start)pingpang_start<=1'b1;
else if(pingpang_done&&~pingpang_start&&~done)pingpang_start<=1'b1;
else pingpang_start<=1'b0;
//compute1_done_ff
always_ff@(posedge clk,posedge rst)
if(rst)compute1_done_ff<=1'b0;
else if(compute1_done)compute1_done_ff<=1'b1;
else if(pingpang_done)compute1_done_ff<=1'b0;
//compute2_done_ff
always_ff@(posedge clk,posedge rst)
if(rst)compute2_done_ff<=1'b0;
else if(compute2_done)compute2_done_ff<=1'b1;
else if(pingpang_done)compute2_done_ff<=1'b0;
//store1_done_ff
always_ff@(posedge clk,posedge rst)
if(rst)store1_done_ff<=1'b0;
else if(store1_done)store1_done_ff<=1'b1;
else if(pingpang_done)store1_done_ff<=1'b0;
//store2_done_ff
always_ff@(posedge clk,posedge rst)
if(rst)store2_done_ff<=1'b0;
else if(store2_done)store2_done_ff<=1'b1;
else if(pingpang_done)store2_done_ff<=1'b0;
//pingpang_done
always_ff@(posedge clk,posedge rst)
if(rst)pingpang_done<=1'b0;
else if(pingpang==1'b0)                    //compute1 and store2if(~pingpang_done)                if(first_compute&&compute1_done_ff)pingpang_done<=1'b1;else if(final_store&&store2_done_ff)pingpang_done<=1'b1;else if(compute1_done_ff&&store2_done_ff)pingpang_done<=1'b1;elsepingpang_done<=1'b0;elsepingpang_done<=1'b0;
else                                        //compute2 and store1if(~pingpang_done)if(first_compute&&compute2_done_ff)pingpang_done<=1'b1;else if(final_store&&store1_done_ff)pingpang_done<=1'b1;else if(compute2_done_ff&&store1_done_ff)pingpang_done<=1'b1;elsepingpang_done<=1'b0;elsepingpang_done<=1'b0;
//done,fisrt_compute,final_compute
assign done=(pingpang_done&&pre_block_col==N-Tn&&pre_block_row==N-Tn)?1'b1:1'b0;
assign first_compute=(block_row==0&&block_col==0&&busy)?1'b1:1'b0;
assign final_store=(pre_block_row==N-Tn&&pre_block_col==N-Tn&&busy)?1'b1:1'b0;
//start1,2
assign start_compute1=(~pingpang&&pingpang_start&&~final_store)?1'b1:1'b0;
assign start_store2=(~pingpang&&pingpang_start&&~first_compute)?1'b1:1'b0;
assign start_compute2=(pingpang&&pingpang_start&&~final_store)?1'b1:1'b0;
assign start_store1=(pingpang&&pingpang_start&&~first_compute)?1'b1:1'b0;
//addra1,addra2,addrb1,addrb2
assign addra=(pingpang==1'b0)?addra1:addra2;
assign addrb=(pingpang==1'b0)?addrb1:addrb2;
//addro1,addro2,we1,we2,douto1,douto2
assign addro=(pingpang==1'b0)?addro2:addro1;                                   //compute1 and store2
assign we=(pingpang==1'b0)?we2:we1;
assign douto=(pingpang==1'b0)?douto2:douto1;
//模块例化
compute_one_block U1(
.clk(clk),
.rst(rst),
.start(start_compute1),
.dina(dina),
.dinb(dinb),
.block_row(block_row),
.block_col(block_col),
.addra(addra1),
.addrb(addrb1),
.result(buff_o1),
.done(compute1_done));compute_one_block U2(
.clk(clk),
.rst(rst),
.start(start_compute2),
.dina(dina),
.dinb(dinb),
.block_row(block_row),
.block_col(block_col),
.addra(addra2),
.addrb(addrb2),
.result(buff_o2),
.done(compute2_done));store_block V1(
.block_row(pre_block_row),
.block_col(pre_block_col),
.block_mat(buff_o1),
.clk(clk),
.rst(rst),
.start(start_store1),
.we(we1),
.addr(addro1),
.dout(douto1),
.done(store1_done));store_block V2(
.block_row(pre_block_row),
.block_col(pre_block_col),
.block_mat(buff_o2),
.clk(clk),
.rst(rst),
.start(start_store2),
.we(we2),
.addr(addro2),
.dout(douto2),
.done(store2_done));
endmodule

这是testbench:

`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2020/11/17 22:36:27
// Design Name:
// Module Name: compute_mm_test
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//module compute_mm_test;
parameter N = 16;
logic clk;
logic rst;
logic start;
logic [15:0]dina;
logic [15:0]dinb;
logic [7:0]addra;
logic [7:0]addrb;
logic we;
logic [7:0]addro;
logic [15:0]douto;
logic done;
//
logic [7:0]addra_ff;
logic [7:0]addrb_ff;
logic [15:0]result[0:N-1][0:N-1];
logic [7:0]row;
logic [7:0]col;
logic [15:0]A[0:N-1][0:N-1];
logic [15:0]B[0:N-1][0:N-1];
logic [15:0]O[0:N-1][0:N-1];
int error_count;initial
beginfor(int i=0;i<N;i++)for(int j=0;j<N;j++)beginA[i][j]=i*16+j;B[i][j]=i*16+j;end    for(int i=0;i<N;i++)for(int j=0;j<N;j++)beginO[i][j]=0;for(int k=0;k<N;k++)O[i][j]+=A[i][k]*B[k][j];endfor(int i=0;i<N;i++)beginfor(int j=0;j<N;j++)begin$write("%d,",O[i][j]);end$write("\n");end
endassign row=addro[7:4];              //row=addro/16
assign col=addro[3:0];              //col=addro%16
//result
always_ff@(posedge clk,posedge rst)
if(rst)
for(int i=0;i<N;i++)for(int j=0;j<N;j++)result[i][j]=0;
else if(we)
beginresult[row][col]<=douto;
end
//done
always_ff@(posedge clk)
if(done)
begin
$display("The Module's Result:");
for(int i=0;i<N;i++)
beginfor(int j=0;j<N;j++)begin$write("%d,",result[i][j]);end$write("\n");
end
$display("Compare the result");
error_count=0;
for(int i=0;i<N;i++)for(int j=0;j<N;j++)beginif(O[i][j]!=result[i][j])begin$display("Error,O[%d][%d]!=result[%d][%d]",i,j,i,j);error_count++;endend
if(error_count==0)$display("Test Pass");
end
//dina,dinb
always_ff@(posedge clk,posedge rst)
if(rst)
begindina<=16'd0;dinb<=16'd0;
end
else
begindina<=addra_ff;dinb<=addrb_ff;
end
always_ff@(posedge clk,posedge rst)
if(rst)
beginaddra_ff<=8'd0;addrb_ff<=8'd0;
end
else
beginaddra_ff<=addra;addrb_ff<=addrb;
end
//clk
initial
beginclk=0;forever#5clk=~clk;
end
//rst
initial
beginrst=1;#10rst=0;
end
//start
initial
beginstart=0;#100start=1;#10start=0;
endcompute_mm U(.*);
endmodule

仿真结果显示完全正确:

这是仿真的波形图

更详细的:

可以看到顶层模块调用了两个子模块,这两个子模块见分块矩阵乘法+乒乓操作
和基于FPGA的矩阵乘法

system verilog实现矩阵乘法相关推荐

  1. 分块矩阵乘法+乒乓操作

    本文用system verilog实现了分块矩阵乘法中计算输出矩阵的某一块,并且进行了pingpang操作,以掩盖数据传输时间. 这是顶层模块的代码: `timescale 1ns / 1ps // ...

  2. 用MapReduce实现矩阵乘法

    主要介绍Hadoop家族产品,常用的项目包括Hadoop, Hive, Pig, HBase, Sqoop, Mahout, Zookeeper, Avro, Ambari, Chukwa,新增加的项 ...

  3. 多线程读取矩阵文件+多线程矩阵乘法(C++实现)

    算法概述 矩阵乘法可以在算法层面上进行并行. vector< vector > Mat[3]; 这个二维向量数组就是来放做矩阵乘法中的那些矩阵的.Mat[0]是矩阵A,Mat[1]是矩阵B ...

  4. 蓝桥杯-矩阵乘法(java)

    算法训练 矩阵乘法 时间限制:1.0s 内存限制:512.0MB问题描述输入两个矩阵,分别是m*s,s*n大小.输出两个矩阵相乘的结果.输入格式第一行,空格隔开的三个正整数m,s,n(均不超过200) ...

  5. c++矩阵作为函数输入变量_C++实现矩阵乘法

    最近学习C++,做了一个矩阵乘法的练习.先说一下功能,输入两个矩阵A,B,大小自己定,换行用:表示(matlab的习惯).然后输出A*B的矩阵. 1.思路 首先,由于输入的矩阵维数是随机的,因此,我们 ...

  6. GPU与CPU版本的矩阵乘法对比

    由于刚刚开始学习Cuda,还没有整理出一个完整的Cuda类,只是在Nvidia提供的kenerl架构上做修改. 但用于初体验GPU给我们带来的好处也绰绰有余了. 直接贴代码: /*矩阵乘法,CPU版本 ...

  7. 矩阵乘法如何去逆矩阵_矩阵乘法和求逆

    矩阵乘法如何去逆矩阵 数据科学与机器学习的线性代数 (LINEAR ALGEBRA FOR DATA SCIENCE AND MACHINE LEARNING) We are going to tre ...

  8. java矩阵连乘算法_使用java写的矩阵乘法实例(Strassen算法)

    Strassen算法于1969年由德国数学家Strassen提出,该方法引入七个中间变量,每个中间变量都只需要进行一次乘法运算.而朴素算法却需要进行8次乘法运算. 原理 Strassen算法的原理如下 ...

  9. Vijos 1603 ----迷宫(矩阵乘法,矩阵快速幂)

    描述 在某个神秘的星球上有一个游乐园 游乐园里有一个奇怪的迷宫,迷宫内有n个点,每个点之间都可能会有一条有向边(可能会有自环) 现在游乐园主有个问题想请你帮忙: 问:从s点走到f点,恰好走过m条边(边 ...

最新文章

  1. 高可用keepalived实例
  2. Oracle建立约束、删除约束
  3. 重磅!微软发布 vscode.dev,把 VSCode 带入浏览器!
  4. “约见”面试官系列之常见面试题之第九十四篇之MVVM框架(建议收藏)
  5. 祝各位网友儿童节快乐!
  6. 这是波士顿动力机器狗「他爸」?美军80年代机器狗「考古」,身高3米,人机联合操作...
  7. leetcode - 467. 环绕字符串中唯一的子字符串
  8. 数值优化(Numerical Optimization)学习系列-目录
  9. 数字图像处理与机器视觉光盘资料_机器视觉——数字图像处理知识点总结
  10. Day3-字符串-数组-正则表达式
  11. configure: error: Cannot find the WebServer
  12. 资讯--2019年4月
  13. 2020电信宽带费用_现在电信宽带多少钱一年,2020年电信宽带套餐价格表
  14. linux查看目录是不是btrfs,btrfs文件系统常用命令使用
  15. Learning to Track at 100 FPS with Deep Regression Networks全文翻译
  16. 机器人运动学、动力学基础上利用MATLAB进行PID控制仿真
  17. python爬虫基础Ⅱ——Ajax数据爬取、带参请求:QQ音乐歌单、QQ音乐评论
  18. 记录一次使用Redis中ZSet和List分页
  19. CSS峰会亮点直击,大咖共议产业上云的安全“最优解”
  20. sparql查询mysql_Sparql查询语言基础学习(一)

热门文章

  1. COleDateTime使用
  2. Classmate Reunion-Technical Support
  3. 星光不问赶路人,时光不负有心人
  4. 易语言软件登录界面教程
  5. 转载 ----MAVEN相关学习
  6. 使用SAS 批量修改文件名
  7. PHP获取微信公众号头像,新版微擎框架公众号获取用户头像
  8. Springboot + elementUI实现上传用户头像
  9. java类的继承(基础)
  10. 数据采集协同架构,集成马扎克、西门子、海德汉、广数、凯恩帝、三菱、海德汉、兄弟、哈斯、宝元、新代、发那科、华中各类数控以及各类PLC数据采集软件