(8)FPGA-CNN池化层
池化层
池化层(Pooling Layer)是卷积神经网络(CNN)中常用的下采样模块,其作用是在保留主要特征信息的同时降低特征图的空间分辨率,从而减少计算量和参数数量,提高模型的鲁棒性。常见的池化方式包括最大池化(Max Pooling)和平均池化(Average Pooling),其中最大池化通过选取局部区域内的最大值来突出显著特征。通过池化操作,特征图尺寸逐渐减小,既能降低后续网络的计算复杂度,又能增强模型对目标位置微小变化和噪声干扰的适应能力。
最大池化
常用的是2×2最大池化(Max Pooling)通常采用Stride=2,即窗口每次移动2个像素。对于输入特征图中的每个2×2区域,池化层只保留其中的最大值作为输出,其余数据被舍弃。以上例中,4×4输入特征图经过2×2最大池化后输出为2×2特征图,空间尺寸缩小为原来的1/2,而数据量减少到原来的1/4。
FPGA实现
该池化层 Verilog 模块通过移位寄存器搭建滑动窗口缓存,控制窗口按指定步长遍历输入特征图,最大池化经多级比较器提取窗口极值,输出降采样后的特征数据,采用全流水线结构降低计算延迟。代码如下:
xpm_fifo_sync #( .FIFO_MEMORY_TYPE ("block" ), // "auto" / "block" / "distributed" / "ultra" .FIFO_WRITE_DEPTH (FIFO_DEPTH ), .WRITE_DATA_WIDTH (24 ), .READ_DATA_WIDTH (24 ), .READ_MODE ("fwft" ) ) u_lane_buffer( .wr_clk (clk ), .rst ((~aresetn)|fifo_rst), .din (wr_data ), .wr_en (wr_en ), .full ( ), .dout (rd_data ), .rd_en (rd_en ), .empty ( ) ); wire [23:0] w01,w11; reg [23:0] w00,w10; assign w01 = rd_data; assign w11 = wr_data; assign wd_valid = wr_en & (row_cnt >= 1) & (col_cnt >= 1) & row_cnt[0] & col_cnt[0]; always @(posedge clk or negedge aresetn) begin if(~aresetn)begin w00 <= 0; w10 <= 0; end else begin w00 <= w01; w10 <= w11; end end //=============Compare============ reg signed [23:0] temp_a,temp_b; reg signed [23:0] pool_rlt; reg pool_vld; reg valid_d1; always @(posedge clk or negedge aresetn) begin if(~aresetn)begin valid_d1 <= 0; pool_vld <= 0; end else begin valid_d1 <= wd_valid; pool_vld <= valid_d1; end end always @(posedge clk or negedge aresetn) begin if(~aresetn)begin temp_a <= 0; temp_b <= 0; end else if(wd_valid)begin if(w00 > w01)begin temp_a <= w00; end else begin temp_a <= w01; end if(w10 > w11)begin temp_b <= w10; end else begin temp_b <= w11; end end else begin temp_a <= 0; temp_b <= 0; end end always @(posedge clk or negedge aresetn) begin if(~aresetn)begin pool_rlt <= 0; end else if(valid_d1)begin if(temp_a > temp_b)begin pool_rlt <= temp_a; end else begin pool_rlt <= temp_b; end end else begin pool_rlt <= 0; end end仿真验证
仿真的激励为224x224的男版lena图片,经过一个5x5x3的卷积计算后,得到220x220的结果,再经过池化层最终的尺寸为110x110。下面是rtl的计算结果和python里计算结果的对比:
本章节完成了池化层的 Verilog 设计与仿真验证工作。针对池化运算的窗口滑动、数据比较/累加及输出时序等关键逻辑进行了实现,并搭建仿真测试环境生成测试激励。将 Verilog 仿真结果与 Python 参考模型输出进行逐项对比,结果一致,验证了所设计池化层在功能和计算结果上的正确性,为后续卷积神经网络硬件模块的集成与优化奠定了基础。
