verilog实现矩阵卷积运算

verilog实现矩阵卷积运算verilog 实现卷积运算卷积的运算原理卷积是一种线性运算 是很多普通图像处理操作的基本算法之一 它提供了两个数组相乘的方式 两个数组拥有不同的大小 但是具有相同的维数 生成了一个用于相同维数的新数组 可以用来图像的执行操作 输入一组特定的像素值线性组合成为另一组像素值 在图像处理中常见的 msk 运算都是卷积 广泛应用于图像滤波 1 1 卷积出现的背景卷积是在信号与线性系统的基础或背景中出现的

verilog实现卷积运算

卷积的运算原理

图1.1
构造一个3 * 3的卷积核,并利用该卷积核完成与6×6矩阵的卷积运算,数据位宽8bit补码数, 结果位宽20bit补码数。
卷积的基本过程如下:
对卷积核进行180度翻转(数据读写顺序的调度)将3×3卷积核的中心对准 6×6 矩阵的每个数进行对应数据乘累加得出结果,如此往复作业。输入数据补码8bit,实际有效7bit,输出数据补码20bit,实际有效19bit,卷积增加位数3×3=9,所以单个乘法最多增加19-7-9=3bit。所以卷积核采用3bit数,即4bit补码数。
内置电路图如图二所示:
芯片内置图
正如第二部分对本次设计的介绍,我们要做到的是对模拟信号的采样由A/D转换器来完成,而卷积过程由信号的移位来实现。为了设计卷积运算器,首先要设计RAM 和A/D转换器的VerilogHDL 模型。在电子工业发达的国家,可以通过商业渠道得到非常准确的外围器件的虚拟模型。如果没有外围器件的虚拟模型。因为RAM和A/D转换器不是我们设计的硬件对象,所以需要的只是他们的行为模型,精确的行为模型需要认真细致的编写,并不比综合模块容易编写。
运算过程简介
系统内置3×3的4bit补码数的卷积核
3*3卷积核
外部输入6*6的8比特补码数:
6*6的补码数






















//TESTBENCH `timescale 1us/1us module TESTBENCH(); reg signed [7:0] TiData[1:6][1:6]; // Test input Data reg signed [19:0] ToData[1:4][1:4]; // Test output Data reg signed [7:0] TiDataSingle; // for transmission wire signed [19:0] ToDataSingle; // for transmission reg clk; reg reset; reg CONV_start; wire CONV_finish; reg [7:0] i; reg [7:0] j; parameter period = 10; parameter hperiod = 5; CONV CONV_T( .reset(reset), .clk(clk), .CONV_start(CONV_start), .CONV_finish(CONV_finish), .CONV_iData(TiDataSingle), .CONV_oData(ToDataSingle)); initial begin $display("0.Load Data"); $readmemh("Data_input.txt", TiData); for(i = 1; i < 7; i = i + 1) $display("%d %d %d %d %d %d", TiData[i][1], TiData[i][2], TiData[i][3], TiData[i][4], TiData[i][5], TiData[i][6]); clk = 0; CONV_start = 0; reset = 1; // Reset Chip #period reset = 0; // Chip Working #period CONV_start = 1; // CONV start and writing data // align test data to the negedge of clk $display("1.Write Data"); for(i = 1; i < 7; i = i + 1) for(j = 1; j < 7; j = j + 1) begin TiDataSingle = TiData[i][j]; #period; end CONV_start = 0; // finish writing data $display("2.Convolution"); while(!CONV_finish) #period; #period; $display("3.Read Data"); for(i = 1; i < 5; i = i + 1) for(j = 1; j < 5; j = j + 1) begin ToData[i][j] = ToDataSingle; end for(i = 1; i < 5; i = i + 1) $display("%d %d %d %d", ToData[i][1], ToData[i][2], ToData[i][3], ToData[i][4]); $display("End"): end always #hperiod clk = !clk; endmodule 

verlog源码

