1.功能要求:
输入图像大小为 256256。在clk时钟下进行 55均值滤波之后的结果。
难点分析,主要是时序分析和边界对齐等问题。
2.模块划分:
模块一:行数据的统计。图像数据中的行数据流在时钟下输出,每五个像素点计算一个累计和。
模块二:列数据的统计。对于模块一的输出数据流,在该模块中通过shift_ram ip核进行输出,输出的是5行数据流。
模块三:对于结果进行均值处理。主要实现的功能是累加和除以模板像素点。
模块一的设计:
该模块重点就是统计每一行中对应模板参数个数的像素和。最为常见的一种方法就是将数据进行连续的打拍,然后求和,但是这种方式消耗的加法器和寄存器较多,时钟开销为三个clk。
本文采用的是利用另外一种求和方法,对于连续的数据流而言,五个数求和的运算在操作是仅仅只是首和尾的两个数进行改变,中间的3个数仍然参与运算。所以可以得到如下的算法:
该算法的硬件结构为:
我在实现过程中,将最开始的四个数都进行直接求和操作。
//功能实现3、数据求和
always@(posedge clk )begin
if(din_vaild==1'b1 && din_vaild_r[KSZ]==1'b0)
sum<=sum+data_in;
else if(din_vaild==1'b1 && din_vaild_r[KSZ]==1'b1)
sum<=sum+diff;
else
sum<={16{1'b0}};
end
模块二设计:
模块二设计的过程中,我采用的是移位寄存器的方式实现。将每一个行的求和结果依次缓存进移位寄存器中,这里需要申请4个移位寄存器,寄存器的长度为每行数据的输出长度。赛灵思提供了相应的ip核,具体如下:
在设计中,主要是长度和选择,其次,就是需要将4个寄存器都串联起来,在程序中的实现方法就是首尾相连。具体如下:
//功能实现,将4个shift_ram 级联起来
shift_ram uut1(
.clk ( clk ),
.ce ( ce1 ),
.d ( sum_1d ),
.q ( row2 )
);
shift_ram uut2(
.clk ( clk ),
.d ( row2 ),
.ce ( ce1 ),
.q ( row3 )
);
shift_ram uut3(
.clk ( clk ),
.d ( row3 ),
.ce ( ce1 ),
.q ( row4 )
);
shift_ram uut4(
.clk ( clk ),
.d ( row4 ),
.ce ( ce1 ),
.q ( row5 )
);
模块设计三:
该模块的设计没有太大难度,重点在于对于除法运算的理解,在fpga中进行除法运算,一种方法是使用ip核,但是这种方法比较麻烦,输出结果中既包含了余数,也包含了商,并且输出结果较输入数据有一段时间的延时,具体可以参看相关资料。我在设计除法模块时主要采用的是数据移位的办法。具体如下:
计算过程中需要对数据进行处理:
在这个模块的实现过程中,重点实现除法,放大之后再缩小,使用左右移位进行除法运算,移位操作不需要延时,先算分子,再算分母。
具体代码如下:
//功能实现1、右移10位
always@(posedge clk or negedge reset_n)begin
if(!reset_n)begin
sum_1<=16'd0;
sum_2<=16'd0;
sum_3<=8'd0;
sum_4<=8'd0;
sum_5<=8'd0;
sum_6<=8'd0;
sum_7<=8'd0;
sum_8<=8'd0;
end
else if(dout_vaild2)begin
sum_1<=sum<<5;
sum_2<=sum<<3;
sum_3<=sum>>1;
sum_4<=sum>>2;
sum_5<=sum>>3;
sum_6<=sum>>4;
sum_7<=sum>>6;
sum_8<=sum>>7;
end
end
以上就是实现均值滤波的整个思路(非喜勿喷)。
3.思考与总结:
1.在实现过程中,主要是对于算法的理解,对于实际要求并没有太多的实现。比如图像大小,在实际应用中应该较大(1024*1024),我看移位寄存器的最大缓存长度为1088,感觉1024的图像实现也可以使用这种思路。
2.在实现过程中,对于数据的对齐操作比较晕,就只会数据打拍。并且以上的方法在实现过程中,结果并不包含边缘部分,即上下左右2行的数据。对于这点数据的处理不知道怎么处理,网上有说边缘不处理,直接输出,另外还有就是利用图像的镜像处理,扩充边界,突然想到卷积神经网络中的padding,哈哈。
3.没有实现板级验证,没有结合vga驱动显示看看具体效果。(以后在弄吧)