基于FPGA的3x3矩阵生成

参考文献
[1] https://www.cnblogs.com/xianyuIC/p/12401085.html

前言

  在数字图像处理中,很多图像算法的实现需要卷积操作,而图像卷积操作是以滑动窗为基础的,滑动窗大小可为1x1、3x3等。在实际应用中,图像数据基本上是实时输入到FPGA中,因此需要对数据进行行缓存才能同时输出3x3个并行数据。本文将介绍FPGA如何得到3x3数据核。

一、行缓存

  矩形窗口最常用的窗口有3x3和5x5模型,下面介绍3x3窗口的硬件实现方法:
1)通过2个或3个FIFO来实现;
2)通过2个或3个RAM来实现;
3)通过2个或3个Shift_Ram通过移位来实现;
  本设计主要用2个FIFO来实现3x3矩形窗口。3x3窗口本质上就是将窗口中的9个像素点在一个时钟周期下同时并行输出,然后再对9个数据进行相应的操作运算。但是图像数据在硬件中是按照时钟一个像素一个像素进行传输的,所以我们必须使用寄存器进行缓存相应行数的数据,再将输出同时输出。本设计采用的方法是,调用两次FIFOIP核,该FIFO的深度只要超过2行的数据个数就行,两个FIFO写数据相同,都是输入的像素数据,两个FIFO的读写信号通过行数的进行使能。其中一个FIFO从第1行开始读,不写最后一行,第二个FIFO从第2行开始读,不写最后2行。FIFO读写信号示意图如下:
在这里插入图片描述

  如此,从第3行数据开始,两个FIFO输出的数据核输入的数据形成3行平行的数据。

二、代码实现

  下面实现的是对二值图像进行行缓存并并行输出3x3的并行数据。可以通过简单的位宽修改成其他位宽的数据。需要注意的是FIFO的深度。

//耗时2clk
module  Matrix_3X3 
(
    input            clk,  
    input            rst_n,
         
    input            vs,
    input            hs,
    input            de,
    input            data_in,//输入的一位数据,二值化的数据
     
    output           matrix_vs,
    output           matrix_hs,
    output           matrix_de,
    output reg  matrix_p11,//0或者1
    output reg  matrix_p12, 
    output reg  matrix_p13,
    output reg  matrix_p21, 
    output reg  matrix_p22, 
    output reg  matrix_p23,
    output reg  matrix_p31, 
    output reg  matrix_p32, 
    output reg  matrix_p33
);
  
wire  row1_data;  
wire  row2_data;  
wire  read_vs;
wire  read_de;
//wire  data_bw;
reg  row3_data;  
reg  [1:0]  vs_r;
reg  [1:0]  hs_r;
reg  [1:0]  de_r;

assign read_vs    =  hs_r[0];
assign read_de    =  de_r[0];
assign matrix_vs  =  vs_r[1];
assign matrix_hs  =  hs_r[1];
assign matrix_de  =  de_r[1];//延迟两个周期产生矩阵

always@(posedge clk or negedge rst_n) begin
    if(!rst_n)
        row3_data <= 0;
    else begin
        if(de)
            row3_data <= data_in ;
        else
            row3_data <= row3_data ;
    end
end
//产生平行数据,1clk
line_shift  line_Shift_m0
(
    .clk          (clk),
    .vs           (vs),
    .de           (de),
    .rst_n        (rst_n),
    .shiftin        (data_in  ),   //二值化后的数据1bit,且取反,1代表白色,0代表黑色
    .taps2x         (row2_data),   
    .taps1x         (row1_data)    
);

