基于FPGA的图像边缘检测实现(二)

一、 主要内容:对SCCB模块做下简要的说明

二、 SCCB是串行摄像机控制总线协议(Serial Camera Control Bus
)的英文简称 ,它控制着摄像头大部分的功能,包括图像数据格式、分辨率以及图像处理参数等 ,它有两线和三线两种,3线SCCB接口可以对多个从器件控制,两线只能控制一个从机,本次只控制一个OV7670摄像头,用两线的SCCB即可对摄像头进行配置。

三、 下图是两线模式的基本时序图,其中SIO_C是时钟线,本工程设为100KHz,SIO_D为数据线,开始时,SIO_D信号拉低到SIO_C拉低之间的时间间隔要大于100ns;结束时,SIO_D拉高到SIO_C拉高时间间隔要大于100ns。SIO_D的数据在SIO_C低电平开始变化

SCCB基本时序图
四、 读写流程
1、字节格式
字节格式
2. 写 一般在写寄存器的过程中先发送设备的ID地址(ID Address),然后发送写数据的目地寄存器地址(Sub_address),最后发送要写入的数据(Write Data),本次工程使用的是OV7670,其中Address=8’h42,Sub_addr=8’h12,wdata=8’h04,x为都置1.
3.读 读如下图所示,其中Address(W)=8’h42,Sub_addr=8’h12,Address®=8’h43,最后数据FPGA可以从SIO_D中读取到数据
在这里插入图片描述
五、下表为此模块的接口信号列表
在这里插入图片描述
六、verilog代码

/***********Filename ﹕sccb .v**************

************Author ﹕Wenliang Zhou*********

************Description ﹕SCCB**********

************Revision time﹕2019.08.02**********

************Email  2253226757@qq.com﹕**********

***********/

