sensor_fifo.v 8.02 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
 * 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
Andrey Filippov's avatar
Andrey Filippov committed
26
    parameter SENSOR_FIFO_DELAY = 5 // 7 // approxiametly half (1 << SENSOR_FIFO_2DEPTH) - how long to wait after getting HACT on FIFO before stering it on output
27
)(
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
    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
Andrey Filippov's avatar
Andrey Filippov committed
48 49
//    wire                        pre_re;
    wire                        re; // re_w,re;
50
//    reg                         re_r;
51
    reg                   [1:0] pre_hact;
52
    reg                   [1:0] hact_out_r;
53
    reg [SENSOR_DATA_WIDTH-1:0] pxd_r;
54
//    wire                        hact_out_start;
55 56
    
    assign we=sof_in || eof_in || hact || hact_r;
Andrey Filippov's avatar
Andrey Filippov committed
57 58 59
    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};
60 61 62 63 64 65
    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
66 67 68 69 70 71 72
        .rst        (1'b0),   // rst), // input
        .rrst       (prst),   // input
        .wrst       (irst),   // input
        .rclk       (pclk),   // input
        .wclk       (iclk),   // input
        .we         (we),     // input
        .re         (re),     // input
73 74 75
        .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
76
        .half_empty ()        // output
77
    );
78
/*
79 80 81
    dly_16 #(
        .WIDTH(1)
    ) hact_dly_16_i (
Andrey Filippov's avatar
Andrey Filippov committed
82 83 84
        .clk(pclk),                         // input
        .rst(prst),                         // input
        .dly(SENSOR_FIFO_DELAY),            // input[3:0] 
85
        .din(pre_hact[0] && ! pre_hact[1]), // input[0:0] 
Andrey Filippov's avatar
Andrey Filippov committed
86
        .dout(hact_out_start)               // output[0:0] 
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
*/    
    wire pre_sof_pclk;
    wire pre_eof_pclk;
    wire pre_sol_pclk;

    wire sof_pclk;
    wire eof_pclk;
    wire sol_pclk;
    
    pulse_cross_clock pulse_cross_clock_sof_i (
        .rst         (irst),           // input
        .src_clk     (iclk),          // input
        .dst_clk     (pclk),          // input
        .in_pulse    (sof_in),  // input
        .out_pulse   (pre_sof_pclk),      // output
        .busy() // output
    );

    pulse_cross_clock pulse_cross_clock_eof_i (
        .rst         (irst),           // input
        .src_clk     (iclk),          // input
        .dst_clk     (pclk),          // input
        .in_pulse    (eof_in),  // input
        .out_pulse   (pre_eof_pclk),      // output
        .busy() // output
    );

    pulse_cross_clock pulse_cross_clock_sol_i (
        .rst         (irst),           // input
        .src_clk     (iclk),          // input
        .dst_clk     (pclk),          // input
        .in_pulse    (hact && !hact_r),  // input
        .out_pulse   (pre_sol_pclk),      // output
        .busy() // output
    );

    dly_16 #(
        .WIDTH(3)
    ) hact_dly_16_i (
        .clk(pclk),                                       // input
        .rst(prst),                                       // input
        .dly(SENSOR_FIFO_DELAY),                          // input[3:0] 
        .din({pre_sof_pclk, pre_eof_pclk, pre_sol_pclk}), // input[0:0] 
        .dout({sof_pclk, eof_pclk, sol_pclk})             // output[0:0] 
    );
    
    
    
    reg sof_rq;
    reg eof_rq;
    reg sol_rq;
    always @ (posedge pclk) begin
        if (prst || (re && sof_w)) sof_rq <= 0;
        else if (sof_pclk)         sof_rq <= 1;

        if (prst || (re && eof_w)) eof_rq <= 0;
        else if (eof_pclk)         eof_rq <= 1;

        if (prst || (re && hact_out_r[0] && !hact_out_r[1])) sol_rq <= 0;
        else if (sol_pclk)                                   sol_rq <= 1;
    end
    
    
