下冰雹 · 7月19日

基于FPGA的数字视频信号处理器设计(附代码)

今天给大侠带来基于FPGA的数字视频信号处理器设计,由于篇幅较长,分三篇。今天带来第三篇,下篇,程序测试与运行。话不多说,上货。

前两篇放个超链接。

基于FPGA的数字视频信号处理器设计(上)

基于FPGA的数字视频信号处理器设计(中)

导读 

图像是用各种观测系统以不同形式和手段观测客观世界而获得的,可以直接或间接作用于人眼进而产生视知觉的实体。

随着电子技术和计算机技术的飞速发展,数字图像技术近年来得到极大的重视和长足的发展,并在科学研究、工业生产、医疗卫生、通信等方面得到广泛的应用。

视频信号由一系列连续的图像组成。对视频信号的处理已经成为数字图像处理领域中重要的一部分。例如机器人模式识别的过程就是一个视频信号处理的过程,电视制导导弹识别目标就是充分利用视频信号处理技术不断判断目标是否和预先设定目标图像一致。本篇将讲解如何用 FPGA 技术实现基本的视频信号处理。本篇的例子可以作为各位大侠进行视频信号处理时的一个参考,也可以在这个基础上根据需要进行扩展。

第三篇内容摘要:本篇会介绍程序测试与运行,包括测试程序、测试结果以及总结等相关内容。

五、程序测试与运行

由于整个 FPGA 程序包括 3 部分:处于 TOP 的主体程序,控制其他各个部分程序的运行;视频图像数据采集程序,从 SAA7113 获得数字图像数据并保存到 SRAM 中;SRAM 读写程序实现对 SRAM 的数据读写。测试程序需要仿真数据的全部流程。

5.1 测试程序

测试程序代码如下:


