设输入矩阵为NixNi,卷积核大小为KxK,卷积步长为S,则可以选用长度为Ni,高度为K的shift_ram实现,具体如下。 记输入shift_ram的时间为clk0,则易知经过NixK个周期后shift_ram被充满,也即产生第一列有效输出 X 0 , 0 , X 1 , 0 , X 2 , 0 X_{0,0},X_{1,0},X_{2,0} X0,0,X1,0,X2,0,再经过Nix(Ni-K+1)-1个周期,产生最后一列有效输出 X N i − 1 , N i − 1 , X N i − 2 , N i − 1 , X N i − 3 , N i − 1 X_{Ni-1,Ni-1},X_{Ni-2,Ni-1},X_{Ni-3,Ni-1} XNi−1,Ni−1,XNi−2,Ni−1,XNi−3,Ni−1,设数据读出延时为2+1个clk,计算卷积需要乘法1个周期,加法需要2个周期(每列相加,再把每列的和相加),则从输入第一个数据的读地址开始,需要经过NixK+(2+1)+(1+2)+K-1(需等待余下K-1列读出)个clk才会产生第一个卷积输出,经过NixK+(2+1)+(Ni-K+1)xNi-1+(1+2)个周期产生最后一个卷积输出,当然,这之间的输出并不都有效,应视步长S有选择的进行读取结果。 这种方式计算一个矩阵的大约需要 O ( N i 2 ) O(N_i^2) O(Ni2)个clk周期。 代码如下,已通过仿真,卷积核大小为3,其他卷积核大小需要修改部分代码,但思路一样。 conv.v
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2020/02/13 20:54:56
// Design Name:
// Module Name: top
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module conv
# (
parameter Ni=5,
parameter K=3,
parameter S=2,
parameter No=(Ni-K)/S+1,
parameter F=8) //FΪС��λ��
(
input clk,
input rst,
input start,
input signed[15:0]weight,
output reg[7:0]weight_addr,
input signed [15:0]rd_data,
output signed [15:0]wr_data,
output reg[15:0]rd_addr,
output reg[15:0]wr_addr,
output wren,
output done
);
wire [47:0]taps;
wire signed[15:0]dout,dout0,dout1,dout2;
reg read_weight;
reg read;
reg sum_valid;
reg sum_valid_d1;
reg wr_data_valid;
reg signed[15:0]din;
reg signed[15:0]dout0_d1,dout0_d2,dout1_d1,dout1_d2,dout2_d1,dout2_d2;
reg signed [31:0]mul1,mul2,mul0,mul1_d1,mul2_d1,mul0_d1,mul2_d2,mul1_d2,mul0_d2;
reg signed [31:0]sum0,sum1,sum2;
reg signed [15:0]sum;
reg [7:0]weight_addr_d1,weight_addr_d2;
reg [9:0]cnt1,cnt2;
reg [9:0]cnt_s1,cnt_s2;
reg busy;
wire signed [31:0]p11,p12,p13,p21,p22,p23,p31,p32,p33;
reg signed[15:0]k11,k12,k13,k21,k22,k23,k31,k32,k33;
assign p13=dout0*k13;
assign p23=dout1*k23;
assign p33=dout2*k33;
assign p12=dout0_d1*k12;
assign p22=dout1_d1*k22;
assign p32=dout2_d1*k32;
assign p11=dout0_d2*k11;
assign p21=dout1_d2*k21;
assign p31=dout2_d2*k31;
assign {dout0,dout1,dout2}=taps;
always@(posedge clk,posedge rst)
if(rst)
busy
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?