module CONV( input wire reset, input wire clk, input wire CONV_start, output reg CONV_finish, input wire signed [7:0] CONV_iData, output reg signed [19:0] CONV_oData ); reg signed [3:0]CONV_core[1:9]; reg [3:0] ii_count; reg [3:0] ij_count; reg [3:0] ci_count; reg [3:0] cj_count; reg [3:0] oi_count; reg [3:0] oj_count; reg signed [7:0] CONV_iArrayData[1:6][1:6]; // input Data reg signed [19:0] CONV_oArrayData[1:4][1:4]; // output Data reg CONV_StartCal; // Start convolution // For ReConstruct wire signed [7:0] CONV_iReCon[1:9]; // input ReConstruct Temp wire signed [19:0] CONV_mul[1:9]; wire signed [19:0] CONV_result; // Calculating Convolution assign CONV_iReCon[1] = CONV_iArrayData[ci_count+0][cj_count+0]; assign CONV_iReCon[2] = CONV_iArrayData[ci_count+0][cj_count+1]; assign CONV_iReCon[3] = CONV_iArrayData[ci_count+0][cj_count+2]; assign CONV_iReCon[4] = CONV_iArrayData[ci_count+1][cj_count+0]; assign CONV_iReCon[5] = CONV_iArrayData[ci_count+1][cj_count+1]; assign CONV_iReCon[6] = CONV_iArrayData[ci_count+1][cj_count+2]; assign CONV_iReCon[7] = CONV_iArrayData[ci_count+2][cj_count+0]; assign CONV_iReCon[8] = CONV_iArrayData[ci_count+2][cj_count+1]; assign CONV_iReCon[9] = CONV_iArrayData[ci_count+2][cj_count+2]; assign CONV_mul[1] = CONV_core[9]*CONV_iReCon[1]; assign CONV_mul[2] = CONV_core[8]*CONV_iReCon[2]; assign CONV_mul[3] = CONV_core[7]*CONV_iReCon[3]; assign CONV_mul[4] = CONV_core[6]*CONV_iReCon[4]; assign CONV_mul[5] = CONV_core[5]*CONV_iReCon[5]; assign CONV_mul[6] = CONV_core[4]*CONV_iReCon[6]; assign CONV_mul[7] = CONV_core[3]*CONV_iReCon[7]; assign CONV_mul[8] = CONV_core[2]*CONV_iReCon[8]; assign CONV_mul[9] = CONV_core[1]*CONV_iReCon[9]; assign CONV_result = CONV_mul[1] + CONV_mul[2] + CONV_mul[3] + CONV_mul[4] + CONV_mul[5] + CONV_mul[6] + CONV_mul[7] + CONV_mul[8] + CONV_mul[9]; // Init Core always @(posedge reset) begin CONV_core[1] <= 4'h1; CONV_core[2] <= 4'h2; CONV_core[3] <= 4'hf; CONV_core[4] <= 4'hd; CONV_core[5] <= 4'h5; CONV_core[6] <= 4'h3; CONV_core[7] <= 4'he; CONV_core[8] <= 4'h1; CONV_core[9] <= 4'h2; end // Load input Data always @(posedge clk or posedge reset or posedge CONV_finish) begin if(reset || CONV_finish) begin ii_count <= 1; ij_count <= 1; CONV_StartCal <= 0; end else if(CONV_start && (ii_count < 7)) begin if(ij_count < 6) ij_count <= ij_count + 1; else begin if(ii_count < 6)begin ii_count <= ii_count + 1; ij_count <= 1; end else begin CONV_StartCal <= 1; end end CONV_iArrayData[ii_count][ij_count] <= CONV_iData; // Load Data end end // Convolution always @(posedge clk or posedge reset) begin if(reset) begin ci_count <= 1; cj_count <= 1; CONV_finish <= 0; end else if(CONV_StartCal && (ci_count < 5)) begin if(cj_count < 4) cj_count <= cj_count + 1; else begin if(ci_count < 4) begin ci_count <= ci_count + 1; cj_count <= 1; end else begin CONV_finish <= 1; end end CONV_oArrayData[ci_count][cj_count] <= CONV_result; // Record the Result end end // Output Data always @(posedge clk or posedge reset or posedge CONV_start) begin if(reset || CONV_start) begin oi_count <= 1; oj_count <= 1; end else if(CONV_finish && (oi_count < 5)) begin if(oj_count < 4) oj_count <= oj_count + 1; else begin if(oi_count < 4)begin oi_count <= oi_count + 1; oj_count <= 1; end end CONV_oData <= CONV_oArrayData[oi_count][oj_count]; // Output Data end end endmodule 

