• 【CNN-FPGA开源项目解析】卷积层03--单格乘加运算单元PE & 单窗口卷积块CU 模块


    03–单格乘加运算单元PE & 单窗口卷积块CU

    前言

    ​ 第一和第二篇日志已经详细阐述了"半精度浮点数"的加法和乘法模块了。需要注意,他们的输入和输出均是16bit的半精度浮点数。现在我们自下而上,向着更顶层进发,用floatMult16和floatAdd16模块搭建基本的卷积运算模块。

    ​ 另外,对于卷积神经网络中基本的卷积运算方法、卷积核、卷积层结构和参数等基础知识这里不会赘述,默认读者已经掌握。


    单格乘加运算单元PE

    ​ 在进行Image与filter的完整卷积运算之前,我们需要更小的模块去支持这样的操作。首先最基本的是image的一格与filter的一格进行的乘法运算。在一个卷积窗口内,这样一次又一次的乘法操作结束后需要进行累加,得到最后的卷积结果。

    代码

    `timescale 100 ns / 10 ps
    
    module processingElement16(clk,reset,floatA,floatB,result);
    
    parameter DATA_WIDTH = 16;
    
    input clk, reset;
    input [DATA_WIDTH-1:0] floatA, floatB;
    output reg [DATA_WIDTH-1:0] result;
    
    wire [DATA_WIDTH-1:0] multResult;
    wire [DATA_WIDTH-1:0] addResult;
    
    floatMult16 FM (floatA,floatB,multResult);
    floatAdd16 FADD (multResult,result,addResult);
    
    always @ (posedge clk or posedge reset) begin
    	if (reset == 1'b1) begin
    		result = 0;
    	end else begin
    		result = addResult;
    	end
    end
    
    endmodule
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    模块结构

    • floatA和floatB分别是image和filter中的一格数据,他们输入到PE里来进行运算。
    • 实例化floatMult16和floatAdd16,依"先乘后累加"的逻辑将他们连接起来。

    在这里插入图片描述

    ​ 值得注意的是,这里用到了latch的结构进行累加,即把输出addResult作为输入再次参与加运算

    时序逻辑分析

    在这里插入图片描述
    ① 每个时钟周期上升沿到来时,两个16bit数A和B输入进来。在很短的时间里(一个clk周期内)Mult模块计算出乘积结果AB,并交付于Add模块。

    ② 上一个时钟周期运算完的累加结果addResult输入到Add模块,在极短的时间内(一个clk周期内)与AB进行加运算,得到本次的累加结果sum+AB,交付给后方寄存器result。

    ③ 在下个时钟上升沿到来时,result内存储的累加结果更新为本次的运算结果。同时,result也作为本模块的输出。

    ④ 下一个时钟上升沿到来…

    对其上层模块CU的要求

    每一个时钟周期都必须输入新的两个数A和B,或者当没有新的卷积任务时将输入口置零。否则将会一直对同一格进行乘加造作,导致重复运算的错误。


    单窗口卷积块CU

    ​ CU是PE的上一层,负责完成一整个窗口卷积结果的输出。换言之,在每一个时钟上升沿到来时,CU需要将一个窗口内n*n个格的数依次输入给PE

    ​ 本工程中使用的filter大小是5*5单通道的,因此一个窗口的大小也是1*5*5=25格,也就是25*16=400bit。

    代码

    `timescale 100 ns / 10 ps
    
    module convUnit(clk,reset,image,filter,result);
    
    parameter DATA_WIDTH = 16;
    parameter D = 1; //depth of the filter
    parameter F = 5; //size of the filter
    
    input clk, reset;
    input [0:D*F*F*DATA_WIDTH-1] image, filter;
    output [0:DATA_WIDTH-1] result;
    
    reg [DATA_WIDTH-1:0] selectedInput1, selectedInput2;
    
    integer i;
    
    
    processingElement16 PE
    	(
    		.clk(clk),
    		.reset(reset),
    		.floatA(selectedInput1),
    		.floatB(selectedInput2),
    		.result(result)
    	);
    
    // The convolution is calculated in a sequential process to save hardware
    // The result of the element wise matrix multiplication is finished after (F*F+2) cycles (2 cycles to reset the processing element and F*F cycles to accumulate the result of the F*F multiplications) 
    always @ (posedge clk, posedge reset) begin
    	if (reset == 1'b1) begin // reset
    		i = 0;
    		selectedInput1 = 0;
    		selectedInput2 = 0;
    	end else if (i > D*F*F-1) begin 
    		selectedInput1 = 0;
    		selectedInput2 = 0;
    	end else begin
    		selectedInput1 = image[DATA_WIDTH*i+:DATA_WIDTH];
    		selectedInput2 = filter[DATA_WIDTH*i+:DATA_WIDTH];
    		i = i + 1;
    	end
    end
    
    endmodule
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44

    重要变量说明:

    • selectedInput1和 selectedInput2:在遍历时,分别存储image和filter的一格,输入到PE。
    • i :索引变量。

    逻辑分析

    ​ 其实逻辑非常清晰易懂:

    • 每个时钟上升沿,选择从DATA_WIDTH*i位置开始,往低位DATA_WIDTH位的数据(即一格16bit数据)。image的一格交给input1,filter的一格交给input2。
    • 当一个窗口全都交付运算(i > D*F*F-1)时,A与B均输入16bit的0,防止重复运算最后一格的数据。
    • 此模块的reset受其上层模块convLayerSingle控制。每完成一个窗口的卷积操作,中顿2个时钟周期,随后进行复位,重新开始新的卷积任务。

    (图片和卷积核本是二维数据矩阵,但经过了RFselector后被展平为一维数据,可以通过单变量索引拿取)


    开源项目github-URL:CNN-FPGA

  • 相关阅读:
    RabbitMQ(四)交换机Exchanges
    分布式链路追踪那点事——微服务总结(三)
    freeswitch-1.10.7性能测试
    计算机毕业设计(附源码)python智慧后勤系统
    轻松上手的VsCode:你的理想代码编辑器!
    HTML5和CSS3四属性总结一
    ASEMI快恢复二极管SF1606参数,SF1606图片,SF1606应用
    平板第三方电容笔怎么样?便宜的ipad触控笔推荐
    linux-openssl命令生成自签名证书和查看证书到期时间
    Python 基础入门指南,干货分享来啦!
  • 原文地址:https://blog.csdn.net/GalaxyerKw/article/details/133178652