sensor_fifo.v 4.74 KB
Newer Older
1 2 3
/*******************************************************************************
 * Module: sensor_fifo
 * Date:2015-05-19  
4
 * Author: Andrey Filippov     
5 6
 * Description: Cross clock boundary for sensor data, synchronize to HACT
 *
7
 * Copyright (c) 2015 Elphel, Inc.
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
 * sensor_fifo.v is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 *  sensor_fifo.v is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/> .
 *******************************************************************************/
`timescale 1ns/1ps

module  sensor_fifo #(
    parameter SENSOR_DATA_WIDTH = 12,
    parameter SENSOR_FIFO_2DEPTH = 4, // 4-bit address
    parameter SENSOR_FIFO_DELAY = 7 // approxiametly half (1 << SENSOR_FIFO_2DEPTH) - how long to wait after getting HACT on FIFO before stering it on output
)(
Andrey Filippov's avatar
Andrey Filippov committed
28
//    input                          rst,
29 30
    input                          iclk, // input -synchronous clock
    input                          pclk, // internal lixel clock
Andrey Filippov's avatar
Andrey Filippov committed
31 32 33
    input                          prst, // @ posedge pclk
    input                          irst, // @ posedge iclk
    
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
    input  [SENSOR_DATA_WIDTH-1:0] pxd_in,  // sensor data @posedge iclk
    input                          vact,
    input                          hact,
    output [SENSOR_DATA_WIDTH-1:0] pxd_out,
    output                         data_valid, // @posedge pclk: continuous data valid for each line, FIFO should compensate for clock differences
    output                         sof,        // @posedge pclk: single-cycle Start of Frame
    output                         eof         // @posedge pclk: single-cycle End of Frame (not yet used)
);
    reg                          vact_r,hact_r,sof_in,eof_in;
    wire [SENSOR_DATA_WIDTH-1:0] pxd_w;
    wire                         nempty, hact_w,sof_w,eof_w;
    reg                          sof_r,eof_r;
    wire we;
    // output clock domain
    wire pre_re,re_w,re;
    reg                         re_r;
    reg                   [1:0] pre_hact;
    reg                         hact_out_r;
    reg [SENSOR_DATA_WIDTH-1:0] pxd_r;
    wire                        hact_out_start;
    
    assign we=sof_in || eof_in || hact || hact_r;
Andrey Filippov's avatar
Andrey Filippov committed
56 57 58
    always @(posedge iclk) begin
        if (irst) {vact_r,hact_r,sof_in,eof_in} <= 0;
        else      {vact_r,hact_r,sof_in,eof_in} <= {vact,hact, vact && ! vact_r, vact_r && !vact};
59 60 61 62 63 64
    end

    fifo_cross_clocks #(
        .DATA_WIDTH(SENSOR_DATA_WIDTH+3),
        .DATA_DEPTH(SENSOR_FIFO_2DEPTH)
    ) fifo_cross_clocks_i (
Andrey Filippov's avatar
Andrey Filippov committed
65 66 67 68 69 70 71
        .rst        (1'b0),   // rst), // input
        .rrst       (prst),   // input
        .wrst       (irst),   // input
        .rclk       (pclk),   // input
        .wclk       (iclk),   // input
        .we         (we),     // input
        .re         (re),     // input
72 73 74
        .data_in    ({eof_in, sof_in, hact,   pxd_in}), // input[15:0] 
        .data_out   ({eof_w,  sof_w,  hact_w, pxd_w}), // output[15:0] 
        .nempty     (nempty), // output
Andrey Filippov's avatar
Andrey Filippov committed
75
        .half_empty ()        // output
76 77 78 79 80
    );

    dly_16 #(
        .WIDTH(1)
    ) hact_dly_16_i (
Andrey Filippov's avatar
Andrey Filippov committed
81 82 83
        .clk(pclk),                         // input
        .rst(prst),                         // input
        .dly(SENSOR_FIFO_DELAY),            // input[3:0] 
84
        .din(pre_hact[0] && ! pre_hact[1]), // input[0:0] 
Andrey Filippov's avatar
Andrey Filippov committed
85
        .dout(hact_out_start)               // output[0:0] 
86 87 88 89 90 91 92 93 94 95 96
    );
    
    // output clock domain
    assign pre_re = nempty && !re_r;
    assign re_w = re_r && nempty; // to protect from false positive on nempty
    assign re = (re_w && !pre_hact) || hact_out_r;
    assign pxd_out= pxd_r;
    assign data_valid = hact_out_r;
    assign sof = sof_r;
    assign eof = eof_r;
     
Andrey Filippov's avatar
Andrey Filippov committed
97 98 99
    always @(posedge iclk) begin
        if (irst) re_r <= 0;
        else      re_r <= pre_re;
100

Andrey Filippov's avatar
Andrey Filippov committed
101
        if    (irst) pre_hact[0] <= 0;
102 103
        else if (re) pre_hact[0] <= hact_w;

Andrey Filippov's avatar
Andrey Filippov committed
104
        if    (irst) pre_hact[1] <= 0;
105 106
        else if (re) pre_hact[1] <= pre_hact[0];

Andrey Filippov's avatar
Andrey Filippov committed
107
        if    (irst) pxd_r <= 0;
108 109
        else if (re) pxd_r <= pxd_w;

Andrey Filippov's avatar
Andrey Filippov committed
110
        if      (irst)           hact_out_r <= 0;
111 112 113
        else if (hact_out_start) hact_out_r <= 1;
        else if (!hact_w)        hact_out_r <= 0;

Andrey Filippov's avatar
Andrey Filippov committed
114 115
        if (irst) sof_r <= 0;
        else      sof_r <= re && sof_w;
116

Andrey Filippov's avatar
Andrey Filippov committed
117 118
        if (irst) eof_r <= 0;
        else      eof_r <= re && eof_w;
119 120 121 122 123 124 125

    end
    


endmodule