151 152
    
    // output clock domain
Andrey Filippov's avatar
Andrey Filippov committed
153 154 155 156
//    assign pre_re = nempty && !re_r;
// Generating first read (for hact), then wait to fill half FIFO and continue continuous read until hact end
//    assign re_w = re_r && nempty; // to protect from false positive on nempty
//    assign re = (re_w && !pre_hact) || hact_out_r; // no check for nempty - producing un-interrupted stream
157 158
//    assign re = (re_r && nempty && !pre_hact[0]) || hact_out_r[0]; // no check for nempty - producing un-interrupted stream
    assign re = ((sof_rq || eof_rq || sol_rq) && nempty) || hact_out_r[0]; // no check for nempty - producing un-interrupted stream
159
    assign pxd_out= pxd_r;
160
    assign data_valid = hact_out_r[1];
161 162
    assign sof = sof_r;
    assign eof = eof_r;
Andrey Filippov's avatar
Andrey Filippov committed
163 164

    always @(posedge pclk) begin
165 166
//        if (prst) re_r <= 0;
//        else      re_r <= nempty && !re_r && !pre_hact[0]; // only generate one cycle (after SOF of HACT)
Andrey Filippov's avatar
Andrey Filippov committed
167 168 169 170 171 172 173 174 175 176 177

        if    (prst) pre_hact[0] <= 0;
        else if (re) pre_hact[0] <= hact_w;

        if    (prst) pre_hact[1] <= 0;
        else         pre_hact[1] <= pre_hact[0];


        if    (prst) pxd_r <= 0;
        else if (re) pxd_r <= pxd_w;

178 179 180 181 182 183
        if      (prst)            hact_out_r[0] <= 0;
        else if (sol_pclk)        hact_out_r[0] <= 1;
        else if (!(hact_w) && re) hact_out_r[0] <= 0;
        
        if      (prst || (!(hact_w) && re)) hact_out_r[1] <= 0;
        else                                hact_out_r[1] <= hact_out_r[0];
Andrey Filippov's avatar
Andrey Filippov committed
184 185 186 187 188 189 190 191

        if (prst) sof_r <= 0;
        else      sof_r <= re && sof_w;

        if (prst) eof_r <= 0;
        else      eof_r <= re && eof_w;

    end
192
     
Andrey Filippov's avatar
Andrey Filippov committed
193
/*
Andrey Filippov's avatar
Andrey Filippov committed
194 195 196
    always @(posedge iclk) begin
        if (irst) re_r <= 0;
        else      re_r <= pre_re;
197

Andrey Filippov's avatar
Andrey Filippov committed
198
        if    (irst) pre_hact[0] <= 0;
199 200
        else if (re) pre_hact[0] <= hact_w;

Andrey Filippov's avatar
Andrey Filippov committed
201
        if    (irst) pre_hact[1] <= 0;
202 203
        else if (re) pre_hact[1] <= pre_hact[0];

Andrey Filippov's avatar
Andrey Filippov committed
204
        if    (irst) pxd_r <= 0;
205 206
        else if (re) pxd_r <= pxd_w;

Andrey Filippov's avatar
Andrey Filippov committed
207
        if      (irst)           hact_out_r <= 0;
208 209 210
        else if (hact_out_start) hact_out_r <= 1;
        else if (!hact_w)        hact_out_r <= 0;

Andrey Filippov's avatar
Andrey Filippov committed
211 212
        if (irst) sof_r <= 0;
        else      sof_r <= re && sof_w;
213

Andrey Filippov's avatar
Andrey Filippov committed
214 215
        if (irst) eof_r <= 0;
        else      eof_r <= re && eof_w;
216 217

    end
Andrey Filippov's avatar
Andrey Filippov committed
218
*/    
219 220 221 222


endmodule