卷积计算的verilog 实现

该博客围绕构造3*3卷积核与6*6矩阵的卷积运算展开。介绍了问题分析、工作框图、工作方式等内容,明确输入输出数据位宽,阐述卷积过程及数据选取,说明了文件、端口、工作、仿真等情况,最后用Matlab验证,结果与Verilog输出吻合。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在这里插入图片描述

目录

1.问题分析
2.工作框图
3.工作方式
4.数据选取
5.文件说明
6.端口说明
7.工作说明
8.仿真说明
9.仿真结果
1)波形
2)Transcript
10.Matlab 验证

1. 问题分析

构造一个3 * 3的卷积核,并利用该卷积核完成与6*6矩阵的卷积运算,数据位宽8bit补码数, 结果位宽20bit补码数

卷积的基本过程如下:

对卷积核进行180度翻转(数据读写顺序的调度)将33卷积核的中心对准66矩阵的每个数进行对应数据乘累加得出结果,如此往复作业给出实现结构以及RTL代码

ModelSim SE10.1a

Matlab R2010a

输入数据补码8bit,实际有效7bit,输出数据补码20bit,实际有效19bit,卷积增加位数3*3=9,所以单个乘法最多增加19-7-9=3bit。所以卷积核采用3bit数,即4bit补码数。

2. 工作框图

在这里插入图片描述

在这里插入图片描述

3. 工作方式

系统内置3*3的4bit补码数的卷积核
在这里插入图片描述

外部输入6*6的8bit补码数
在这里插入图片描述

工作过程:系统将反转后的卷积核与上图某一深色数据和其周围一圈进行相乘并相加。直到所有深色部分均进行过卷积操作。

举例如下,对应第一个要进行卷积操作的数D22
在这里插入图片描述

O22= D11*C33 + D12*C32 + D13*C31输出数据为:
   + D21*C23 + D22*C22 + D23*C21
   + D31*C13 + D32*C12 + D33*C11

4. 数据选取

卷积核固定选取为:
在这里插入图片描述

输入数据为:(Data_input.txt 有符号16进制)
在这里插入图片描述

转换成10进制
在这里插入图片描述

5. 文件说明

在这里插入图片描述

6. 端口说明

在这里插入图片描述

7. 工作说明

每次启动后TB读取要卷积的数据,并将此数据传输给CONV,每次传输一个数据即8bit
CONV接收完数据后开始卷积
卷积结束后把数据传输给TB,每次传输一个数据即20bit
在这里插入图片描述

8. 仿真说明

在仿真前Transcript中命令:do wave.do加载预设波形
输出结果在Transcript中查看

9. 仿真结果

  1. 波形
    在这里插入图片描述

  2. Transcript
    在这里插入图片描述

10. Matlab 验证

Matlab验证结果(Matlab_Verify.m)
在这里插入图片描述

与verilog输出吻合

### 使用 Verilog 实现卷积操作 在FPGA上使用Verilog实现卷积操作通常涉及几个关键组件:图像数据的读取、卷积核的应用以及结果的输出。下面是一个简化版的卷积实现方法,主要针对9×9大小的卷积核。 #### 图像数据准备 为了处理图像,在硬件描述语言中一般会采用移位寄存器来暂存待处理的数据流。对于一个给定尺寸(比如96x96)的灰度图而言,可以将其按照行优先顺序依次加载到一系列串联起来的移位寄存器内[^3]。 ```verilog // 假设已经有一个名为image_data_in的过程用于接收外部传来的单通道图像信号 reg [7:0] shift_register[0 : 863]; // 创建长度为864的一维数组模拟移位寄存器链表结构 integer i; always @(posedge clk or negedge rst_n) begin if (!rst_n) for (i = 0; i <= 863; i = i + 1) shift_register[i] <= 8'b0; else {shift_register[863], shift_register[0 : 862]} <= {image_data_in, shift_register[0 : 862]}; end ``` 这段代码展示了如何构建一个由864个元素组成的移位寄存器阵列,用来保存当前正在被处理的那一部分图像的信息。每当接收到新的像素值时,整个队列就会向左移动一位,并把新到来的数据放到最右边的位置上去。 #### 卷积计算单元 接下来定义具体的乘积累加逻辑电路来进行实际的卷积运算。这里假设我们已经有了预先设定好的权重参数`kernel_weights`和偏置项`bias_value`[^4]。 ```verilog wire signed [15:0] product_terms[0 : 80]; genvar j,k; generate for(j=0;j<9;j=j+1)begin:ROW_LOOP for(k=0;k<9;k=k+1)begin:COLUMN_LOOP assign product_terms[j*9+k]=signed'(shift_register[(j)*96+(k)]) * kernel_weights[j][k]; end end endgenerate reg signed [23:0] accumulation_result; always @(*) begin accumulation_result = bias_value; for(i=0;i<=80;i=i+1) accumulation_result += product_terms[i]; end ``` 上述片段实现了对每一个位置上的局部区域应用指定的卷积核进行逐点相乘再求和的操作。注意这里的索引是从零开始计数直到80为止,因为总共存在\(9\times9=81\)个独立的乘法子表达式需要累加以得出最终的结果。 #### 输出阶段 最后一步则是将得到的新特征映射输出至下一个模块继续后续的任务或是直接显示出来。考虑到实际情况中的量化误差等因素影响,可能还需要加入一些额外的功能如饱和裁剪等以确保数值范围合理有效。 ```verilog assign output_feature_map = ((accumulation_result > MAX_VALUE)?MAX_VALUE:(accumulation_result < MIN_VALUE)?MIN_VALUE:accumulation_result); ``` 以上便是关于怎样运用Verilog编写一段简单的卷积算法的大致思路概述。当然真实项目里往往还会涉及到更多细节优化措施,例如流水线技术的应用使得吞吐量最大化;或者是借助于专用IP核完成更加高效的矩阵运算等等[^1]。
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值