【Verilog】简单二维卷积硬件verilog实现

基本知识:
https://blog.csdn.net/appleyuchi/article/details/78597516
https://blog.csdn.net/carson2005/article/details/43702241
网上有很多资料,这里不做赘述。
在这里插入图片描述

代码实现:
本文只是简单的实现,没有做任何加速。但可以说明卷积的原理,比如ROM,可以改成用函数

$readmemh("conv_2d.hex",ROM);

比如在处理窗数据时,可以改用FIFO缓存,或或者用滑动窗口在一个时刻取出窗口数据,速度会有很大的提升,所以很多前辈在做加速。
以下面的数据为例:
在这里插入图片描述

代码很简单
//
// Company: 
// Engineer: ZHANG ZEKUN
// 
// Create Date: 2019/08/24 15:01:16
// Design Name: 
// Module Name: easy_conv_2d
// Project Name:  
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//

module conv_2d#(
	parameter CORE3X3_0 = 2'b01, //conv core
	parameter CORE3X3_1 = 2'b10,
	parameter CORE3X3_2 = 2'b11,
	parameter CORE3X3_3 = 2'b01,
	parameter CORE3X3_4 = 2'b10,
	parameter CORE3X3_5 = 2'b11,
	parameter CORE3X3_6 = 2'b01,
	parameter CORE3X3_7 = 2'b10,
	parameter CORE3X3_8 = 2'b11
)
(	
	input CLK,
	input RSTn,
	input read,
	
	output [7:0] CONV_OUT
);

reg [3:0] ROM [35:0];                   //memory 
reg [5:0] rd;                           //memory address
reg [7:0] CONV_OUT_REG;                //regsiter of conv_out
reg [3:0] WIN0;                           //windows data
reg [3:0] WIN1;
reg [3:0] WIN2;
reg [3:0] WIN3;
reg [3:0] WIN4;
reg [3:0] WIN5;
reg [3:0] WIN6;
reg [3:0] WIN7;
reg [3:0] WIN8;


initial                                //data is small,direct store
begin
	ROM[ 0] = 4'b0001;
	ROM[ 1] = 4'b0010;
	ROM[ 2] = 4'b0011;
	ROM[ 3] = 4'b0100;
	ROM[ 4] = 4'b0101;
	ROM[ 5] = 4'b0110;
	ROM[ 6] = 4'b0111;
	ROM[ 7] = 4'b1000;
	ROM[ 8] = 4'b1001;
	ROM[ 9] = 4'b1010;
	ROM[10] = 4'b1011;
	ROM[11] = 4'b1100;
	ROM[12] = 4'b1101;
	ROM[13] = 4'b1110;
	ROM[14] = 4'b1111;
	ROM[15] = 4'b0000;
	ROM[16] = 4'b0001;
	ROM[17] = 4'b0010;
	ROM[18] = 4'b0011;
	ROM[19] = 4'b0100;
	ROM[20] = 4'b0101;
	ROM[21] = 4'b0110;
	ROM[22] = 4'b0111;
	ROM[23] = 4'b1000;
	ROM[24] = 4'b1001;
	ROM[25] = 4'b1010;
	ROM[26] = 4'b1011;
	ROM[27] = 4'b1100;
	ROM[28] = 4'b1101;
	ROM[29] = 4'b1110;
	ROM[30] = 4'b1111;
	ROM[31] = 4'b0000;
	ROM[32] = 4'b0001;
	ROM[33] = 4'b0010;
	ROM[34] = 4'b0011;
	ROM[35] = 4'b0100;
end

always @ (posedge CLK or negedge RSTn)
begin
	if (!RSTn)
		begin
		WIN0 <= 2'bx;
		WIN1 <= 2'bx;
		WIN2 <= 2'bx;
		WIN3 <= 2'bx;
		WIN4 <= 2'bx;
		WIN5 <= 2'bx;
		WIN6 <= 2'bx;
		WIN7 <= 2'bx;
		WIN8 <= 2'bx;
		rd <= 0;
		end
	else if (read)
		begin
			WIN0 = ROM[rd];
			WIN1 = ROM[rd + 4'b0001];
			WIN2 = ROM[rd + 4'b0010];
			WIN3 = ROM[rd + 4'b0110];
			WIN4 = ROM[rd + 4'b0111];
			WIN5 = ROM[rd + 4'b1000];
			WIN6 = ROM[rd + 4'b1100];
			WIN7 = ROM[rd + 4'b1101];
			WIN8 = ROM[rd + 4'b1110];
			rd <= rd + 1'b1;
		end
end

always @ ( posedge CLK or negedge RSTn )
begin
	case (rd)
	6'd3:rd <= rd + 2'b11;
	6'd9:rd <= rd + 2'b11;
	6'd15:rd <= rd + 2'b11;
	endcase
end	

always @ ( posedge CLK or negedge RSTn )
begin
	if (!RSTn)
		CONV_OUT_REG <= 0;
	else 
		CONV_OUT_REG <= WIN0 * CORE3X3_8 + WIN1 * CORE3X3_7 + WIN2 * CORE3X3_6 + WIN3 * CORE3X3_5 + WIN4 * CORE3X3_4 + WIN5 * CORE3X3_3 + WIN6 * CORE3X3_2 + WIN7 * CORE3X3_1 + WIN8 * CORE3X3_0;
end


assign CONV_OUT = CONV_OUT_REG;


endmodule
简单仿真
module conv_2d_tb();
	reg CLK;
	reg RSTn;
	reg read;
	
	wire [7:0] CONV_OUT;
	
	
initial 
begin
	CLK = 0;
	forever #100 CLK = ~CLK;
end

initial 
begin
	RSTn = 0;
	#50 RSTn = 1;
	read = 1;
end

conv_2d CONV(.CLK(CLK),
			 .RSTn(RSTn),
			 .read(read),
			 .CONV_OUT(CONV_OUT));
			 
endmodule

仿真结果
在这里插入图片描述
用matlab验证:
在这里插入图片描述
综合:
在这里插入图片描述
对比数据是正确的,逻辑没有问题。
很简单的实现了二维卷积,没有涉及到pad等,可以在这个基础上改进很多

越是憧憬,越要风雨兼程。

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值