always@(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        vs_r <= 0;
        hs_r <= 0;
        de_r <= 0;
    end
    else begin
        vs_r <= { vs_r[0],vs };
        hs_r <= { hs_r[0],hs };
        de_r <= { de_r[0],de };
    end
end

always@(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        {matrix_p11, matrix_p12, matrix_p13} <=  3'b0;//初始化为黑色
        {matrix_p21, matrix_p22, matrix_p23} <=  3'b0;
        {matrix_p31, matrix_p32, matrix_p33} <=  3'b0;
    end
    else if(read_vs) begin //延迟一个clk与输出的平行数据同步
                if(read_de) begin
                    {matrix_p11, matrix_p12, matrix_p13} <= {matrix_p12, matrix_p13, row1_data};
                    {matrix_p21, matrix_p22, matrix_p23} <= {matrix_p22, matrix_p23, row2_data};
                    {matrix_p31, matrix_p32, matrix_p33} <= {matrix_p32, matrix_p33, row3_data};
                end
                else begin
                    {matrix_p11, matrix_p12, matrix_p13} <= {matrix_p11, matrix_p12, matrix_p13};
                    {matrix_p21, matrix_p22, matrix_p23} <= {matrix_p21, matrix_p22, matrix_p23};
                    {matrix_p31, matrix_p32, matrix_p33} <= {matrix_p31, matrix_p32, matrix_p33};
                end	
    end
    else begin
        {matrix_p11, matrix_p12, matrix_p13} <=  3'b0;//数据无效区域补零,边缘补0
        {matrix_p21, matrix_p22, matrix_p23} <=  3'b0;
        {matrix_p31, matrix_p32, matrix_p33} <=  3'b0;
    end
end
 
endmodule 
//延迟一个clk
module line_shift
#(
    parameter H = 10'd768,//图像高
    parameter W = 10'd1024//图像宽
)
(
    input clk,
    input vs,
    input de,
    input rst_n,
    input   shiftin,  //输入的数据,延迟一个周期就是第三行数据,为什么?为了与第二第一行数据保持同步
    output  taps2x,   //输出的数据,第二行数据
    output  taps1x    //输出的数据,第一行数据   
);

wire rd_data1 ;//移位寄存器宽度1,深度1024
wire rd_data2 ;//第二级移位寄存器
assign taps2x = rd_data1;
assign taps1x = rd_data2;
reg [9:0] cnt_row;
reg de_d,vs_d;
always @(posedge clk or negedge rst_n)begin
    if(!rst_n)
        cnt_row<=10'd0;
    else if(!de && de_d)
        cnt_row<=cnt_row+1;
    else if(!vs && vs_d)
        cnt_row<=10'd0;
end

always @(posedge clk or negedge rst_n)begin
    if(!rst_n)begin
        de_d<=1'b0;vs_d<=1'b0;
    end
    else begin
        de_d<=de;vs_d<=vs;
    end
end
wire wr_en1,rd_en1,wr_en2,rd_en2;
assign wr_en1 = (de && cnt_row < H-1)? 1'b1:1'b0;//不写最后一行,0~766
assign rd_en1 = (de && cnt_row > 0  )? 1'b1:1'b0;//从第一行开始读,1~767
assign wr_en2 = (de && cnt_row < H-2)? 1'b1:1'b0;//不写最后两行,0~765
assign rd_en2 = (de && cnt_row > 1  )? 1'b1:1'b0;//从第二行开始读,2~767

//fifo深度 >= 2*W
 line_shift_fifo fifo_row2 (
  .clk                (clk       ),      // input
  .rst                (!rst_n    ),      // input
  .wr_en              (wr_en1    ),      // input
  .wr_data            (shiftin   ),      // input
  .wr_full            (          ),      // output
  .almost_full        (          ),      // output
  .rd_en              (rd_en1    ),      // input
  .rd_data            (rd_data1  ),      // output
  .rd_empty           (          ),      // output
  .almost_empty       (          )       // output
);


 line_shift_fifo fifo_row1 (
  .clk                (clk       ),      // input
  .rst                (!rst_n    ),      // input
  .wr_en              (wr_en2    ),      // input
  .wr_data            (shiftin   ),      // input
  .wr_full            (          ),      // output
  .almost_full        (          ),      // output
  .rd_en              (rd_en2    ),      // input
  .rd_data            (rd_data2  ),      // output
  .rd_empty           (          ),      // output
  .almost_empty       (          )       // output
);

endmodule
  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,针对你的问题,以下是基于FPGA矩阵键盘实验任务的一些思路: 1. 实验目的 本实验旨在通过FPGA实现矩阵键盘的识别和控制,学习FPGA的IO口配置,数字电路设计和Verilog HDL语言编写,以及矩阵键盘的原理和工作方式。 2. 实验原理 矩阵键盘是一种常用的输入设备,它由多个按键按照一定的规律排列组成,可以通过行和列的扫描来检测按键状态。在FPGA中,可以通过GPIO口配置为输入和输出,并使用Verilog HDL语言编写数字电路实现对矩阵键盘的扫描和解码。 3. 实验步骤 (1) 硬件设计 根据矩阵键盘的规格,确定行列数和按键个数,设计电路图并布线,将行和列分别连接到FPGA的GPIO口。 (2) Verilog HDL编写 根据矩阵键盘的工作原理,编写Verilog HDL代码实现扫描和解码,将按键状态转换为数字信号输出到FPGA的其他模块进行处理。 (3) 系统集成和测试 将硬件和Verilog HDL代码集成在一起,进行功能测试和性能评估,如检测按键的灵敏度、误触率和响应时间等,优化设计并提高可靠性。 4. 实验要求 (1) 硬件设计符合规范,布线清晰、简洁、美观。 (2) Verilog HDL代码编写规范、清晰、易于理解,功能完备、稳定、可靠。 (3) 系统测试结果准确、可靠、稳定,性能达到预期要求。 以上是关于基于FPGA矩阵键盘实验任务的一些思路和要求,希望能对你有所帮助。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值