明德扬小冉 发表于 2019-12-4 17:15:20

【基于FPGA的图像处理工程】边缘检测工程之摄像头配置模块代码解析

【基于FPGA的图像处理工程】                                                         —边缘检测工程:摄像头配置模块代码解析作者:肖肖肖

      本文为明德扬原创文章,转载请注明出处!
摄像头配置模块的功能: 根据摄像头配置指令模块ov7670_para的操作,产生对应的写寄存器命令、读寄存器命令给下游模块。具体功能如下:
1. 根据ov7670_para的参数,逐个配置或者读取寄存器;
2. 所有寄存器操作完成后,产生完成指示信号。


通过代码:`include“ov7670_para.v”,可以把边缘检测摄像头配置指令模块ov7670_para包含进本模块。


一、      设计架构


摄像头配置模块采用两个计数器的架构:计数器reg_cnt表示的是对要配置的164个寄存器进行计数,计数器rw_cnt表示判断写数据还是读数据的时序。例如,在写时序时,判断参数是否要写寄存器,如果要写寄存器,此时才产生写命令,如果参数是不要写寄存器,此时也不产生写命令。其结构图如下:

计数器rw_cnt:寄存器读写时序计数器。用来区分“向寄存器写数据”还是“从寄存器读数据”这两个状态。当其为0时,表示判断是否写寄存器的时序,当其为1时,表示判断是否读寄存器的时序。不管读写属性参数是什么,每个寄存器都会占有这两个时序。
计数器reg_cnt:寄存器顺序计数器。对摄像头164个寄存器进行排序,按顺序配置各个寄存器。




二、      信号意义



信号类型意义
clk输入信号时钟信号
rst_n输入信号复位信号,低电平有效。
config_en输入信号配置开始指示信号。
rdy输入信号当接收到该信号为1时,就开始对寄存器进行配置。
rdata输入信号下游sccb模块准备好指示信号。
rdata_vld输入信号0:下游sccb模块正忙,正在传输数据,不能向sccb发送配置指令;
wdata输出信号1:下游sccb模块空闲没有在传输数据,可以向sccb发送配置指令。
addr输出信号从 SCCB模块返回的读寄存器数据。没有用到
wr_en      输出信号此工程没有用到。
rd_en输出信号从SCCB模块返回的数据有效指示信号。没有用到
cmos_en输出信号此工程没有用到。
pwdn输出信号向下游SCCB模块配置寄存器的写数据,当写寄存器命令有效时,此数据才有效。
reg_cnt内部信号设计逻辑:该数据取自取摄像头配置指令的低8位,表示向需要配置的摄像头寄存器中写入的数据。
add_reg_cnt内部信号配置寄存器的读写地址,当写寄存器命令或者读寄存器命令有效时,此数据才有效。
end_reg_cnt内部信号设计逻辑:无论读还是写寄存器,其值均来自于取摄像头配置指令的第9位到第16位,表示需要操作的摄像头寄存器的地址。
flag_add内部信号写寄存器命令使能。
add_wdata内部信号设计逻辑:在“判断是否写时序”的时候,如果在配置指令中次高位为1,此时写寄存器命令有效。当开始对寄存器进行配置并且下游sccb模块准备好接收数据了(rdy=1),在sccb传输时序的写数据阶段时,摄像头配置指令的次高位为1,此时写使能为1,否则为0。
rw_cnt内部信号读寄存器命令使能。
add_rw_cnt内部信号设计逻辑:在“判断是否读时序”的时候,如果在配置指令中最高位为1,此时读寄存器命令有效,否则为0。当开始对寄存器进行配置并且下游sccb模块准备好接收数据了(rdy=1),在sccb传输时序的读数据阶段时,摄像头配置指令的最高位为1,此时读使能为1,否则为0。
end_rw_cnt内部信号下游摄像头图像采集cmos_capture模块使能信号。
三、参考代码 下面展出本模块的设计,欢迎进一步交流,如果需要源代码,欢迎与本人联系。
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137 moduleov7670_config(    clk       ,    rst_n   ,    config_en ,    rdy       ,    rdata   ,    rdata_vld ,    wdata   ,    addr      ,    wr_en          ,         rd_en      ,    cmos_en   ,     pwdn          );
    parameter      DATA_W =         8;    parameter      RW_NUM =         2;

    input               clk      ;//50Mhz    input               rst_n    ;    input               config_en;    input               rdy      ;    input rdata   ;    input               rdata_vld;
    outputwdata   ;    outputaddr    ;
    output            cmos_en;    output            wr_en    ;    output            rd_en    ;    output            pwdn   ;    regwdata    ;    regaddr   ;    reg               cmos_en;    reg               wr_en    ;    reg                rd_en    ;
    reg      reg_cnt;    wire                add_reg_cnt/*synthesis keep*/;    wire                end_reg_cnt/*synthesis keep*/;    reg               flag_add   ;    reg      add_wdata/*synthesiskeep*/;
    reg[ 1:0]      rw_cnt   ;    wire                add_rw_cnt ;
    assign            pwdn = 0;

    `include "ov7670_para.v"

    always @(posedge clk or negedge rst_n)begin      if(rst_n==1'b0)begin            reg_cnt <= 0;      end      else if(add_reg_cnt)begin            if(end_reg_cnt)                reg_cnt <= 0;            else                reg_cnt <= reg_cnt + 1;      end    end
    assign add_reg_cnt = end_rw_cnt;       assign end_reg_cnt = add_reg_cnt &®_cnt==REG_NUM-1;
    always @(posedge clk or negedge rst_n)begin      if(rst_n==1'b0)begin            rw_cnt <= 0;      end      else if(add_rw_cnt) begin            if(end_rw_cnt)                rw_cnt <= 0;            else                rw_cnt <= rw_cnt + 1;      end    end
    assign add_rw_cnt = flag_add && rdy;    assign end_rw_cnt = add_rw_cnt && rw_cnt==RW_NUM-1;


    always @(posedge clk or negedge rst_n)begin      if(rst_n==1'b0)begin            flag_add <= 1'b0;      end      else if(config_en)begin            flag_add <= 1'b1;      end      else if(end_reg_cnt)begin            flag_add <= 1'b0;      end    end
    //cmos_en    always @(posedge clk or negedge rst_n)begin      if(rst_n==1'b0)begin            cmos_en <= 1'b0;      end      else if(end_reg_cnt)begin            cmos_en <= 1'b1;      end    end

    //add_wdata
    always @(posedge clk or negedge rst_n)begin      if(rst_n==1'b0)begin            wdata <= 8'b0;      end      else begin            wdata <= add_wdata;      end    end
    always @(posedge clk or negedge rst_n)begin      if(rst_n==1'b0)begin            addr <= 8'b0;      end      else begin            addr <= add_wdata;      end    end

    //wr_en    always @(posedge clk or negedge rst_n)begin      if(rst_n==1'b0)begin            wr_en <= 1'b0;      end      else if(add_rw_cnt && rw_cnt==0&& add_wdata)begin            wr_en <= 1'b1;      end      else begin            wr_en <= 1'b0;      end    end

    always @(posedge clk or negedge rst_n)begin      if(rst_n==1'b0)begin            rd_en <= 1'b0;      end      else if(add_rw_cnt && rw_cnt==1&& add_wdata)begin            rd_en <= 1'b1;      end      else begin            rd_en <= 1'b0;      end    end

endmodule

      明德扬专注FPGA研究,我司正在连载两本书籍:《基于FPGA至简设计法实现的图像边缘检测系统》(http://www.fpgabbs.cn/forum.php?mod=viewthread&tid=691)、《ASIC和FPGA时序约束理论与应用》(http://www.fpgabbs.cn/forum.php?mod=viewthread&tid=705),有兴趣点击观看。也欢迎加入群(838209674),及时获取最新的文章信息,个性化问题也可以找我哦:Q1479512800(肖肖肖)。


页: [1]
查看完整版本: 【基于FPGA的图像处理工程】边缘检测工程之摄像头配置模块代码解析