• 基于FPGA的图像实时采集


    一、系统框架

    首先整个系统由摄像头模块、SDRAM数据缓存模块、vga显示模块、PLL时钟模块以及图像处理模块组成,这里先不用图像处理模块。
    在这里插入图片描述

    1.摄像头模块

    摄像头配置

    摄像头模块里面负责处理摄像头采集的数据,根据ov5640摄像头手册说明,我们需要先通过I2C协议去配置摄像头相关寄存器的参数。在摄像头上电后需要等待20ms。然后再通过I2C发送设备ID、写地址和数据,其中地址先发送高8位再发送低8位。这里包含摄像头时钟、图像大小、帧率以及其他和图像相关的参数。这里最重要的配置参数就是摄像头的图像分辨率和图像的色彩格式,这里通过配置的分辨率为1280*720,RGB565格式。

    摄像头数据处理

    根据时序图可以看到,当场同步信号到来后,会跟随着许多HREF数据有效信号,我们在HREF高电平的时候去采集数据即可。
    在这里插入图片描述
    但是摄像头的数据是把16位RGB拆分为高八位和低八位发送的,我们需要通过移位+位拼接的方式把两个8bit数据合并成16bit数据输出。同时为了SDRAM模块更好的识别帧头和帧尾,在图像的第一个像素点以及最后一个像素点的时候分别拉高sop和eop信号,其余像素点这拉低。

        always  @(posedge clk or negedge rst_n)begin
            if(~rst_n)begin
                data <= 0;
            end
            else begin
                data <= {data[7:0],din};//左移
            end
        end
    
        assign pixel = data;
        assign sop = cnt_h == 1 && cnt_v == 0;
        assign eop = data_eop;
        assign vld = cnt_h[0];
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    2.SDRAM模块

    SDRAM控制模块

    由于摄像头数据时钟(84M)和vga时钟(75M)不一样,为了避免读写数据速度不一致就需要把摄像头的数据进行缓存,常见的缓存可以通过fifo,但是这里的数据量十分庞大,故需要通过SDRAM进行缓存。缓存的方式则是通过乒乓缓存,把SDRAM的两个blank单独作为数据的写入和读出,并在读写完成后切换读写blank,并且需要通过丢帧和复读的操作来保证读写图像的完整性。

    SDRAM读写仲裁

    由于摄像头的数据输出和vga的数据请求都是源源不断的,此时到底是读还是写SDRAM就需要一个规则约束。首先为了保证写FIFO数据过多或者读FIFO数据过少。当写FIFO数据大于阈值后就会发起一个写请求,当读FIFO的数据低于阈值后就会发起读请求。仲裁机制根据读写请求进行仲裁,如果同一时间只有单独的读或者写请求直接执行即可,如果同时存在两种请求,则会根据上次执行的是读或者写来进行相反的请求。

    //flag_sel    ;//标记上一次操作
        always @(posedge clk or negedge rst_n)begin 
            if(!rst_n)begin
                flag_sel <= 0;
            end 
            else if(read2done)begin 
                flag_sel <= 1;
            end 
            else if(write2done)begin 
                flag_sel <= 0;
            end 
        end
    
    //prior_flag  ;//优先级标志 0:写优先级高   1:读优先级高     仲裁读、写的优先级
        always @(posedge clk or negedge rst_n)begin 
            if(!rst_n)begin
                prior_flag <= 0;
            end 
            else if(wr_flag && (flag_sel || (~flag_sel && ~rd_flag)))begin   //突发写优先级高
                prior_flag <= 1'b0;
            end 
            else if(rd_flag && (~flag_sel || (flag_sel && ~wr_flag)))begin   //突发读优先级高
                prior_flag <= 1'b1;
            end 
        end
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    SDRAM接口

    这里直接使用quartus自带的SDRAM接口ip。
    在这里插入图片描述
    需要注意的是SDRAM的blank数据是数据位的最高位和第10位,行地址为第23位到11位,列地址则为低9位当然前提是这里的为4blank13行9列。如图为ip接口部分源码
    在这里插入图片描述
    所以地址需要这样进行拼接

        assign avm_addr   = (state_c == WRITE)?{wr_bank[1],wr_addr[21:9],wr_bank[0],wr_addr[8:0]}
                           :((state_c == READ)?{rd_bank[1],rd_addr[21:9],rd_bank[0],rd_addr[8:0]}
                           :0);
    
    • 1
    • 2
    • 3

    读写FIFO

    整个SDRAM模块涉及到摄像头模块到SDRAM模块(慢时钟域到快时钟域),SDRAM数据到vga模块(快时钟域到慢时钟域)的跨时钟域数据同步的问题,这里使用两个异步FIFO来缓存两个跨时钟域的数据。

    首先是写FIFO(这里的读写相对于SDRAM)
    写FIFO的写使能条件是FIFO非满、输入数据有效、旧的一帧被vga读完且新的一帧到来或者是当前帧数据。
    写FIFO的读使能条件是当前需要往SDRAM写数据且FIFO非空,这里通过SDRAM控制模块的仲裁机制决定。

        assign wfifo_wrreq = ~wfifo_full & din_vld & ((~wr_finish_r[1] & din_sop) ||wr_data_flag);
        assign wfifo_rdreq = state_c == WRITE && ~avs_waitrequest;
    
    • 1
    • 2

    然后是读FIFO
    读FIFO的写使能是当前把SDRAM读出来的数据有效且FIFO非满
    读FIFO的读使能为当前FIFO非空且vga发起数据请求。

        assign rfifo_wrreq = ~rfifo_full & avs_rddata_vld;
        assign rfifo_rdreq = ~rfifo_empty & rdreq;
    
    • 1
    • 2

    3.vga显示模块

    vga显示这边使用1280*780@60HZ参数输出图像,在行场有效区域内通过拉发起请求读取读FIFO的数据内的数据,再输出到屏幕上面。可以参考前面的博客基于FPGA的VGA显示彩条、字符、图片,这里不多描述。

    4.PLL时钟模块

    整个系统由50M的基准时钟驱动,并且通过PLL生成配置摄像头的驱动时钟(24M)、SDRAM接口驱动时钟(100M),vga驱动时钟(75M)还有输出到SDRAM外设的100M带相位偏移的时钟。
    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述
    在这里插入图片描述

    二、部分模块实现代码

    1.摄像头配置

    I2C接口

    `include "param.v"
    
    module i2c_intf(
        input               clk         ,
        input               rst_n       ,
    
        input               req         ,
        input       [3:0]   cmd         ,
        input       [7:0]   din         ,
    
        output      [7:0]   dout        ,
        output              done        ,
        output              slave_ack   ,
        output              i2c_scl     ,
        input               i2c_sda_i   ,
        output              i2c_sda_o   ,
        output              i2c_sda_oe     
        );
    
    //状态机参数定义
    
        localparam  IDLE  = 7'b000_0001,
                    START = 7'b000_0010,
                    WRITE = 7'b000_0100,
                    RACK  = 7'b000_1000,
                    READ  = 7'b001_0000,
                    SACK  = 7'b010_0000,
                    STOP  = 7'b100_0000;
    
    //信号定义
    
        reg     [6:0]       state_c     ;
        reg     [6:0]       state_n     ;
    
        reg     [8:0]       cnt_scl     ;//产生i2c时钟
        wire                add_cnt_scl ;
        wire                end_cnt_scl ;
        reg     [3:0]       cnt_bit     ;//传输数据 bit计数器
        wire                add_cnt_bit ;
        wire                end_cnt_bit ;
        reg     [3:0]       bit_num     ;
        
        reg                 scl         ;//输出寄存器
        reg                 sda_out     ;
        reg                 sda_out_en  ;
    
        reg     [7:0]       rx_data     ;
        reg                 rx_ack      ;
        reg     [3:0]       command     ;
        reg     [7:0]       tx_data     ;//发送数据
    
        wire                idle2start  ; 
        wire                idle2write  ; 
        wire                idle2read   ; 
        wire                start2write ; 
        wire                start2read  ; 
        wire                write2rack  ; 
        wire                read2sack   ; 
        wire                rack2stop   ; 
        wire                sack2stop   ; 
        wire                rack2idle   ; 
        wire                sack2idle   ; 
        wire                stop2idle   ; 
    
    
    //状态机
        always @(posedge clk or negedge rst_n) begin 
            if (rst_n==0) begin
                state_c <= IDLE ;
            end
            else begin
                state_c <= state_n;
           end
        end
        
        always @(*) begin 
            case(state_c)  
                IDLE :begin
                    if(idle2start)
                        state_n = START ;
                    else if(idle2write)
                        state_n = WRITE ;
                    else if(idle2read)
                        state_n = READ ;
                    else 
                        state_n = state_c ;
                end
                START :begin
                    if(start2write)
                        state_n = WRITE ;
                    else if(start2read)
                        state_n = READ ;
                    else 
                        state_n = state_c ;
                end
                WRITE :begin
                    if(write2rack)
                        state_n = RACK ;
                    else 
                        state_n = state_c ;
                end
                RACK :begin
                    if(rack2stop)
                        state_n = STOP ;
                    else if(rack2idle)
                        state_n = IDLE ;
                    else 
                        state_n = state_c ;
                end
                READ :begin
                    if(read2sack)
                        state_n = SACK ;
                    else 
                        state_n = state_c ;
                end
                SACK :begin
                    if(sack2stop)
                        state_n = STOP ;
                    else if(sack2idle)
                        state_n = IDLE ;
                    else 
                        state_n = state_c ;
                end
                STOP :begin
                    if(stop2idle)
                        state_n = IDLE ;
                    else 
                        state_n = state_c ;
                end
                default : state_n = IDLE ;
            endcase
        end
        
        assign idle2start  = state_c==IDLE  && (req && (cmd&`CMD_START));
        assign idle2write  = state_c==IDLE  && (req && (cmd&`CMD_WRITE));
        assign idle2read   = state_c==IDLE  && (req && (cmd&`CMD_READ ));
        assign start2write = state_c==START && (end_cnt_bit && (command&`CMD_WRITE));
        assign start2read  = state_c==START && (end_cnt_bit && (command&`CMD_READ ));
        assign write2rack  = state_c==WRITE && (end_cnt_bit);
        assign read2sack   = state_c==READ  && (end_cnt_bit);
        assign rack2stop   = state_c==RACK  && (end_cnt_bit && (command&`CMD_STOP ));
        assign sack2stop   = state_c==SACK  && (end_cnt_bit && (command&`CMD_STOP ));
        assign rack2idle   = state_c==RACK  && (end_cnt_bit && (command&`CMD_STOP ) == 0);
        assign sack2idle   = state_c==SACK  && (end_cnt_bit && (command&`CMD_STOP ) == 0);
        assign stop2idle   = state_c==STOP  && (end_cnt_bit );
        
    //计数器
        always @(posedge clk or negedge rst_n) begin 
            if (rst_n==0) begin
                cnt_scl <= 0; 
            end
            else if(add_cnt_scl) begin
                if(end_cnt_scl)
                    cnt_scl <= 0; 
                else
                    cnt_scl <= cnt_scl+1 ;
           end
        end
        assign add_cnt_scl = (state_c != IDLE);
        assign end_cnt_scl = add_cnt_scl  && cnt_scl == (`SCL_PERIOD)-1 ;
    
        always @(posedge clk or negedge rst_n) begin 
            if (rst_n==0) begin
                cnt_bit <= 0; 
            end
            else if(add_cnt_bit) begin
                if(end_cnt_bit)
                    cnt_bit <= 0; 
                else
                    cnt_bit <= cnt_bit+1 ;
           end
        end
        assign add_cnt_bit = (end_cnt_scl);
        assign end_cnt_bit = add_cnt_bit  && cnt_bit == (bit_num)-1 ;
    
        always  @(*)begin
            if(state_c == WRITE | state_c == READ) begin
                bit_num = 8;
            end
            else begin 
                bit_num = 1;
            end 
        end
    //command
        always  @(posedge clk or negedge rst_n)begin
            if(~rst_n)begin
                command <= 0;
            end
            else if(req)begin
                command <= cmd;
            end
        end
    
    //tx_data
        always  @(posedge clk or negedge rst_n)begin
            if(~rst_n)begin
                tx_data <= 0;
            end
            else if(req)begin
                tx_data <= din;
            end
        end
    
    //scl
        always  @(posedge clk or negedge rst_n)begin
            if(~rst_n)begin
                scl <= 1'b1;
            end
            else if(idle2start | idle2write | idle2read)begin//开始发送时,拉低
                scl <= 1'b0;
            end
            else if(add_cnt_scl && cnt_scl == `SCL_HALF-1)begin 
                scl <= 1'b1;
            end 
            else if(end_cnt_scl && ~stop2idle)begin 
                scl <= 1'b0;
            end 
        end
    
    //sda_out
        always  @(posedge clk or negedge rst_n)begin
            if(~rst_n)begin
                sda_out <= 1'b1;
            end
            else if(state_c == START)begin          //发起始位
                if(cnt_scl == `LOW_HLAF)begin       //时钟低电平时拉高sda总线
                    sda_out <= 1'b1;
                end
                else if(cnt_scl == `HIGH_HALF)begin    //时钟高电平时拉低sda总线 
                    sda_out <= 1'b0;                //保证从机能检测到起始位
                end 
            end 
            else if(state_c == WRITE && cnt_scl == `LOW_HLAF)begin  //scl低电平时发送数据   并串转换
                sda_out <= tx_data[7-cnt_bit];      
            end 
            else if(state_c == SACK && cnt_scl == `LOW_HLAF)begin  //发应答位
                sda_out <= (command&`CMD_STOP)?1'b1:1'b0;
            end 
            else if(state_c == STOP)begin //发停止位
                if(cnt_scl == `LOW_HLAF)begin       //时钟低电平时拉低sda总线
                    sda_out <= 1'b0;
                end
                else if(cnt_scl == `HIGH_HALF)begin    //时钟高电平时拉高sda总线 
                    sda_out <= 1'b1;                //保证从机能检测到停止位
                end 
            end 
        end
    
    //sda_out_en  总线输出数据使能
        always  @(posedge clk or negedge rst_n)begin
            if(~rst_n)begin
                sda_out_en <= 1'b0;
            end
            else if(idle2start | idle2write | read2sack | rack2stop)begin
                sda_out_en <= 1'b1;
            end
            else if(idle2read | start2read | write2rack | stop2idle)begin 
                sda_out_en <= 1'b0;
            end 
        end
    
    //rx_data       接收读入的数据
        always  @(posedge clk or negedge rst_n)begin
            if(~rst_n)begin
                rx_data <= 0;
            end
            else if(state_c == READ && cnt_scl == `HIGH_HALF)begin
                rx_data[7-cnt_bit] <= i2c_sda_i;    //串并转换
            end
        end
    
    //rx_ack
        always  @(posedge clk or negedge rst_n)begin
            if(~rst_n)begin
                rx_ack <= 1'b1;
            end
            else if(state_c == RACK && cnt_scl == `HIGH_HALF)begin
                rx_ack <= i2c_sda_i;
            end
        end
    
    
    //输出信号
    
        assign i2c_scl    = scl         ;
        assign i2c_sda_o  = sda_out     ;
        assign i2c_sda_oe = sda_out_en  ;
       
        assign dout = rx_data;
        assign done = rack2idle | sack2idle | stop2idle;
        assign slave_ack = rx_ack;
    
    endmodule
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251
    • 252
    • 253
    • 254
    • 255
    • 256
    • 257
    • 258
    • 259
    • 260
    • 261
    • 262
    • 263
    • 264
    • 265
    • 266
    • 267
    • 268
    • 269
    • 270
    • 271
    • 272
    • 273
    • 274
    • 275
    • 276
    • 277
    • 278
    • 279
    • 280
    • 281
    • 282
    • 283
    • 284
    • 285
    • 286
    • 287
    • 288
    • 289
    • 290
    • 291
    • 292
    • 293
    • 294
    • 295

    摄像头配置

    `include "param.v"
    module cmos_config(
        input               clk         ,
        input               rst_n       ,
        //i2c_master
        output              req         ,
        output      [3:0]   cmd         ,
        output      [7:0]   dout        ,
        input               done        ,
        
        output              config_done 
    );
    
    //定义参数
    
        localparam  WAIT   = 4'b0001,//上电等待20ms
                    IDLE   = 4'b0010,
                    WREQ   = 4'b0100,//发写请求
                    WRITE  = 4'b1000;//等待一个字节写完
        parameter   DELAY  = 1000_000;//上电延时20ms开始配置
    //信号定义
    
        reg     [3:0]       state_c     ;
        reg     [3:0]       state_n     ;
        
        reg     [19:0]      cnt0        ;
        wire                add_cnt0/* synthesis syn_keep*/    ;
        wire                end_cnt0/* synthesis syn_keep*/    ;
        reg     [1:0]       cnt1        ;
        wire                add_cnt1/* synthesis syn_keep*/    ;
        wire                end_cnt1/* synthesis syn_keep*/    ;
        reg                 config_flag ;//1:表示在配置摄像头 0:表示配置完成
        reg     [23:0]      lut_data    ;
    
        reg                 tran_req    ; 
        reg      [3:0]      tran_cmd    ; 
        reg      [7:0]      tran_dout   ; 
    
        wire                wait2idle   ; 
        wire                idle2wreq   ; 
        wire                write2wreq  ; 
        wire                write2idle  ; 
    
    
    //状态机
    
        always  @(posedge clk or negedge rst_n)begin
            if(~rst_n)begin        
                state_c <= WAIT;
            end
            else begin
                state_c <= state_n;
            end
        end
    
        always  @(*)begin
            case(state_c)
                WAIT :begin 
                    if(wait2idle)
                       state_n = IDLE;
                    else 
                       state_n = state_c; 
                end 
                IDLE :begin 
                    if(idle2wreq)
                        state_n = WREQ; 
                    else 
                        state_n = state_c; 
                end  
                WREQ  :state_n = WRITE;
                WRITE :begin 
                    if(write2wreq)
                        state_n = WREQ; 
                    else if(write2idle)
                        state_n = IDLE;
                    else 
                        state_n = state_c; 
                end 
                default:state_n = IDLE; 
            endcase 
        end
    
        assign wait2idle  = state_c == WAIT  && end_cnt0; 
        assign idle2wreq  = state_c == IDLE  && config_flag; 
        assign write2wreq = state_c == WRITE && done && ~end_cnt1; 
        assign write2idle = state_c == WRITE && end_cnt1; 
    
    //计数器
        always @(posedge clk or negedge rst_n)begin
            if(!rst_n)begin
                cnt0 <= 0;
            end
            else if(add_cnt0)begin
                if(end_cnt0)
                    cnt0 <= 0;
                else
                    cnt0 <= cnt0 + 1;
            end
        end
        
        assign add_cnt0 = state_c == WAIT || state_c == WRITE && end_cnt1;
        assign end_cnt0 = add_cnt0 && cnt0 == ((state_c == WAIT)?(DELAY-1):(`REG_NUM-1));
    
        always @(posedge clk or negedge rst_n)begin 
            if(!rst_n)begin
                cnt1 <= 0;
            end
            else if(add_cnt1)begin
                if(end_cnt1)
                    cnt1 <= 0;
                else
                    cnt1 <= cnt1 + 1;
            end
        end
        
        assign add_cnt1 = state_c == WRITE && done;
        assign end_cnt1 = add_cnt1 && cnt1 == 4-1;
    
    //config_flag
        always  @(posedge clk or negedge rst_n)begin
            if(~rst_n)begin
                config_flag <= 1'b1;
            end
            else if(config_flag & end_cnt0 & state_c != WAIT)begin    //所有寄存器配置完,flag拉低
                config_flag <= 1'b0;
            end
        end
    
    //输出寄存器
    
        always  @(posedge clk or negedge rst_n)begin
            if(~rst_n)begin
                tran_req <= 0;
                tran_cmd <= 0;
                tran_dout <= 0;
            end
            else if(state_c == WREQ)begin
                case(cnt1)
                    0:begin 
                        tran_req <= 1;
                        tran_cmd <= {`CMD_START | `CMD_WRITE};
                        tran_dout <= `WR_ID;
                    end 
                    1:begin 
                        tran_req <= 1;
                        tran_cmd <= `CMD_WRITE;
                        tran_dout <= lut_data[23:16];
                    end
                    2:begin 
                        tran_req <= 1;
                        tran_cmd <= `CMD_WRITE;
                        tran_dout <= lut_data[15:8];
                    end
                    3:begin 
                        tran_req <= 1;
                        tran_cmd <= {`CMD_STOP | `CMD_WRITE};
                        tran_dout <= lut_data[7:0];
                    end
                    default:tran_req <= 0;
                endcase 
            end
    		else begin
    		    tran_req  <= 0;
                tran_cmd  <= 0;
                tran_dout <= 0;
    		end 
        end
    
    //输出
    
        assign config_done = ~config_flag;
        assign req = tran_req;
        assign cmd = tran_cmd;
        assign dout = tran_dout;
    
    
    //lut_data   
        always@(*)begin
    	    case(cnt0)			  
    		 //15fps VGA YUV output
    		 // 24MHz input clock, 84MHz PCLK
    		 0  :lut_data	= 	{24'h3103_11}; // system clock from pad, bit[1]
    		 1  :lut_data	= 	{24'h3008_82}; // software reset, bit[7]
    		 2  :lut_data	= 	{24'h3008_42}; // software power down, bit[6]
    		 3  :lut_data	= 	{24'h3103_03}; // system clock from PLL, bit[1]
    		 4  :lut_data	= 	{24'h3017_ff}; // FREX, Vsync, HREF, PCLK, D[9:6] output enable
    		 5  :lut_data	= 	{24'h3018_ff}; // D[5:0], GPIO[1:0] output enable
    		 6  :lut_data	= 	{24'h3034_1a}; // MIPI 10-bit
    		 7  :lut_data	= 	{24'h3037_13}; // PLL root divider, bit[4], PLL pre-divider, bit[3:0]
    		 8  :lut_data	= 	{24'h3108_01}; // PCLK root divider, bit[5:4], SCLK2x root divider, bit[3:2]
    		 9  :lut_data	= 	{24'h3630_36};//SCLK root divider, bit[1:0]
    		 10 :lut_data	= 	{24'h3631_0e};
    		 11 :lut_data	= 	{24'h3632_e2};
    		 12 :lut_data	= 	{24'h3633_12};
    		 13 :lut_data	= 	{24'h3621_e0};
    		 14 :lut_data	= 	{24'h3704_a0};
    		 15 :lut_data	= 	{24'h3703_5a};
    		 16 :lut_data	= 	{24'h3715_78};
    		 17 :lut_data	= 	{24'h3717_01};
    		 18 :lut_data	= 	{24'h370b_60};
    		 19 :lut_data	= 	{24'h3705_1a};
    		 20 :lut_data	= 	{24'h3905_02};
    		 21 :lut_data	= 	{24'h3906_10};
    		 22 :lut_data	= 	{24'h3901_0a};
    		 23 :lut_data	= 	{24'h3731_12};
    		 24 :lut_data	= 	{24'h3600_08}; // VCM control
    		 25 :lut_data	= 	{24'h3601_33}; // VCM control
    		 26 :lut_data	= 	{24'h302d_60}; // system control
    		 27 :lut_data	= 	{24'h3620_52};
    		 28 :lut_data	= 	{24'h371b_20};
    		 29 :lut_data	= 	{24'h471c_50};
    		 30 :lut_data	= 	{24'h3a13_43}; // pre-gain = 1.047x
    		 31 :lut_data	= 	{24'h3a18_00}; // gain ceiling
    		 32 :lut_data	= 	{24'h3a19_f8}; // gain ceiling = 15.5x
    		 33 :lut_data	= 	{24'h3635_13};
    		 34 :lut_data	= 	{24'h3636_03};
    		 35 :lut_data	= 	{24'h3634_40};
    		 36 :lut_data	= 	{24'h3622_01};
    		// 50/60Hz detection 50/60Hz 灯光条纹过滤
    		 37 :lut_data	= 	{24'h3c01_34}; // Band auto, bit[7]
    		 38 :lut_data	= 	{24'h3c04_28}; // threshold low sum
    		 39 :lut_data	= 	{24'h3c05_98}; // threshold high sum
    		 40 :lut_data	= 	{24'h3c06_00}; // light meter 1 threshold[15:8]
    		 41 :lut_data	= 	{24'h3c07_08}; // light meter 1 threshold[7:0]
    		 42 :lut_data	= 	{24'h3c08_00}; // light meter 2 threshold[15:8]
    		 43 :lut_data	= 	{24'h3c09_1c}; // light meter 2 threshold[7:0]
    		 44 :lut_data	= 	{24'h3c0a_9c}; // sample number[15:8]
    		 45 :lut_data	= 	{24'h3c0b_40}; // sample number[7:0]
    		 46 :lut_data	= 	{24'h3810_00}; // Timing Hoffset[11:8]
    		 47 :lut_data	= 	{24'h3811_10}; // Timing Hoffset[7:0]
    		 48 :lut_data	= 	{24'h3812_00}; // Timing Voffset[10:8]
    		 49 :lut_data	= 	{24'h3708_64};
    		 50 :lut_data	= 	{24'h4001_02}; // BLC start from line 2
    		 51 :lut_data	= 	{24'h4005_1a}; // BLC always update
    		 52 :lut_data	= 	{24'h3000_00}; // enable blocks
    		 53 :lut_data	= 	{24'h3004_ff}; // enable clocks
    		 54 :lut_data	= 	{24'h300e_58}; //MIPI power down,DVP enable
    		 55 :lut_data	= 	{24'h302e_00};
    		 56 :lut_data	= 	{24'h4300_61}; // RGB,
    		 57 :lut_data	= 	{24'h501f_01}; // ISP RGB
    		 58 :lut_data	= 	{24'h440e_00};
    		 59 :lut_data	= 	{24'h5000_a7}; // Lenc on, raw gamma on, BPC on, WPC on, CIP on
    		// AEC target 自动曝光控制
    		 60 :lut_data	= 	{24'h3a0f_30}; // stable range in high
    		 61 :lut_data	= 	{24'h3a10_28}; // stable range in low
    		 62 :lut_data	= 	{24'h3a1b_30}; // stable range out high
    		 63 :lut_data	= 	{24'h3a1e_26}; // stable range out low
    		 64 :lut_data	= 	{24'h3a11_60}; // fast zone high
    		 65 :lut_data	= 	{24'h3a1f_14}; // fast zone low
    		// Lens correction for ? 镜头补偿
    		 66 :lut_data	= 	{24'h5800_23};
    		 67 :lut_data	= 	{24'h5801_14};
    		 68 :lut_data	= 	{24'h5802_0f};
    		 69 :lut_data	= 	{24'h5803_0f};
    		 70 :lut_data	= 	{24'h5804_12};
    		 71 :lut_data	= 	{24'h5805_26};
    		 72 :lut_data	= 	{24'h5806_0c};
    		 73 :lut_data	= 	{24'h5807_08};
    		 74 :lut_data	= 	{24'h5808_05};
    		 75 :lut_data	= 	{24'h5809_05};
    		 76 :lut_data	= 	{24'h580a_08};
    		 77 :lut_data	= 	{24'h580b_0d};
    		 78 :lut_data	= 	{24'h580c_08};
    		 79 :lut_data	= 	{24'h580d_03};
    		 80 :lut_data	= 	{24'h580e_00};
    		 81 :lut_data	= 	{24'h580f_00};
    		 82 :lut_data	= 	{24'h5810_03};
    		 83 :lut_data	= 	{24'h5811_09};
    		 84 :lut_data	= 	{24'h5812_07};
    		 85 :lut_data	= 	{24'h5813_03};
    		 86 :lut_data	= 	{24'h5814_00};
    		 87 :lut_data	= 	{24'h5815_01};
    		 88 :lut_data	= 	{24'h5816_03};
    		 89 :lut_data	= 	{24'h5817_08};
    		 90 :lut_data	= 	{24'h5818_0d};
    		 91 :lut_data	= 	{24'h5819_08};
    		 92 :lut_data	= 	{24'h581a_05};
    		 93 :lut_data	= 	{24'h581b_06};
    		 94 :lut_data	= 	{24'h581c_08};
    		 95 :lut_data	= 	{24'h581d_0e};
    		 96 :lut_data	= 	{24'h581e_29};
    		 97 :lut_data	= 	{24'h581f_17};
    		 98 :lut_data	= 	{24'h5820_11};
    		 99 :lut_data	= 	{24'h5821_11};
    		 100:lut_data	= 	{24'h5822_15};
    		 101:lut_data	= 	{24'h5823_28};
    		 102:lut_data	= 	{24'h5824_46};
    		 103:lut_data	= 	{24'h5825_26};
    		 104:lut_data	= 	{24'h5826_08};
    		 105:lut_data	= 	{24'h5827_26};
    		 106:lut_data	= 	{24'h5828_64};
    		 107:lut_data	= 	{24'h5829_26};
    		 108:lut_data	= 	{24'h582a_24};
    		 109:lut_data	= 	{24'h582b_22};
    		 110:lut_data	= 	{24'h582c_24};
    		 111:lut_data	= 	{24'h582d_24};
    		 112:lut_data	= 	{24'h582e_06};
    		 113:lut_data	= 	{24'h582f_22};
    		 114:lut_data	= 	{24'h5830_40};
    		 115:lut_data	= 	{24'h5831_42};
    		 116:lut_data	= 	{24'h5832_24};
    		 117:lut_data	= 	{24'h5833_26};
    		 118:lut_data	= 	{24'h5834_24};
    		 119:lut_data	= 	{24'h5835_22};
    		 120:lut_data	= 	{24'h5836_22};
    		 121:lut_data	= 	{24'h5837_26};
    		 122:lut_data	= 	{24'h5838_44};
    		 123:lut_data	= 	{24'h5839_24};
    		 124:lut_data	= 	{24'h583a_26};
    		 125:lut_data	= 	{24'h583b_28};
    		 126:lut_data	= 	{24'h583c_42};
    		 127:lut_data	= 	{24'h583d_ce}; // lenc BR offset
    		// AWB 自动白平衡
    		 128:lut_data	= 	{24'h5180_ff}; // AWB B block
    		 129:lut_data	= 	{24'h5181_f2}; // AWB control
    		 130:lut_data	= 	{24'h5182_00}; // [7:4] max local counter, [3:0] max fast counter
    		 131:lut_data	= 	{24'h5183_14}; // AWB advanced
    		 132:lut_data	= 	{24'h5184_25};
    		 133:lut_data	= 	{24'h5185_24};
    		 134:lut_data	= 	{24'h5186_09};
    		 135:lut_data	= 	{24'h5187_09};
    		 136:lut_data	= 	{24'h5188_09};
    		 137:lut_data	= 	{24'h5189_75};
    		 138:lut_data	= 	{24'h518a_54};
    		 139:lut_data	= 	{24'h518b_e0};
    		 140:lut_data	= 	{24'h518c_b2};
    		 141:lut_data	= 	{24'h518d_42};
    		 142:lut_data	= 	{24'h518e_3d};
    		 143:lut_data	= 	{24'h518f_56};
    		 144:lut_data	= 	{24'h5190_46};
    		 145:lut_data	= 	{24'h5191_f8}; // AWB top limit
    		 146:lut_data	= 	{24'h5192_04}; // AWB bottom limit
    		 147:lut_data	= 	{24'h5193_70}; // red limit
    		 148:lut_data	= 	{24'h5194_f0}; // green limit
    		 149:lut_data	= 	{24'h5195_f0}; // blue limit
    		 150:lut_data	= 	{24'h5196_03}; // AWB control
    		 151:lut_data	= 	{24'h5197_01}; // local limit
    		 152:lut_data	= 	{24'h5198_04};
    		 153:lut_data	= 	{24'h5199_12};
    		 154:lut_data	= 	{24'h519a_04};
    		 155:lut_data	= 	{24'h519b_00};
    		 156:lut_data	= 	{24'h519c_06};
    		 157:lut_data	= 	{24'h519d_82};
    		 158:lut_data	= 	{24'h519e_38}; // AWB control
    		// Gamma 伽玛曲线
    		 159:lut_data	= 	{24'h5480_01}; //Gamma bias plus on, bit[0]
    		 160:lut_data	= 	{24'h5481_08};
    		 161:lut_data	= 	{24'h5482_14};
    		 162:lut_data	= 	{24'h5483_28};
    		 163:lut_data	= 	{24'h5484_51};
    		 164:lut_data	= 	{24'h5485_65};
    		 165:lut_data	= 	{24'h5486_71};
    		 166:lut_data	= 	{24'h5487_7d};
    		 167:lut_data	= 	{24'h5488_87};
    		 168:lut_data	= 	{24'h5489_91};
    		 169:lut_data	= 	{24'h548a_9a};
    		 170:lut_data	= 	{24'h548b_aa};
    		 171:lut_data	= 	{24'h548c_b8};
    		 172:lut_data	= 	{24'h548d_cd};
    		 173:lut_data	= 	{24'h548e_dd};
    		 174:lut_data	= 	{24'h548f_ea};
    		 175:lut_data	= 	{24'h5490_1d};
    		// color matrix 色彩矩阵
    		 176:lut_data	= 	{24'h5381_1e}; // CMX1 for Y
    		 177:lut_data	= 	{24'h5382_5b}; // CMX2 for Y
    		 178:lut_data	= 	{24'h5383_08}; // CMX3 for Y
    		 179:lut_data	= 	{24'h5384_0a}; // CMX4 for U
    		 180:lut_data	= 	{24'h5385_7e}; // CMX5 for U
    		 181:lut_data	= 	{24'h5386_88}; // CMX6 for U
    		 182:lut_data	= 	{24'h5387_7c}; // CMX7 for V
    		 183:lut_data	= 	{24'h5388_6c}; // CMX8 for V
    		 184:lut_data	= 	{24'h5389_10}; // CMX9 for V
    		 185:lut_data	= 	{24'h538a_01}; // sign[9]
    		 186:lut_data	= 	{24'h538b_98}; // sign[8:1]
    		// UV adjust UV 色彩饱和度调整
    		 187:lut_data	= 	{24'h5580_06}; // saturation on, bit[1]
    		 188:lut_data	= 	{24'h5583_40};
    		 189:lut_data	= 	{24'h5584_10};
    		 190:lut_data	= 	{24'h5589_10};
    		 191:lut_data	= 	{24'h558a_00};
    		 192:lut_data	= 	{24'h558b_f8};
    		 193:lut_data	= 	{24'h501d_40}; // enable manual offset of contrast
    		// CIP 锐化和降噪
    		 194:lut_data	= 	{24'h5300_08}; //CIP sharpen MT threshold 1
    		 195:lut_data	= 	{24'h5301_30}; //CIP sharpen MT threshold 2
    		 196:lut_data	= 	{24'h5302_10}; // CIP sharpen MT offset 1
    		 197:lut_data	= 	{24'h5303_00}; // CIP sharpen MT offset 2
    		 198:lut_data	= 	{24'h5304_08}; // CIP DNS threshold 1
    		 199:lut_data	= 	{24'h5305_30}; // CIP DNS threshold 2
    		 200:lut_data	= 	{24'h5306_08}; // CIP DNS offset 1
    		 201:lut_data	= 	{24'h5307_16}; // CIP DNS offset 2
    		 202:lut_data	= 	{24'h5309_08}; //CIP sharpen TH threshold 1
    		 203:lut_data	= 	{24'h530a_30}; //CIP sharpen TH threshold 2
    		 204:lut_data	= 	{24'h530b_04}; //CIP sharpen TH offset 1
    		 205:lut_data	= 	{24'h530c_06}; //CIP sharpen TH offset 2
    		 206:lut_data	= 	{24'h5025_00};
    		 207:lut_data	= 	{24'h3008_02}; //wake up from standby,bit[6]
    		// input clock 24Mhz, PCLK 84Mhz
    		 208:lut_data	= 	{24'h3035_21}; // PLL
    		 209:lut_data	= 	{24'h3036_69}; // PLL
    		 210:lut_data	= 	{24'h3c07_07}; // lightmeter 1 threshold[7:0]
    		 211:lut_data	= 	{24'h3820_47}; // flip
    		 212:lut_data	= 	{24'h3821_01}; // no mirror
    		 213:lut_data	= 	{24'h3814_31}; // timing X inc
    		 214:lut_data	= 	{24'h3815_31}; // timing Y inc
    		 215:lut_data	= 	{24'h3800_00}; // HS
    		 216:lut_data	= 	{24'h3801_00}; // HS
    		 217:lut_data	= 	{24'h3802_00}; // VS
    		 218:lut_data	= 	{24'h3803_fa}; // VS
    		 219:lut_data	= 	{24'h3804_0a}; // HW  :   	 
    		 220:lut_data	= 	{24'h3805_3f}; // HW  :   	
    		 221:lut_data	= 	{24'h3806_06}; // VH  :   	
    		 222:lut_data	= 	{24'h3807_a9}; // VH  :   	
    		 223:lut_data	= 	{24'h3808_05}; // DVPHO 1280
    		 224:lut_data	= 	{24'h3809_00}; // DVPHO
    		 225:lut_data	= 	{24'h380a_02}; // DVPVO 720
    		 226:lut_data	= 	{24'h380b_d0}; // DVPVO
    		 227:lut_data	= 	{24'h380c_07}; // HTS
    		 228:lut_data	= 	{24'h380d_64}; // HTS
    		 229:lut_data	= 	{24'h380e_02}; // VTS
    		 230:lut_data	= 	{24'h380f_e4}; // VTS
    		 231:lut_data	= 	{24'h3813_04}; // timing V offset
    		 232:lut_data	= 	{24'h3618_00};
    		 233:lut_data	= 	{24'h3612_29};
    		 234:lut_data	= 	{24'h3709_52};
    		 235:lut_data	= 	{24'h370c_03};
    		 236:lut_data	= 	{24'h3a02_02}; // 60Hz max exposure
    		 237:lut_data	= 	{24'h3a03_e0}; // 60Hz max exposure
    		 238:lut_data	= 	{24'h3a14_02}; // 50Hz max exposure
    		 239:lut_data	= 	{24'h3a15_e0}; // 50Hz max exposure
    		 240:lut_data	= 	{24'h4004_02}; // BLC line number
    		 241:lut_data	= 	{24'h3002_1c}; // reset JFIFO, SFIFO, JPG
    		 242:lut_data	= 	{24'h3006_c3}; // disable clock of JPEG2x, JPEG
    		 243:lut_data	= 	{24'h4713_03}; // JPEG mode 3
    		 244:lut_data	= 	{24'h4407_04}; // Quantization scale
    		 245:lut_data	= 	{24'h460b_37};
    		 246:lut_data	= 	{24'h460c_20};
    		 247:lut_data	= 	{24'h4837_16}; // MIPI global timing
    		 248:lut_data	= 	{24'h3824_04}; // PCLK manual divider
    		 249:lut_data	= 	{24'h5001_83}; // SDE on, CMX on, AWB on
    		 250:lut_data	= 	{24'h3503_00}; // AEC/AGC on             
    		 251:lut_data	= 	{24'h4740_20}; // VS 1
    		 252:lut_data	= 	{24'h503d_00}; // color bar
    		 253:lut_data	= 	{24'h4741_00}; //
    		default:lut_data	=	0;
    	    endcase
        end
    
    endmodule 
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251
    • 252
    • 253
    • 254
    • 255
    • 256
    • 257
    • 258
    • 259
    • 260
    • 261
    • 262
    • 263
    • 264
    • 265
    • 266
    • 267
    • 268
    • 269
    • 270
    • 271
    • 272
    • 273
    • 274
    • 275
    • 276
    • 277
    • 278
    • 279
    • 280
    • 281
    • 282
    • 283
    • 284
    • 285
    • 286
    • 287
    • 288
    • 289
    • 290
    • 291
    • 292
    • 293
    • 294
    • 295
    • 296
    • 297
    • 298
    • 299
    • 300
    • 301
    • 302
    • 303
    • 304
    • 305
    • 306
    • 307
    • 308
    • 309
    • 310
    • 311
    • 312
    • 313
    • 314
    • 315
    • 316
    • 317
    • 318
    • 319
    • 320
    • 321
    • 322
    • 323
    • 324
    • 325
    • 326
    • 327
    • 328
    • 329
    • 330
    • 331
    • 332
    • 333
    • 334
    • 335
    • 336
    • 337
    • 338
    • 339
    • 340
    • 341
    • 342
    • 343
    • 344
    • 345
    • 346
    • 347
    • 348
    • 349
    • 350
    • 351
    • 352
    • 353
    • 354
    • 355
    • 356
    • 357
    • 358
    • 359
    • 360
    • 361
    • 362
    • 363
    • 364
    • 365
    • 366
    • 367
    • 368
    • 369
    • 370
    • 371
    • 372
    • 373
    • 374
    • 375
    • 376
    • 377
    • 378
    • 379
    • 380
    • 381
    • 382
    • 383
    • 384
    • 385
    • 386
    • 387
    • 388
    • 389
    • 390
    • 391
    • 392
    • 393
    • 394
    • 395
    • 396
    • 397
    • 398
    • 399
    • 400
    • 401
    • 402
    • 403
    • 404
    • 405
    • 406
    • 407
    • 408
    • 409
    • 410
    • 411
    • 412
    • 413
    • 414
    • 415
    • 416
    • 417
    • 418
    • 419
    • 420
    • 421
    • 422
    • 423
    • 424
    • 425
    • 426
    • 427
    • 428
    • 429
    • 430
    • 431
    • 432
    • 433
    • 434
    • 435
    • 436
    • 437
    • 438
    • 439
    • 440
    • 441
    • 442
    • 443
    • 444
    • 445
    • 446
    • 447
    • 448
    • 449
    • 450
    • 451

    摄像头数据处理

    `include "param.v"
    module capture (
        input			wire						clk,
        input			wire						rst_n,
        input			wire						vsync,
        input			wire						href,
        input			wire		[ 7:0 ]		    din,
        input			wire						din_vld,
    
        output			wire						sop,
        output			wire						eop,
        output			wire						vld,
        output			wire		[ 15:0 ]		pixel	
    );
    // localparam	red    = 16'd63488;
    // localparam	orange = 16'd64384;
    // localparam	yellow = 16'd65472;
    // localparam	green  = 16'd1024;
    // localparam	blue   = 16'd31;
    // localparam	indigo = 16'd18448;
    // localparam	purple = 16'd32784;
    // localparam	white  = 16'd65503;
    // localparam	black  = 16'd0;
    
    
    //信号定义
        reg     [11:0]      cnt_h       ;
        wire                add_cnt_h   ;
        wire                end_cnt_h   ;
        reg     [9:0]       cnt_v       ;
        wire                add_cnt_v   ;
        wire                end_cnt_v   ;
        
        reg     [1:0]       vsync_r     ;//同步打拍
        wire                vsync_nedge ;//下降沿
        reg                 flag        ;//串并转换标志
        
        reg     [15:0]      data        ;
        reg                 data_vld    ;
        reg                 data_sop    ;
        reg                 data_eop    ;
    
    //计数器
        
        always @(posedge clk or negedge rst_n) begin 
            if (rst_n==0) begin
                cnt_h <= 0; 
            end
            else if(add_cnt_h) begin
                if(end_cnt_h)
                    cnt_h <= 0; 
                else
                    cnt_h <= cnt_h+1 ;
           end
        end
        assign add_cnt_h = flag & href;
        assign end_cnt_h = add_cnt_h  && cnt_h == (`H_AP << 1)-1;
        
        always @(posedge clk or negedge rst_n) begin 
            if (rst_n==0) begin
                cnt_v <= 0; 
            end
            else if(add_cnt_v) begin
                if(end_cnt_v)
                    cnt_v <= 0; 
                else
                    cnt_v <= cnt_v+1 ;
           end
        end
        assign add_cnt_v = end_cnt_h;
        assign end_cnt_v = add_cnt_v  && cnt_v == `V_AP-1 ;
    
    //vsync同步打拍
        always  @(posedge clk or negedge rst_n)begin
            if(~rst_n)begin
                vsync_r <= 2'b00;
            end
            else begin
                vsync_r <= {vsync_r[0],vsync};
            end
        end
        assign vsync_nedge = vsync_r[1] & ~vsync_r[0];
    
        always  @(posedge clk or negedge rst_n)begin
            if(~rst_n)begin
                flag <= 1'b0;
            end
            else if(din_vld & vsync_nedge)begin  //摄像头配置完成且场同步信号拉低之后开始采集有效数据
                flag <= 1'b1;
            end
            else if(end_cnt_v)begin     //一帧数据采集完拉低
                flag <= 1'b0;   
            end
        end
    
    //data
        always  @(posedge clk or negedge rst_n)begin
            if(~rst_n)begin
                data <= 0;
            end
            else begin
                data <= {data[7:0],din};//左移
            end
        end
    
    //data_sop
        always  @(posedge clk or negedge rst_n)begin
            if(~rst_n)begin
                data_sop <= 1'b0;
                data_eop <= 1'b0;
                data_vld <= 1'b0;
            end
            else begin
                data_sop <= add_cnt_h && cnt_h == 2-1 && cnt_v == 0;
                data_eop <= end_cnt_v;
                data_vld <= add_cnt_h && cnt_h[0] == 1'b0 ;
            end
        end
    
        assign pixel = data;
        assign sop = cnt_h == 1 && cnt_v == 0;
        assign eop = data_eop;
        assign vld = cnt_h[0];
        
    endmodule //capture
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125

    2.SDRAM控制模块

    `include"param.v"
    module sdram_ctrl (
        input               clk             ,
        input               clk_in          ,
        input               clk_out         ,
        input               rst_n           ,
        //数据输入
        input   [15:0]      din             ,//摄像头输入像素数据
        input               din_sop         ,
        input               din_eop         ,    
        input               din_vld         ,
        //数据输出
        input               rdreq           ,//vga的读数据请求
        output  [15:0]      dout            ,//输出给vga的数据
        output              dout_vld        ,//输出给vga的数据有效标志
        //sdram_interface
        output              avm_write       ,//输出给sdram 接口 IP 的写请求
        output              avm_read        ,//输出给sdram 接口 IP 的读请求
        output  [23:0]      avm_addr        ,//输出给sdram 接口 IP 的读写地址
        output  [15:0]      avm_wrdata      ,//输出给sdram 接口 IP 的写数据
        input   [15:0]      avs_rddata      ,//sdram 接口 IP 输入的读数据
        input               avs_rddata_vld  ,
        input               avs_waitrequest    
    );
    
    //参数定义
        localparam  IDLE  = 4'b0001,
                    WRITE = 4'b0010,
                    READ  = 4'b0100,
                    DONE  = 4'b1000;
    
    //信号定义
    
        reg     [3:0]       state_c     ;
        reg     [3:0]       state_n     ;
    
        reg     [8:0]       cnt         ;//突发读写计数器
        wire                add_cnt     ;
        wire                end_cnt     ;
        
        reg     [1:0]       wr_bank     ;//写bank
        reg     [1:0]       rd_bank     ;//读bank
        reg     [21:0]      wr_addr     ;//写地址   行地址 + 列地址
        wire                add_wr_addr ;
        wire                end_wr_addr ;
        reg     [21:0]      rd_addr     ;//读地址   行地址 + 列地址
        wire                add_rd_addr ;
        wire                end_rd_addr ;
    
        reg                 change_bank ;//切换bank 
        reg                 wr_finish   ;//一帧数据写完
        reg     [1:0]       wr_finish_r ;//同步到写侧
        reg                 wr_data_flag;//wrfifo写数据的标志
    
        reg                 wr_flag     ;
        reg                 rd_flag     ;
        reg                 flag_sel    ;
        reg                 prior_flag  ;
    
        wire                idle2write  ;  
        wire                idle2read   ;
        wire                write2done  ;
        wire                read2done   ;
    
        reg     [15:0]      rd_data     ;//rfifo读数据输出
        reg                 rd_data_vld ;
    
        wire    [17:0]      wfifo_data  ; 
        wire                wfifo_rdreq ;
        wire                wfifo_wrreq ;
        wire    [17:0]      wfifo_q     ;
        wire                wfifo_empty ;
        wire    [10:0]      wfifo_usedw ;
        wire                wfifo_full  ;
    
        wire    [15:0]      rfifo_data  ;
        wire                rfifo_rdreq ;
        wire                rfifo_wrreq ;
        wire    [15:0]      rfifo_q     ;
        wire                rfifo_empty ;
        wire                rfifo_full  ;
        wire    [10:0]      rfifo_usedw ;
    
    //状态机
        always  @(posedge clk or negedge rst_n)begin
            if(~rst_n)begin
                state_c <= IDLE;
            end
            else begin
                state_c <= state_n;
            end
        end
    
        always  @(*)begin
            case(state_c)
                IDLE  :begin 
                    if(idle2write)
                        state_n = WRITE;
                    else if(idle2read)
                        state_n = READ;
                    else 
                        state_n = state_c;
                end 
                WRITE :begin 
                    if(write2done)
                        state_n = DONE;
                    else 
                        state_n = state_c;
                end     
                READ  :begin 
                    if(read2done)
                        state_n = DONE;
                    else 
                        state_n = state_c;
                end 
                DONE  :state_n = IDLE;
                default:state_n = IDLE;
            endcase  
        end
    
        assign idle2write = state_c == IDLE  && (~prior_flag && wfifo_usedw >= `USER_BL);
        assign idle2read  = state_c == IDLE  && prior_flag && rfifo_usedw <= `RD_UT;
        assign write2done = state_c == WRITE && end_cnt;
        assign read2done  = state_c == READ  && end_cnt;
    
    //计数器
        always @(posedge clk or negedge rst_n)begin
            if(!rst_n)begin
                cnt <= 0;
            end
            else if(add_cnt)begin
                if(end_cnt)
                    cnt <= 0;
                else
                    cnt <= cnt + 1;
            end
        end
    
        assign add_cnt = (state_c == WRITE | state_c == READ) & ~avs_waitrequest; 
        assign end_cnt = add_cnt && cnt== `USER_BL-1;  
    
    /************************读写优先级仲裁*****************************/
    //rd_flag     ;//读请求标志
        always @(posedge clk or negedge rst_n)begin 
            if(!rst_n)begin
                rd_flag <= 0;
            end 
            else if(rfifo_usedw <= `RD_LT)begin   
                rd_flag <= 1'b1;
            end 
            else if(rfifo_usedw > `RD_UT)begin 
                rd_flag <= 1'b0;
            end 
        end
    
    //wr_flag     ;//写请求标志
        always @(posedge clk or negedge rst_n)begin 
            if(!rst_n)begin
                wr_flag <= 0;
            end 
            else if(wfifo_usedw >= `USER_BL)begin 
                wr_flag <= 1'b1;
            end 
            else begin 
                wr_flag <= 1'b0;
            end 
        end
    
    //flag_sel    ;//标记上一次操作
        always @(posedge clk or negedge rst_n)begin 
            if(!rst_n)begin
                flag_sel <= 0;
            end 
            else if(read2done)begin 
                flag_sel <= 1;
            end 
            else if(write2done)begin 
                flag_sel <= 0;
            end 
        end
    
    //prior_flag  ;//优先级标志 0:写优先级高   1:读优先级高     仲裁读、写的优先级
        always @(posedge clk or negedge rst_n)begin 
            if(!rst_n)begin
                prior_flag <= 0;
            end 
            else if(wr_flag && (flag_sel || (~flag_sel && ~rd_flag)))begin   //突发写优先级高
                prior_flag <= 1'b0;
            end 
            else if(rd_flag && (~flag_sel || (flag_sel && ~wr_flag)))begin   //突发读优先级高
                prior_flag <= 1'b1;
            end 
        end
    
    /******************************************************************/    
    
    /********************      地址设计    ****************************/    
    
    //wr_bank  rd_bank
        always  @(posedge clk or negedge rst_n)begin
            if(~rst_n)begin
                wr_bank <= 2'b00;
                rd_bank <= 2'b11;
            end
            else if(change_bank)begin
                wr_bank <= ~wr_bank;
                rd_bank <= ~rd_bank;
            end
        end
    
    // wr_addr   rd_addr
        always @(posedge clk or negedge rst_n) begin 
            if (rst_n==0) begin
                wr_addr <= 0; 
            end
            else if(add_wr_addr) begin
                if(end_wr_addr)
                    wr_addr <= 0; 
                else
                    wr_addr <= wr_addr+1 ;
           end
        end
        assign add_wr_addr = (state_c == WRITE) && ~avs_waitrequest;
        assign end_wr_addr = add_wr_addr  && wr_addr == `BURST_MAX-1 ;
        
        always @(posedge clk or negedge rst_n) begin 
            if (rst_n==0) begin
                rd_addr <= 0; 
            end
            else if(add_rd_addr) begin
                if(end_rd_addr)
                    rd_addr <= 0; 
                else
                    rd_addr <= rd_addr+1 ;
           end
        end
        assign add_rd_addr = (state_c == READ) && ~avs_waitrequest;
        assign end_rd_addr = add_rd_addr  && rd_addr == `BURST_MAX-1;
    
    //wr_finish     一帧数据全部写到SDRAM
        always  @(posedge clk or negedge rst_n)begin
            if(~rst_n)begin
                wr_finish <= 1'b0;
            end
            else if(~wr_finish & end_wr_addr)begin  //写完  从wrfifo读出eop
                wr_finish <= 1'b1;
            end
            else if(wr_finish && end_rd_addr)begin  //读完
                wr_finish <= 1'b0;
            end
        end
    
    //change_bank ;//切换bank 
        always  @(posedge clk or negedge rst_n)begin
            if(~rst_n)begin
                change_bank <= 1'b0;
            end
            else begin
                change_bank <= wr_finish && end_rd_addr;
            end
        end
    
    /****************************************************************/
    
    /*********************** wrfifo 写数据   ************************/
    //控制像素数据帧 写入 或 丢帧
    
        always  @(posedge clk_in or negedge rst_n)begin
            if(~rst_n)begin
                wr_data_flag <= 1'b0;
            end 
            else if(~wr_data_flag & ~wr_finish_r[1] & din_sop)begin//可以向wrfifo写数据 
                wr_data_flag <= 1'b1;
            end
            else if(/*wr_finish_r[1] && din_sop*/wr_data_flag & din_eop)begin//不可以向wrfifo写入数据
                wr_data_flag <= 1'b0;
            end
        end
    
        always  @(posedge clk_in or negedge rst_n)begin //把wr_finish从wrfifo的读侧同步到写侧
            if(~rst_n)begin
                wr_finish_r <= 0;
            end
            else begin
                wr_finish_r <= {wr_finish_r[0],wr_finish};
            end
        end
    
    /****************************************************************/
    
        always  @(posedge clk_out or negedge rst_n)begin
            if(~rst_n)begin
                rd_data <= 0;
                rd_data_vld <= 1'b0;
            end
            else begin
                rd_data <= rfifo_q;
                rd_data_vld <= rfifo_rdreq;
            end
        end
    
    wfifo	wrfifo_inst (
    	.aclr   (~rst_n     ),
    	.data   (wfifo_data ),
    	.rdclk  (clk        ),
    	.rdreq  (wfifo_rdreq),
    	.wrclk  (clk_in     ),
    	.wrreq  (wfifo_wrreq),
    	.q      (wfifo_q    ),
    	.rdempty(wfifo_empty),
    	.rdusedw(wfifo_usedw),
    	.wrfull (wfifo_full )
    	);
    
        assign wfifo_data = {din_eop,din_sop,din};
        assign wfifo_wrreq = ~wfifo_full & din_vld & ((~wr_finish_r[1] & din_sop) ||wr_data_flag);
        assign wfifo_rdreq = state_c == WRITE && ~avs_waitrequest;
    
    rfifo u_rdfifo(
    	.aclr       (~rst_n     ),
    	.data       (rfifo_data ),
    	.rdclk      (clk_out    ),
    	.rdreq      (rfifo_rdreq),
    	.wrclk      (clk        ),
    	.wrreq      (rfifo_wrreq),
    	.q          (rfifo_q    ), 
    	.rdempty    (rfifo_empty),
    	.wrfull     (rfifo_full ),
    	.wrusedw    (rfifo_usedw)
    );
    
        assign rfifo_data = avs_rddata;
        assign rfifo_wrreq = ~rfifo_full & avs_rddata_vld;
        assign rfifo_rdreq = ~rfifo_empty & rdreq;
    
    //输出
        assign dout       = rd_data;
        assign dout_vld   = rd_data_vld;
        assign avm_wrdata = wfifo_q[15:0];
        assign avm_write  = ~(state_c == WRITE && ~avs_waitrequest);
        assign avm_read   = ~(state_c == READ && ~avs_waitrequest);
        assign avm_addr   = (state_c == WRITE)?{wr_bank[1],wr_addr[21:9],wr_bank[0],wr_addr[8:0]}
                           :((state_c == READ)?{rd_bank[1],rd_addr[21:9],rd_bank[0],rd_addr[8:0]}
                           :0);
    
    endmodule 
    
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251
    • 252
    • 253
    • 254
    • 255
    • 256
    • 257
    • 258
    • 259
    • 260
    • 261
    • 262
    • 263
    • 264
    • 265
    • 266
    • 267
    • 268
    • 269
    • 270
    • 271
    • 272
    • 273
    • 274
    • 275
    • 276
    • 277
    • 278
    • 279
    • 280
    • 281
    • 282
    • 283
    • 284
    • 285
    • 286
    • 287
    • 288
    • 289
    • 290
    • 291
    • 292
    • 293
    • 294
    • 295
    • 296
    • 297
    • 298
    • 299
    • 300
    • 301
    • 302
    • 303
    • 304
    • 305
    • 306
    • 307
    • 308
    • 309
    • 310
    • 311
    • 312
    • 313
    • 314
    • 315
    • 316
    • 317
    • 318
    • 319
    • 320
    • 321
    • 322
    • 323
    • 324
    • 325
    • 326
    • 327
    • 328
    • 329
    • 330
    • 331
    • 332
    • 333
    • 334
    • 335
    • 336
    • 337
    • 338
    • 339
    • 340
    • 341
    • 342
    • 343
    • 344
    • 345
    • 346
    • 347
    • 348
    • 349

    3.vga模块

        module vga_dirve (input			wire						clk,            //系统时钟
                        input			wire						rst_n,          //复位
                        input			wire		[ 15:0 ]		rgb_data,       //16位RGB对应值
                        output			reg							h_sync,     //行同步信号
                        output			reg							v_sync,     //场同步信号
                        output			reg		[ 11:0 ]				addr_h, //行地址
                        output			reg		[ 11:0 ]				addr_v,  //列地址
                        output			wire		[ 4:0 ]				rgb_r,  //红基色
                        output			wire		[ 5:0 ]				rgb_g,  //绿基色
                        output			wire		[ 4:0 ]				rgb_b  //蓝基色
        );
    
    //1280 * 640 60HZ
    localparam	 H_FRONT = 110; // 行同步前沿信号周期长
    localparam	 H_SYNC  = 40; // 行同步信号周期长
    localparam	 H_BLACK = 220; // 行同步后沿信号周期长
    localparam	 H_ACT   = 1280; // 行显示周期长
    localparam	 V_FRONT = 5; // 场同步前沿信号周期长
    localparam	 V_SYNC  = 5; // 场同步信号周期长
    localparam	 V_BLACK = 20; // 场同步后沿信号周期长
    localparam	 V_ACT   = 720; // 场显示周期长
    // 640 * 480 60HZ
    // localparam	 H_FRONT = 16; // 行同步前沿信号周期长
    // localparam	 H_SYNC  = 96; // 行同步信号周期长
    // localparam	 H_BLACK = 48; // 行同步后沿信号周期长
    // localparam	 H_ACT   = 640; // 行显示周期长
    // localparam	 V_FRONT = 11; // 场同步前沿信号周期长
    // localparam	 V_SYNC  = 2; // 场同步信号周期长
    // localparam	 V_BLACK = 31; // 场同步后沿信号周期长
    // localparam	 V_ACT   = 480; // 场显示周期长
    
    // 800 * 600 72HZ
    // localparam	 H_FRONT = 40; // 行同步前沿信号周期长
    // localparam	 H_SYNC  = 120; // 行同步信号周期长
    // localparam	 H_BLACK = 88; // 行同步后沿信号周期长
    // localparam	 H_ACT   = 800; // 行显示周期长
    // localparam	 V_FRONT = 37; // 场同步前沿信号周期长
    // localparam	 V_SYNC  = 6; // 场同步信号周期长
    // localparam	 V_BLACK = 23; // 场同步后沿信号周期长
    // localparam	 V_ACT   = 600; // 场显示周期长
    
    
    localparam	H_TOTAL = H_FRONT + H_SYNC + H_BLACK + H_ACT; // 行周期
    localparam	V_TOTAL = V_FRONT + V_SYNC + V_BLACK + V_ACT; // 列周期
    
    reg			[ 11:0 ]			cnt_h			; // 行计数器
    reg			[ 11:0 ]			cnt_v			; // 场计数器
    reg			[ 15:0 ]			rgb			; // 对应显示颜色值
    
    // 对应计数器开始、结束、计数信号
    wire							flag_enable_cnt_h			;
    wire							flag_clear_cnt_h			;
    wire							flag_enable_cnt_v			;
    wire							flag_clear_cnt_v			;
    wire							flag_add_cnt_v  			;
    wire							valid_area      			;
    
    
    
    // 行计数
    always @( posedge clk or negedge rst_n ) begin
        if ( !rst_n ) begin
            cnt_h <= 0;
        end
        else if ( flag_enable_cnt_h ) begin
            if ( flag_clear_cnt_h ) begin
                cnt_h <= 0;
            end
            else begin
                cnt_h <= cnt_h + 1;
            end
        end
        else begin
            cnt_h <= 0;
        end
    end
    assign flag_enable_cnt_h = 1;
    assign flag_clear_cnt_h  = cnt_h == H_TOTAL - 1;
    
    // 行同步信号
    always @( posedge clk or negedge rst_n ) begin
        if ( !rst_n ) begin
            h_sync <= 1;
        end
        else if ( cnt_h == H_SYNC - 1 ) begin // 同步周期时为1
            h_sync <= 0;
        end
        else if ( flag_clear_cnt_h ) begin // 其余为0
            h_sync <= 1;
        end
        else begin
            h_sync <= h_sync;
        end
    end
    
    // 场计数
    always @( posedge clk or negedge rst_n ) begin
        if ( !rst_n ) begin
            cnt_v <= 0;
        end
        else if ( flag_enable_cnt_v ) begin
            if ( flag_clear_cnt_v ) begin
                cnt_v <= 0;
            end
            else if ( flag_add_cnt_v ) begin
                cnt_v <= cnt_v + 1;
            end
            else begin
                cnt_v <= cnt_v;
            end
        end
        else begin
            cnt_v <= 0;
        end
    end
    assign flag_enable_cnt_v = flag_enable_cnt_h;
    assign flag_clear_cnt_v  = cnt_v == V_TOTAL - 1;
    assign flag_add_cnt_v    = flag_clear_cnt_h;
    
    // 场同步信号
    always @( posedge clk or negedge rst_n ) begin
        if ( !rst_n ) begin
            v_sync <= 1;
        end
        else if ( cnt_v == V_SYNC - 1 ) begin
            v_sync <= 0;
        end
        else if ( flag_clear_cnt_v ) begin
            v_sync <= 1;
        end
    end
    
    // 对应有效区域行地址 1-640
    always @( posedge clk or negedge rst_n ) begin
        if ( !rst_n ) begin
            addr_h <= 0;
        end
        else if ( valid_area ) begin
            addr_h <= cnt_h - H_SYNC - H_BLACK + 1;
        end
        else begin
            addr_h <= 0;
        end
    end
    // 对应有效区域列地址 1-480
    always @( posedge clk or negedge rst_n ) begin
        if ( !rst_n ) begin
            addr_v <= 0;
        end
        else if ( valid_area ) begin
            addr_v <= cnt_v -V_SYNC - V_BLACK + 1;
        end
        else begin
            addr_v <= 0;
        end
    end
    // 有效显示区域
    assign valid_area = cnt_h >= H_SYNC + H_BLACK && cnt_h < H_SYNC + H_BLACK + H_ACT && cnt_v >= V_SYNC + V_BLACK && cnt_v < V_SYNC + V_BLACK + V_ACT;
    
    
    // 显示颜色
    always @( posedge clk or negedge rst_n ) begin
        if ( !rst_n ) begin
            rgb <= 16'h0;
        end
        else if ( valid_area ) begin
            rgb <= rgb_data;
        end
        else begin
            rgb <= 16'b0;
        end
    end
    assign rgb_r = rgb[ 15:11 ];
    assign rgb_g = rgb[ 10:5 ];
    assign rgb_b = rgb[ 4:0 ];
    
    endmodule // vga_dirve
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178

    4.顶层文件

    module camera_top (
        input			wire						clk,
        input			wire						rst_n,
        /* 配置寄存器 */
        output			wire						cmos_pwdn,
        output			wire						cmos_reset,
        output			wire						cmos_sioc,
        output			wire						cmos_siod,
        output			wire						cmos_xclk,
    
        input			wire						cmos_pclk,
        input			wire						cmos_vsync,
        input			wire						cmos_href,
        input			wire		[7:0]			cmos_din,
    
        output                                      sdram_clk       ,
        output                                      sdram_cke       ,   
        output                                      sdram_csn       ,   
        output                                      sdram_rasn      ,   
        output                                      sdram_casn      ,   
        output                                      sdram_wen       ,   
        output                      [1:0 ]          sdram_bank      ,   
        output                      [12:0]          sdram_addr      ,   
        inout                       [15:0]          sdram_dq        ,   
        output                      [1: 0]          sdram_dqm       ,
    
        //vga
        output			wire						h_sync,
        output			wire						v_sync,
        output			wire		[15:0]			vga_rgb
    
    );
    
    wire							clk_24			;
    wire							clk_50			;
    wire							clk_75			;
    wire							clk_100			;
    wire							clk_84			;
    wire							clk_100_s			;
    wire							clk_150			;
    wire							clk_200			;
    wire							pclk			;
    wire							has_config			;
    wire							rd_req			;
    wire		[ 15:0 ]			dout			;
    wire							sop			;
    wire							eop			;
    wire							vld			;
    wire		[ 15:0 ]			data			;
    wire							dout_vld			;
    wire		[ 11:0 ]			addr_h			;
    wire		[ 11:0 ]			addr_v			;
    wire		[ 15:0 ]			rgb_data			;
    
    //PLL
        pll	pll_inst (
    	.areset ( ~rst_n ),
    	.inclk0 ( clk ),
    	.c0 ( clk_50 ),//50M
    	.c1 ( clk_24 ),//24M
    	.c2 ( clk_75 ),//75M
    	.c3 ( clk_100 ),//100M
        .c4 ( clk_84 )
    	);
    
        pll1	pll1_inst (
            .areset ( ~rst_n ),
            .inclk0 ( clk ),
            .c0 ( clk_100_s ),
            .c1 ( clk_150 ),
            .c2 ( clk_200 )
            );
    
        iobuf u_iobuf(
    	.datain     (cmos_pclk  ),
        .dataout    (pclk       )
        );
    
        assign sdram_clk = clk_100_s;
        assign cmos_xclk = clk_24;
    
        cmos_top u_cmos_top(
            .clk        ( clk           ),
            .rst_n      ( rst_n         ),
            .scl        ( cmos_sioc      ),
            .sda        (  cmos_siod     ),
            .pwdn       ( cmos_pwdn      ),
            .reset      ( cmos_reset      ),
            .cfg_done   ( has_config    )
        );
        // camera_config_drive u_camera_config_drive(
        //     .clk   ( clk   ),
        //     .rst_n ( rst_n ),
        //     .pwdn  ( cmos_pwdn  ),
        //     .reset ( cmos_reset ),
        //     .sioc  ( cmos_sioc  ),
        //     .siod  ( cmos_siod  ),
        //     .done  ( has_config )
        // );
    
        capture u_capture(
            .clk   ( pclk   ),
            .rst_n ( rst_n ),
            .vsync ( cmos_vsync ),
            .href  ( cmos_href  ),
            .din   ( cmos_din   ),
            .din_vld(has_config),
            .sop   ( sop   ),
            .eop   ( eop   ),
            .vld   ( vld   ),
            .pixel  ( data  )
        );
    
    
        sdram_controller u_sdram_controller(
            .clk            ( clk_100       ),
            .clk_in         ( pclk          ),
            .clk_out        ( clk_75        ),
            .rst_n          ( rst_n          ),
            .sop            ( sop            ),
            .eop            ( eop            ),
            .din            ( data            ),
            .din_vld        ( vld           ),
            .rd_req         ( rd_req         ),
            .dout           ( dout           ),
            .dout_vld       ( dout_vld       ),
            .mem_cke            (sdram_cke     ),
            .mem_csn            (sdram_csn     ),
            .mem_rasn           (sdram_rasn    ),
            .mem_casn           (sdram_casn    ),
            .mem_wen            (sdram_wen     ),
            .mem_bank           (sdram_bank    ),
            .mem_addr           (sdram_addr    ),
            .mem_dq             (sdram_dq      ),
            .mem_dqm            (sdram_dqm     )  
        );
    
        vga_control u_vga_control(
            .clk    ( clk_75  ),
            .rst_n  ( rst_n  ),
            .din    ( dout   ),
            .din_vld ( dout_vld ),
            .addr_h ( addr_h ),
            .addr_v ( addr_v ),
            .rd_req ( rd_req ),
            .rgb_data  ( rgb_data  )
        );
        vga_dirve u_vga_dirve(
            .clk      ( clk_75    ),
            .rst_n    ( rst_n    ),
            .rgb_data ( rgb_data ),
            .h_sync   ( h_sync   ),
            .v_sync   ( v_sync   ),
            .addr_h   ( addr_h   ),
            .addr_v   ( addr_v   ),
            .rgb_r    ( rgb_r    ),
            .rgb_g    ( rgb_g    ),
            .rgb_b    ( rgb_b    )
        );
        // vga_interface u_vga(
        // /*input           */.clk      (clk_75   ),
        // /*input           */.rst_n    (rst_n ),
        // /*input   [15:0]  */.din      (dout      ),
        // /*input           */.din_vld  (dout_vld  ),
        // /*output          */.rdy      (rd_req    ),
        // /*output  [15:0]  */.vga_rgb  (rgb_data   ),
        // /*output          */.vga_hsync(h_sync ),
        // /*output          */.vga_vsync(v_sync )
        // );
        assign vga_rgb = rgb_data;
    endmodule //camera_top
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171

    三、源码

    https://github.com/TangtangSix/ov5640

  • 相关阅读:
    学习中间件之redis基础学习
    掌握.NET基础知识(一)
    前端性能优化之控制请求并发数
    大一学生《Web编程基础》期末网页制作 基于HTML+CSS+JavaScript响应式个人主页相册介绍模板
    Spring MVC ⾼级技术:监听器、过滤器和拦截器
    超越openmp通用核心的硬件
    Web前端学习(HTML)学习---下(表格标签,列表标签,表单标签)案例
    go学习(四、面向接口)
    【java筑基】IO流基础之文件的常见操作
    Unity16 UI
  • 原文地址:https://blog.csdn.net/qq_47281915/article/details/126041967