python验证

import numpy as np from scipy import signal from scipy import misc input_data=[ [1, 2, 3, 4, 5, 6], [17, 18,19,20,21,22], [33, 34,35,36,37,38], [65, 66,67,68,69,70], [-127,-126,-125, -124, -123, -122], [-95,-94,-93, -92,-91, -90] ] heigh,wid=input_data[:2] weights_data=[ [1 ,2,-1], [-3,5,3], [-2 ,1,2] ] heigh1,wid1 = weights_data[:2] con_result = signal.convolve(input_data,weights_data,mode= 'full') grad=signal.convolve2d(weights_data,input_data) print(grad[2:6,2:6]) 

小编还在成长,请大家多多指教!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/228108.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月16日 下午7:48
下一篇 2026年3月16日 下午7:48


相关推荐

  • java date 毫秒_如何在几个数字上加上同一个单位

    java date 毫秒_如何在几个数字上加上同一个单位//时间加上秒后的时间日期publicstaticDatetimePastTenSecond(Integersecond,Stringotime){try{SimpleDateFormatsdf=newSimpleDateFormat(“yyyy-MM-ddHH:mm:ss”);Datedt=sdf.parse(otime);CalendarnewTime=Calenda.

    2025年9月19日
    6
  • 获取数据库中所有表名

    获取数据库中所有表名

    2021年10月19日
    48
  • java 文件名乱码_详解关于java文件下载文件名乱码问题解决方案

    java 文件名乱码_详解关于java文件下载文件名乱码问题解决方案JAVA 文件下载时乱码有两种情况 1 下载时中文文件名乱码 2 下载时因为路径中包含中文文件名乱码 提示找不到文件解决方法见下面部分代码 response setContentTy multipart form data StringuserAg request getHeader User Agent StringoraFil meetingFile ge

    2026年3月26日
    4
  • gitignore不起作用解决办法

    gitignore不起作用解决办法转自 gitignore 不起作用解决办法前面有文章介绍了使用 gitignore 文件的方法 该文件表示过滤规则 但是对已经加入版本库的文件不能生效 因此需要利用命令将想要忽略的文件从版本库中删除 比如说 我们对 android 工程进行跟踪 结果发现 class 和 R 文件每次都会有差异 实际上这些系统生成文件不需要追踪 于是我们写了 ignore 文件去排除跟踪这些文件 具体写法前面文章有介绍 但是在

    2026年3月26日
    1
  • Javascript的5种基本数据类型总结

    Javascript的5种基本数据类型总结ECMAScript中有5种基本数据类型,分别是:Undefined,Null,Boolean,Number和String,还有一种复杂数据类型Object,Object本质上是由一组无序的名值对组成的。(这里就不细细讲述了)typeof操作符typeof操作符是负责检测给定变量的数据类型,下面是几个使用typeof操作符的例子这说明typeof操作符可以是变量,可以是数值字面量。注意,typeof是一个操作符而不是一个函数,因此例子中的圆括号尽管可以使用,但不是必须的。调用typeofnull

    2025年9月2日
    6
  • JAVA读取csv文件_java读取csv文件某一列

    JAVA读取csv文件_java读取csv文件某一列csv文件的介绍以下是来自百度百科的介绍逗号分隔值(Comma-SeparatedValues,CSV,有时也称为字符分隔值,因为分隔字符也可以不是逗号),其文件以纯文本形式存储表格数据(数字和文本)。纯文本意味着该文件是一个字符序列,不含必须像二进制数字那样被解读的数据。CSV文件由任意数目的记录组成,记录间以某种换行符分隔;每条记录由字段组成,字段间的分隔符是其它字符或字符串,最常见的是逗号或制表符。通常,所有记录都有完全相同的字段序列。通常都是纯文本文件。建议使用WORDPAD或是记事本来

    2025年6月1日
    4

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号