`include "timescale.v"
moduletst_saa7113(error,dsprst,xreset,saareset,ARDY,ED_O,ED_OEN_O,SRAM_1_EA,SRAM_2_EA,SRAM_1_O_ED,SRAM_2_O_ED);
    //内部寄存器
    reg reset;
    reg clk;//50MHz 时钟
    reg llck;//SAA7113 的时钟
    reg [7:0] vpo;//来自 saa7113 的图像数据
    reg capture;//采集数据标志
    reg toggle;//总线切换标志
    reg [1:0] rst;

    //输入
    input error;
    input dsprst,xreset,saareset;
    input ARDY;
    input [7:0] ED_O;
    input ED_OEN_O;
    input [18:0] SRAM_1_EA;
    input [7:0] SRAM_1_O_ED;
    input [18:0] SRAM_2_EA;
    input [7:0] SRAM_2_O_ED;

    //来自 dsp 的信号
    reg CE3_;
    reg ARE_;
    reg AWE_;
    reg [21:2] EA;
    reg [7:0] ED_I;

    //TO SRAM
    reg [7:0] SRAM_1_IN_ED;
    reg [7:0] SRAM_2_IN_ED;

    //wires
    //from saa7113
    wire SRAM_CE_;
    wire SRAM_OE_;
    wire SRAM_WE_;
    wire [18:0] la;
    wire [7:0] ld;

    //FROM DSP
    wire CE_SRAM;
    wire WE_SRAM;
    wire OE_SRAM;
    wire [7:0] ED_SRAM;
    wire [18:0] EA_SRAM;

    //连接各个子程序
    LWBSAA7113 L_SAA7113 (
                          .reset(reset),
                          .clk(clk),
                          .llck(llck),
                          .vpo(vpo),
                          .rst(rst),
                          .capture(capture),
                          .error(error),
                          .SRAM_CE_(SRAM_CE_),
                          .SRAM_OE_(SRAM_OE_),
                          .SRAM_WE_(SRAM_WE_),
                          .la(la),
                          .ld(ld)
                      );

    LWBDECODE L_DECODE (
                        .reset(reset),
                        .CE3_(CE3_),
                        .ARE_(ARE_),
                        .AWE_(AWE_),
                        .EA(EA),
                        .ED_I(ED_I),
                        .ED_O(ED_O),
                        .ED_OEN_O(ED_OEN_O),
                        .ARDY(ARDY),
                        .EA_SRAM(EA_SRAM),
                        .ED_SRAM(ED_SRAM),
                        .CE_SRAM(CE_SRAM),
                        .WE_SRAM(WE_SRAM),
                        .OE_SRAM(OE_SRAM),
                        .dsprst(dsprst),
                        .xreset(xreset),
                        .saareset(saareset)
                    );

    LWBBUSCHANGE L_BUSCHANGE (
                              .EA_SRAM(EA_SRAM),
                              .ED_SRAM(ED_SRAM),
                              .CE_SRAM(CE_SRAM),
                              .WE_SRAM(WE_SRAM),
                              .OE_SRAM(OE_SRAM),
                              .la(la),
                              .ld(ld),
                              .SRAM_CE_(SRAM_CE_),
                              .SRAM_WE_(SRAM_WE_),
                              .SRAM_OE_(SRAM_OE_),
                              .SRAM_1_IN_ED(SRAM_1_IN_ED),
                              .SRAM_2_IN_ED(SRAM_2_IN_ED),
                              .toggle(toggle),
                              .SRAM_1_EA(SRAM_1_EA),
                              .SRAM_1_O_ED(SRAM_1_O_ED),
                              .SRAM_2_EA(SRAM_2_EA),
                              .SRAM_2_O_ED(SRAM_2_O_ED)
                          );
    //产生时钟信号
    always #10 clk=~clk;
    always #20 llck = ~llck;
    initial
        begin
            $display("\n status : %t TestBench of saa7113 started! \n\n",$time);

            //initial value
            clk = 0;
            #7;
            llck =0;

            //reset
            reset = 1;

            //dsp 初始化
            ARE_ = 1;
            AWE_ = 1;
            CE3_ = 1;

            //初始化
            capture = 0;
            toggle = 1;
            #2;
            reset = 0;
            repeat(20) @(posedge clk);
            reset = 1'b1; // negate reset

            //dsp 读取数据内容
            SRAM_1_IN_ED = 8'h1d;
            SRAM_2_IN_ED = 8'h2d;

            //dsp 地址总线
            EA[21:16] = 6'b000000;
            EA[15:7] = 9'b000000000;
            EA[6:2]= 5'b00001;
            #5;
            CE3_ = 0;
            ARE_ = 0;
            //saa7113 输出内容
            capture = 1;
            #5;
            @(posedge llck) vpo = 8'haa;
            @(posedge llck) vpo = 8'hbb;
            @(posedge llck) vpo = 8'hcc;
            @(posedge llck) vpo = 8'hdd;
            @(posedge llck) vpo = 8'hee;

            //场同步信号
            //1
            @(posedge llck) vpo = 8'hff;//begin
            @(posedge llck) vpo = 8'h00;
            @(posedge llck) vpo = 8'h00;
            @(posedge llck) vpo = 8'b00100000;//sav

            //2
            @(posedge llck) vpo = 8'hff;//begin
            @(posedge llck) vpo = 8'h00;
            @(posedge llck) vpo = 8'h00;
            @(posedge llck) vpo = 8'b00100000;

            //数据开始
            @(posedge llck) vpo = 8'hff;//begin
            @(posedge llck) vpo = 8'h00;
            @(posedge llck) vpo = 8'h00;
            @(posedge llck) vpo = 8'b00000000;

            //data
            @(posedge llck) vpo = 8'h01;//Cb
            @(posedge llck) vpo = 8'h02;//Yb
            @(posedge llck) vpo = 8'h03;//Cr
            @(posedge llck) vpo = 8'h04;//Yr--1

            @(posedge llck) vpo = 8'h05;//Cb
            @(posedge llck) vpo = 8'h06;//Yb
            @(posedge llck) vpo = 8'h07;//Cr
            @(posedge llck) vpo = 8'h08;//Yr--2

            @(posedge llck) vpo = 8'h09;//Cb
            @(posedge llck) vpo = 8'h0a;//Yb
            @(posedge llck) vpo = 8'h0b;//Cr
            @(posedge llck) vpo = 8'h0c;//Yr--3

            @(posedge llck) vpo = 8'h0d;//Cb
            @(posedge llck) vpo = 8'h0e;//Yb
            @(posedge llck) vpo = 8'h0f;//Cr
            @(posedge llck) vpo = 8'h10;//Yr--4

            @(posedge llck) vpo = 8'h11;//Cb
            @(posedge llck) vpo = 8'h12;//Yb
            @(posedge llck) vpo = 8'h13;//Cr
            @(posedge llck) vpo = 8'h14;//Yr--5

            @(posedge llck) vpo = 8'h15;//Cb
            @(posedge llck) vpo = 8'h16;//Yb
            @(posedge llck) vpo = 8'h17;//Cr
            @(posedge llck) vpo = 8'h18;//Yr--6

            @(posedge llck) vpo = 8'h19;//Cb
            @(posedge llck) vpo = 8'h1a;//Yb
            @(posedge llck) vpo = 8'h1b;//Cr
            @(posedge llck) vpo = 8'h1c;//Yr--7

            @(posedge llck) vpo = 8'h1d;//Cb
            @(posedge llck) vpo = 8'h1e;//Yb
            @(posedge llck) vpo = 8'h1f;//Cr
            @(posedge llck) vpo = 8'h20;//Yr--8

            @(posedge llck) vpo = 8'h21;//Cb
            @(posedge llck) vpo = 8'h22;//Yb
            @(posedge llck) vpo = 8'h23;//Cr
            @(posedge llck) vpo = 8'h24;//Yr--9

            @(posedge llck) vpo = 8'h25;//Cb
            @(posedge llck) vpo = 8'h26;//Yb
            @(posedge llck) vpo = 8'h27;//Cr
            @(posedge llck) vpo = 8'h28;//Yr--10

            @(posedge llck) vpo = 8'h29;//Cb
            @(posedge llck) vpo = 8'h3a;//Yb
            @(posedge llck) vpo = 8'h3b;//Cr
            @(posedge llck) vpo = 8'h3c;//Yr--11

            //数据结束
            @(posedge llck) vpo = 8'hff;//ff
            @(posedge llck) vpo = 8'h00;//00
            @(posedge llck) vpo = 8'h00;//00
            @(posedge llck) vpo = 8'b01110000;//end of field 1

            #20;
            ARE_ = 1;
            capture = 0;
            #200;

            //开始切换
            toggle = 0;
            #100;
            ARE_ = 0;

            //开始采集数据
            capture = 1;

            //vertical blanking stage
            //1
            @(posedge llck) vpo = 8'hff;//begin
            @(posedge llck) vpo = 8'h00;
            @(posedge llck) vpo = 8'h00;
            @(posedge llck) vpo = 8'b00100000;//sav

            //2
            @(posedge llck) vpo = 8'hff;//begin
            @(posedge llck) vpo = 8'h00;
            @(posedge llck) vpo = 8'h00;
            @(posedge llck) vpo = 8'b00100000;

            //data start
            @(posedge llck) vpo = 8'hff;//begin
            @(posedge llck) vpo = 8'h00;
            @(posedge llck) vpo = 8'h00;
            @(posedge llck) vpo = 8'b00000000;

            //data
            @(posedge llck) vpo = 8'h01;//Cb
            @(posedge llck) vpo = 8'h02;//Yb
            @(posedge llck) vpo = 8'h03;//Cr
            @(posedge llck) vpo = 8'h04;//Yr--1

            @(posedge llck) vpo = 8'h05;//Cb
            @(posedge llck) vpo = 8'h06;//Yb
            @(posedge llck) vpo = 8'h07;//Cr
            @(posedge llck) vpo = 8'h08;//Yr--2

            @(posedge llck) vpo = 8'h09;//Cb
            @(posedge llck) vpo = 8'h0a;//Yb
            @(posedge llck) vpo = 8'h0b;//Cr
            @(posedge llck) vpo = 8'h0c;//Yr--3

            @(posedge llck) vpo = 8'h0d;//Cb
            @(posedge llck) vpo = 8'h0e;//Yb
            @(posedge llck) vpo = 8'h0f;//Cr
            @(posedge llck) vpo = 8'h10;//Yr--4

            @(posedge llck) vpo = 8'h11;//Cb
            @(posedge llck) vpo = 8'h12;//Yb
            @(posedge llck) vpo = 8'h13;//Cr
            @(posedge llck) vpo = 8'h14;//Yr--5

            @(posedge llck) vpo = 8'h15;//Cb
            @(posedge llck) vpo = 8'h16;//Yb
            @(posedge llck) vpo = 8'h17;//Cr
            @(posedge llck) vpo = 8'h18;//Yr--6

            @(posedge llck) vpo = 8'h19;//Cb
            @(posedge llck) vpo = 8'h1a;//Yb
            @(posedge llck) vpo = 8'h1b;//Cr
            @(posedge llck) vpo = 8'h1c;//Yr--7

            @(posedge llck) vpo = 8'h1d;//Cb
            @(posedge llck) vpo = 8'h1e;//Yb
            @(posedge llck) vpo = 8'h1f;//Cr
            @(posedge llck) vpo = 8'h20;//Yr--8

            @(posedge llck) vpo = 8'h21;//Cb
            @(posedge llck) vpo = 8'h22;//Yb
            @(posedge llck) vpo = 8'h23;//Cr
            @(posedge llck) vpo = 8'h24;//Yr--9

            @(posedge llck) vpo = 8'h25;//Cb
            @(posedge llck) vpo = 8'h26;//Yb
            @(posedge llck) vpo = 8'h27;//Cr
            @(posedge llck) vpo = 8'h28;//Yr--10

            @(posedge llck) vpo = 8'h29;//Cb
            @(posedge llck) vpo = 8'h3a;//Yb
            @(posedge llck) vpo = 8'h3b;//Cr
            @(posedge llck) vpo = 8'h3c;//Yr--11

            //数据结束
            @(posedge llck) vpo = 8'hff;//ff
            @(posedge llck) vpo = 8'h00;//00
            @(posedge llck) vpo = 8'h00;//00
            @(posedge llck) vpo = 8'b01110000;//end of field 1
            #20;

            //结束数据采集
            capture = 0;

            #200;
            //测试程序结束
            $finish;
        end
endmodule

5.2 测试结果

仿真程序产生的视频图像数据如图 18 所示。开始的“aa bb cc dd ee ff”是无效数据,“ff 00 20”表示场同步信号。

image.png

经过 FPGA 处理后获得有效图像数据并产生相应的地址信号,如图 19 所示。由于只进行灰度运算,只取亮度信息,因此获得数据为“04 08 0c”,同时产生地址信号“00 01 02”。

image.png

对 SRAM 的读写控制,如图 20 所示。

image.png

两块 SRAM 之间的切换,如图 21 所示。

image.png

仿真结果表明整个视频信号处理程序完成了预先设定的设计目标。

七、总结

本篇首先介绍了视频信号的基本原理、组成等,然后讲解了进行视频信号处理的基本过程和框架。接下来结合实例讲解用 FPGA 及其他芯片组成视频处理的电路设计和 FPGA 的程序实现。最后用 Modelsim 仿真和测试了程序。本篇为各位大侠提供了一种视频信号处理的设计方案,仅供参考。

本篇到此结束,各位大侠,有缘再见!

END

作者: The last one
原文:FPGA技术江湖

相关文章推荐

更多FPGA干货请关注FPGA的逻辑技术专栏。欢迎添加极术小姐姐微信(id:aijishu20)加入技术交流群,请备注研究方向。
推荐阅读
关注数
10571
内容数
547
FPGA Logic 二三事
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息