M阶矩阵-向量乘法器的verilog设计

使用Verilog实现矩阵-向量乘法,其目的是将一个M阶矩阵与一个列向量相乘,并将结果输出到指定的输出端口。本设计中,矩阵的阶数、输入输出数据的位宽均被参数化,可自行调整,从而实现任意矩阵阶数、任意数据位宽的矩阵-向量乘法。

本算法中输入是一个矩阵和一个向量,输出为一个向量。矩阵相当于二维数组,向量为一维数组,在verilog中,数组(Memory型)不能作为输入输出的端口,因此要将输入数据转化为数组进行操作(pack),计算后又要将输出的数组还原为reg型变量(unpack)。

具体过程见代码中的注释.

3阶矩阵-向量乘法实现

代码如下:

`timescale 1ns / 1ps
module matrix_vector_multiplier
	#(parameter M   = 3,        //order of matrix and vector
                DW_in  = 4,       //input data width
	            DW_out = 10       //output data width(bit number of M*(2^DW_in-1)^2)at least)
    )    	
   (input  [DW_in * M * M - 1 : 0] matrix_input, 			
	input  [DW_in * M - 1 : 0] vector_input,
	output reg [DW_out * M - 1 : 0] vector_output);		
    
	reg [DW_in-1:0] A [0:M*M-1];        //input matrix in the form of 1-d array
	reg [DW_in-1:0] B [0:M-1][0:M-1];   //input matrix in the form of 2-d array
	reg [DW_in-1:0] V [0:M-1];          //input vector array
	reg [DW_out-1:0] Res [0:M-1];	    //output vector array

	integer i,j,k,p,q,r;
	always@(*)
	begin
	//pack input matrix into 1-d array
		for(i=0;i<M*M;i=i+1)
		begin
        A[i] = matrix_input[(DW_in*(M*M-i) - 1) -: DW_in];
		end
	//pack 1-d array input matrix into 2-d array	
	    for(j=0;j<M;j=j+1)
		begin
		    V[j] = vector_input[(DW_in*(M-j) - 1) -: DW_in];
		    Res[j]=0;
			for(k=0;k<M;k=k+1)
			begin
			   B[j][k]=A[j*M+k];
			end
		end
	//matrix-vector multiplication 
		for(p=0;p<M;p=p+1)
		begin
			for(q=0;q<M;q=q+1)
			begin
                Res[p]=Res[p]+ (B[p][q]*V[q]);
			end
		end
	//unpack output array
		for(r=0;r<M;r=r+1)
		begin
	    vector_output[(DW_out*(M-r)-1) -: DW_out] = Res[r];
		end
	end
endmodule

testbench:

`timescale 1ns/1ps
module mm_tb  ;
	reg [35:0] A;           //word length is M*M*DW_in
	reg [11:0] V;           //word length is M*DW_in
	wire [29:0] result;     //word length is M*DW_out
	
	matrix_vector_multiplier umatrix_vector_multiplier(.matrix_input(A), .vector_input(V), .vector_output(result));
	
	initial begin		
	//Initial inputs
	A={4'd1,4'd2,4'd3,
	   4'd4,4'd5,4'd6,
	   4'd7,4'd8,4'd9};    //input matrix
	V={4'd5,4'd3,4'd5};	   //input vector

//Verdi operation,不使用verdi可略过	
	`ifdef fsdbdump
     $display("\n*** fsdb file dump is turned on ***\n");
     $fsdbDumpfile("mvm.fsdb");
     $fsdbDumpMDA;
     $fsdbDumpvars(0);
     #1000
     $fsdbDumpoff;
     `endif

	end
endmodule

仿真结果:

它实现了矩阵乘法

结果为{26,65,104}。在输出result中以二进制数表示,其中每个元素位宽为10位。

128阶矩阵-向量乘法实现

本设计的一大优点在于矩阵的阶数、输入输出数据的位宽均被参数化,可自行调整,即是矩阵阶数很大,依然可以计算。

首先更改module matrix_vector_multiplier中的参数为:

	#(parameter M   = 128,        
                DW_in  = 4,       
	            DW_out = 16) 

128阶矩阵较大,直接在测试代码中描述矩阵不太方便 ,可将矩阵存放在txt文档中,再通过$readmemh读取至memory型变量。

但这样做会testbench中表示输入矩阵和向量的A和V不能直接获得数据,因此还需要将memory中的数据unpack至A和V中。

具体代码如下

`timescale 1ns/1ps

module mm_tb  ;
	reg [65535:0] A;                       //word length is M*M*DW_in
	reg [511:0] V;                       //word length is M*DW_in
	wire [2047:0] result;                 //word length is M*DW_out
	
	reg [3:0] mem_matrix [0:16383];             //to store the input matrix
	reg [3:0] mem_vector [0:127];
	integer i , j;
	matrix_vector_multiplier umatrix_vector_multiplier(.matrix_input(A), .vector_input(V), .vector_output(result));

	initial begin			
    $readmemh("unit_matrix.txt",mem_matrix);
    $readmemh("vector.txt",mem_vector);
	for(i=0; i<16384; i=i+1) 
	A [65535-4*i -: 4] =  mem_matrix[i];           //unpack mem_matrix to A
	for(j=0; j<128; j=j+1) 
	V [(511-4*j) -: 4] = mem_vector[j];            //unpack mem_vector to V

	//Verdi operation	
	`ifdef fsdbdump
     $display("\n*** fsdb file dump is turned on ***\n");
     $fsdbDumpfile("mvm.fsdb");
     $fsdbDumpMDA;
     $fsdbDumpvars(0);
     #1000
     $fsdbDumpoff;
     `endif
	end
endmodule

例如,下面做一个最简单的测试。用C语言生成一个128阶的单位阵和128阶的全为1的向量,分别写入 unix_matrix.txt和vector.txt.

生成128阶单位矩阵:

#include <stdio.h>

int main() {
    int matrix_size = 128;
    FILE* file;
    file = fopen("unit_matrix.txt", "w");

    if (file == NULL) {
        printf("无法打开文件\n");
        return 1;
    }

    // 生成单位矩阵并写入文件
    for (int i = 0; i < matrix_size; i++) {
        for (int j = 0; j < matrix_size; j++) {
            if (i == j) {
                fprintf(file, "1 ");
            }
            else {
                fprintf(file, "0 ");
            }
        }
        fprintf(file, "\n");
    }

    fclose(file);
    printf("已生成并写入单位矩阵到 unit_matrix.txt\n");

    return 0;
}

生成128维全1的向量 

#include <stdio.h>

int main() {
    int matrix_size = 128;
    FILE* file;
    file = fopen("vector.txt", "w");

    if (file == NULL) {
        printf("无法打开文件\n");
        return 1;
    }

    // 
    for (int i = 0; i < matrix_size; i++) {
        fprintf(file, "1\n");
    }

    fclose(file);
    printf("已生成并写入单位矩阵到 vector.txt\n");

    return 0;
}

仿真结果:

 得到的result也为全1的列向量,仿真结果正确

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

via amiko

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

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

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

打赏作者

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

抵扣说明:

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

余额充值