module sccb(
    clk       ,
    rst_n     ,
    ren       ,
    wen       ,
    sub_addr  ,
    rdata     ,
    rdata_vld ,
    wdata     ,
    rdy       ,
    sio_c     ,
    sio_d_r   ,
    en_sio_d_w,
    sio_d_w         
);

    //锟斤拷锟斤拷锟斤拷锟斤拷
    parameter      SIO_C  = 120 ; 

    //输入引脚定义
    input               clk      ;//25m
    input               rst_n    ;
    input               ren      ;
    input               wen      ;
    input [7:0]         sub_addr ;
    input [7:0]         wdata    ;
	input               sio_d_r   ;
    //输出引脚定义
    output[7:0]         rdata    ;
    output              rdata_vld;
    output              sio_c    ;//208kHz
    output              rdy      ;
    output              en_sio_d_w;
    output              sio_d_w   ;
   
    
    reg [7:0]           rdata    ;
    reg                 rdata_vld;
    reg                 sio_c    ;
    reg                 rdy      ;
	reg                 en_sio_d_w;
    reg                 sio_d_w   ;

    //定义
    reg  [7:0]          count_sck     ;
    reg  [4:0]          count_bit     ;
    reg  [1:0]          count_duan    ;
    reg                 flag_r        ;
    reg                 flag_w        ;
    reg  [4:0]          bit_num       ;
    reg  [1:0]          duan_num      ;
    reg  [29:0]         out_data      ;

    wire                add_count_sck ;
    wire                end_count_sck ;
    wire                add_count_bit ;
    wire                end_count_bit ;
    wire                add_count_duan;
    wire                end_count_duan;
    wire                sio_c_h2l     ;
    wire                sio_c_l2h     ;
    wire                en_sio_d_w_h2l;
    wire                en_sio_d_w_l2h;
    wire                out_data_time ;
    wire                rdata_time    ;
    wire [7:0]          rd_com        ;
    
    always  @(posedge clk or negedge rst_n)begin
        if(rst_n==1'b0)begin
            count_sck <= 0;
        end
        else if(add_count_sck)begin
            if(end_count_sck)begin
                count_sck <= 0;
            end
            else begin
                count_sck <= count_sck + 1;
            end
        end
    end

    assign add_count_sck = flag_r || flag_w;
    assign end_count_sck = add_count_sck && count_sck == SIO_C-1;

    always  @(posedge clk or negedge rst_n)begin
        if(rst_n==1'b0)begin
            count_bit <= 0;
        end
        else if(add_count_bit)begin
            if(end_count_bit)begin
                count_bit <= 0;
            end
            else begin
                count_bit <= count_bit + 1;
            end
        end
    end

    assign add_count_bit = end_count_sck;
    assign end_count_bit = add_count_bit && count_bit == bit_num+2-1;

    always  @(posedge clk or negedge rst_n)begin
        if(rst_n==1'b0)begin
            count_duan <= 0;
        end
        else if(add_count_duan)begin
            if(end_count_duan)begin
                count_duan <= 0;
            end
            else begin
                count_duan <= count_duan + 1;
            end
        end
    end

    assign add_count_duan = end_count_bit;
    assign end_count_duan = add_count_duan && count_duan == duan_num-1;

    always  @(posedge clk or negedge rst_n)begin
        if(rst_n==1'b0)begin
            flag_r <= 0;
        end
        else if(ren)begin
            flag_r <= 1;
        end
        else if(end_count_duan)begin
            flag_r <= 0;
        end
    end

    always  @(posedge clk or negedge rst_n)begin
        if(rst_n==1'b0)begin
            flag_w <= 0;
        end
        else if(wen)begin
            flag_w <= 1;
        end
        else if(end_count_duan)begin 
            flag_w <= 0;
        end
    end

    always  @(*)begin
        if(flag_r)begin
            bit_num = 21;
            duan_num = 2;
        end
        else if(flag_w)begin
            bit_num = 30;
            duan_num = 1;
        end
        else begin
            bit_num = 1;
            duan_num = 1;
        end
    end

    always  @(posedge clk or negedge rst_n)begin
        if(rst_n==1'b0)begin
            sio_c <= 1;
        end
        else if(sio_c_h2l)begin
            sio_c <= 0;
        end
        else if(sio_c_l2h)begin
            sio_c <= 1;
        end
    end

    assign sio_c_h2l = count_bit >= 0 && count_bit < (bit_num-2) && add_count_sck && count_sck == SIO_C-1;
    assign sio_c_l2h = count_bit >= 1 && count_bit < bit_num && add_count_sck && count_sck == SIO_C/2-1;


    always @ (*)begin
        if(flag_r)begin
            out_data <= {1'h0,rd_com,1'h1,sub_addr,1'h1,1'h0,1'h1,9'h0};
        end
        else if(flag_w)begin
            out_data <= {1'h0,8'h42,1'h1,sub_addr,1'h1,wdata,1'h1,1'h0,1'h1};
        end
        else begin
            out_data <= 0;
        end
    end

    assign rd_com = (flag_r && count_duan == 0)? 8'h42 : 8'h43;

    always  @(posedge clk or negedge rst_n)begin
        if(rst_n==1'b0)begin
            en_sio_d_w <= 0;
        end
        else if(ren || wen)begin
            en_sio_d_w <= 1;
        end
        else if(end_count_duan)begin
            en_sio_d_w <= 0;
        end
        else if(en_sio_d_w_h2l)begin
            en_sio_d_w <= 0;
        end
        else if(en_sio_d_w_l2h)begin
            en_sio_d_w <= 1;
        end
    end

    assign en_sio_d_w_h2l = flag_r && count_duan == 1 && count_bit == 10 && add_count_sck && count_sck == 1-1;
    assign en_sio_d_w_l2h = flag_r && count_duan == 1 && count_bit == 18 && add_count_sck && count_sck == 1-1;

    always  @(posedge clk or negedge rst_n)begin
        if(rst_n==1'b0)begin
            sio_d_w <= 1;
        end
        else if(out_data_time)begin
            sio_d_w <= out_data[30-count_bit-1];
        end
    end

    assign out_data_time = count_bit >= 0 && count_bit < bit_num && add_count_sck && count_sck == SIO_C/4-1;

    always  @(posedge clk or negedge rst_n)begin
        if(rst_n==1'b0)begin
            rdata <= 0;
        end
        else if(rdata_time)begin
            rdata[17-count_bit] <= sio_d_r;
        end
    end

    assign rdata_time = flag_r && count_duan==1 && count_bit>=10 && count_bit<18 && add_count_sck && count_sck==SIO_C/4*3-1;

    always  @(posedge clk or negedge rst_n)begin
        if(rst_n==1'b0)begin
            rdata_vld <= 0;
        end
        else if(flag_r && end_count_duan)begin
            rdata_vld <= 1;
        end
        else begin
            rdata_vld <= 0;
        end
    end

    always  @(*)begin
        if(ren || wen || flag_r || flag_w)begin
            rdy = 0;
        end
        else begin
            rdy = 1;
        end
    end

endmodule


六、

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值