sensor_fifo.v 8.83 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11
/*!
 * <b>Module:</b>sensor_fifo
 * @file sensor_fifo.v
 * @date 2015-05-19  
 * @author Andrey Filippov     
 *
 * @brief Cross clock boundary for sensor data, synchronize to HACT
 *
 * @copyright Copyright (c) 2015 Elphel, Inc.
 *
 * <b>License:</b>
12 13 14 15 16 17 18 19 20 21 22 23 24
 *
 * 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/> .
25 26 27 28 29 30
 *
 * Additional permission under GNU GPL version 3 section 7:
 * If you modify this Program, or any covered work, by linking or combining it
 * with independent modules provided by the FPGA vendor only (this permission
 * does not extend to any 3-rd party modules, "soft cores" or macros) under
 * different license terms solely for the purpose of generating binary "bitstream"
31
 * files and/or simulating the code, the copyright holders of this Program give
32 33
 * you the right to distribute the covered work without those independent modules
 * as long as the source code for them is available from the FPGA vendor free of
Andrey Filippov's avatar
Andrey Filippov committed
34
 * charge, and there is no dependence on any encrypted modules for simulating of
35 36 37
 * the combined code. This permission applies to you if the distributed code
 * contains all the components and scripts required to completely simulate it
 * with at least one of the Free Software programs.
38
 */
39 40 41 42 43
`timescale 1ns/1ps

module  sensor_fifo #(
    parameter SENSOR_DATA_WIDTH = 12,
    parameter SENSOR_FIFO_2DEPTH = 4, // 4-bit address
44
    parameter [3:0] 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
45
)(
Andrey Filippov's avatar
Andrey Filippov committed
46
//    input                          rst,
47 48
    input                          iclk, // input -synchronous clock
    input                          pclk, // internal lixel clock
Andrey Filippov's avatar
Andrey Filippov committed
49 50 51
    input                          prst, // @ posedge pclk
    input                          irst, // @ posedge iclk
    
52 53 54 55 56 57 58 59 60 61 62 63 64 65
    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
66 67
//    wire                        pre_re;
    wire                        re; // re_w,re;
68
//    reg                         re_r;
69
    reg                   [1:0] pre_hact;
70
    reg                   [1:0] hact_out_r;
71
    reg [SENSOR_DATA_WIDTH-1:0] pxd_r;
72
//    wire                        hact_out_start;
73 74
    
    assign we=sof_in || eof_in || hact || hact_r;
Andrey Filippov's avatar
Andrey Filippov committed
75 76 77
    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};
78 79 80 81 82 83
    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
84 85 86 87 88 89 90
        .rst        (1'b0),   // rst), // input
        .rrst       (prst),   // input
        .wrst       (irst),   // input
        .rclk       (pclk),   // input
        .wclk       (iclk),   // input
        .we         (we),     // input
        .re         (re),     // input
91 92 93
        .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
94
        .half_empty ()        // output
95
    );
96
/*
97 98 99
    dly_16 #(
        .WIDTH(1)
    ) hact_dly_16_i (
Andrey Filippov's avatar
Andrey Filippov committed
100 101 102
        .clk(pclk),                         // input
        .rst(prst),                         // input
        .dly(SENSOR_FIFO_DELAY),            // input[3:0] 
103
        .din(pre_hact[0] && ! pre_hact[1]), // input[0:0] 
Andrey Filippov's avatar
Andrey Filippov committed
104
        .dout(hact_out_start)               // output[0:0] 
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
*/    
    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
    
    
169 170
    
    // output clock domain
Andrey Filippov's avatar
Andrey Filippov committed
171 172 173 174
//    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
175 176
//    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
177
    assign pxd_out= pxd_r;
178
    assign data_valid = hact_out_r[1];
179 180
    assign sof = sof_r;
    assign eof = eof_r;
Andrey Filippov's avatar
Andrey Filippov committed
181 182

    always @(posedge pclk) begin
183 184
//        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
185 186 187 188 189 190 191 192 193 194 195

        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;

196 197 198 199 200 201
        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
202 203 204 205 206 207 208 209

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

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

    end
210
     
Andrey Filippov's avatar
Andrey Filippov committed
211
/*
Andrey Filippov's avatar
Andrey Filippov committed
212 213 214
    always @(posedge iclk) begin
        if (irst) re_r <= 0;
        else      re_r <= pre_re;
215

Andrey Filippov's avatar
Andrey Filippov committed
216
        if    (irst) pre_hact[0] <= 0;
217 218
        else if (re) pre_hact[0] <= hact_w;

Andrey Filippov's avatar
Andrey Filippov committed
219
        if    (irst) pre_hact[1] <= 0;
220 221
        else if (re) pre_hact[1] <= pre_hact[0];

Andrey Filippov's avatar
Andrey Filippov committed
222
        if    (irst) pxd_r <= 0;
223 224
        else if (re) pxd_r <= pxd_w;

Andrey Filippov's avatar
Andrey Filippov committed
225
        if      (irst)           hact_out_r <= 0;
226 227 228
        else if (hact_out_start) hact_out_r <= 1;
        else if (!hact_w)        hact_out_r <= 0;

Andrey Filippov's avatar
Andrey Filippov committed
229 230
        if (irst) sof_r <= 0;
        else      sof_r <= re && sof_w;
231

Andrey Filippov's avatar
Andrey Filippov committed
232 233
        if (irst) eof_r <= 0;
        else      eof_r <= re && eof_w;
234 235

    end
Andrey Filippov's avatar
Andrey Filippov committed
236
*/    
237 238 239 240


endmodule