生成3x3矩阵(1):FIFO法

  在对图像进行处理时经常用到矩阵操作,本篇博客介绍一下用两个FIFO生成 3x3 矩阵的方法,并对其进行验证。

  要求:模拟一张分辨率为 10x5 的图片,图片的数据为 1~50,用Verilog对其生成 3x3 矩阵,以便后面的图像处理。

   testbench:数据的使能和数据完美对齐,每隔 10 个数据就空闲小段时间,每隔 50 个数据又空闲一段时间,尽可能的模仿图像帧的样子,如下所示:

 

一、计数器行列规划

  数据是 1-50,分为 10 列 5 行,首先想到是用两个计数器将数据按行列来划分。

  第一个计数器为 col_cnt,计10下。第二个计数器为 row_cnt,计5下。这样数据就人为的划分成了10x5,如下图所示:

二、调用两个FIFO形成3行数据

  1、生成一个同步 FIFO IP核,深度只要是超过 2 行的数据个数就行,例如这里一行数据个数是10个,FIFO的深度就选为32。模式选为 normal(standard)模式,其他信号可以都不勾选。

  2、设计3x3模块,调用两次 FIFO IP 核,两个FIFO写数据相同,都是本模块进来的数据 din,两个FIFO的各种信号以后缀 1 和 2 来区分。两个FIFO的读写信号示意图如下所示:

这样设置的话,从第 3 行 din 来开始,q_1、q_2 和新进来的数据din就能形成 3 行平行数据,代码书写如下:

assign wr_en_1 = (cnt_row < 4) ? din_vld : 1'b0; //不写最后1行
assign rd_en_1 = (cnt_row > 0) ? din_vld : 1'b0; //从第1行开始读
assign wr_en_2 = (cnt_row < 3) ? din_vld : 1'b0; //不写最后2行
assign rd_en_2 = (cnt_row > 1) ? din_vld : 1'b0; //从第2行开始读

  3、这样操作后,生成的波形会是怎么样呢?请看仿真:

  由波形看到 din_r(din打了一拍)和 q_1、q_2 信号在第三行数据时变成了平行的三行数据。为什么 din 信号要打一拍呢?是因为此次使用的FIFO模式为normal(standard)模式,给出其读使能过 1clk 后才出数据 q,因此 din 打了一拍后就能和 q_1、q_2对齐了。如果 FIFO 使用的是 show-ahead(first word fall through)模式,

  从波形中我们还可以得出一些信息:

  (1)来前两行数据时,din_r 和 q_1、q_2 形成的三行数据不完整,从第3行数据时才算完整。

  (2)din_r、q_1、q_2的顺序和我们的数据排列相比是倒的,要符合人的正常思维,正确的顺序是:q_2、q_1、din_r。

  (3)形成3行数据后,由于FIFO选用的是 normal(standard)模式,所以整个过程看作是消耗了 1clk。

三、打 3 拍形成 3x3 矩阵

  获得了上述的波形后,我们采用打拍即可完成矩阵的生成,上面说了数据是倒的,因此选择矩阵数据时,我们把数据的编号正过来。

//矩阵数据选取,1clk
//---------------------------------------------------
assign row_1 = q_2;
assign row_2 = q_1;
always @(posedge clk or negedge rst_n) begin
    if(!rst_n)
        row_3 <= 'd0;
    else
        row_3 <= din;
end

  这里 row_3 就是原本的 din_r,命名将顺序正过来后,后面打拍也就更能理解了。

//打拍形成矩阵,矩阵顺序归正,1clk
//---------------------------------------------------
always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        {matrix_11, matrix_12, matrix_13} <= {8'd0, 8'd0, 8'd0};
        {matrix_21, matrix_22, matrix_23} <= {8'd0, 8'd0, 8'd0};
        {matrix_31, matrix_32, matrix_33} <= {8'd0, 8'd0, 8'd0};
    end
    else begin
        {matrix_11, matrix_12, matrix_13} <= {matrix_12, matrix_13, row_1};
        {matrix_21, matrix_22, matrix_23} <= {matrix_22, matrix_23, row_2};
        {matrix_31, matrix_32, matrix_33} <= {matrix_32, matrix_33, row_3};
    end
end

  最后形成的矩阵波形如下所示:

  由波形见得,最后生成的矩阵是成功的,该矩阵的观看顺序是从上到下,一列一列的看,例如第一矩阵是:{000,000,001},第二个矩阵是:{000,000,012}。此外由于矩阵是打拍形成的,也耗费了 1clk 。至此,我们的 3x3 矩阵就生成了,还是挺简单的。

四、问题引出

  如果只是做到这样,其实已经能做图像处理了,但是细细品味这些波形会发现很多小问题。我们会产生一些疑问:

  (1)换行时的数据很怪,如第 4 行数据的第一个矩阵是{10,10,11,20,20,21,30,30,31},这是什么鬼?

  (2)换帧时的数据更怪,虽然第一帧图片前面的矩阵很多都是0,但第二帧图片前面的矩阵很多都是上一帧图片遗留的数据,怎么办?

  (3)这个矩阵进行图像处理,实际效果怎么样?

  (4)show-ahead(first word fall through)模式的话又会是什么情况?

  (5)对于上面的问题,有改进的办法吗?

   这篇博客已经有些长度了,对这些问题我们再开下一篇博客继续分析!

参考资料:

    [1]V3学院FPGA教程

    [2]CrazyBingo 图像处理教程

    [3]NingheChuan 图像处理教程

猜你喜欢

转载自www.cnblogs.com/xianyufpga/p/12401085.html