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

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

  要求:模拟一张分辨率为 10x5 的图片,图片的数据为 1~50,对其生成 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)模式则不需要对 din 信号进行打拍就能对齐。

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

  (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)模式,din数据打了一拍,所以整个过程消耗了 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 矩阵就生成了,总共耗费 2clk,即两个时钟周期。

四、问题引出

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

  (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教程

原文地址:https://www.cnblogs.com/xianyufpga/p/12401085.html