sensor_fifo.v 8.92 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
 * 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/> .
20 21 22 23 24 25
 *
 * 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"
26
 * files and/or simulating the code, the copyright holders of this Program give
27 28
 * 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
29
 * charge, and there is no dependence on any encrypted modules for simulating of
30 31 32
 * 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.
33 34 35 36 37 38
 *******************************************************************************/
`timescale 1ns/1ps

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

    always @(posedge pclk) begin
178 179
//        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
180 181 182 183 184 185 186 187 188 189 190

        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;

191 192 193 194 195 196
        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
197 198 199 200 201 202 203 204

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

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

    end
205
     
Andrey Filippov's avatar
Andrey Filippov committed
206
/*
Andrey Filippov's avatar
Andrey Filippov committed
207 208 209
    always @(posedge iclk) begin
        if (irst) re_r <= 0;
        else      re_r <= pre_re;
210

Andrey Filippov's avatar
Andrey Filippov committed
211
        if    (irst) pre_hact[0] <= 0;
212 213
        else if (re) pre_hact[0] <= hact_w;

Andrey Filippov's avatar
Andrey Filippov committed
214
        if    (irst) pre_hact[1] <= 0;
215 216
        else if (re) pre_hact[1] <= pre_hact[0];

Andrey Filippov's avatar
Andrey Filippov committed
217
        if    (irst) pxd_r <= 0;
218 219
        else if (re) pxd_r <= pxd_w;

Andrey Filippov's avatar
Andrey Filippov committed
220
        if      (irst)           hact_out_r <= 0;
221 222 223
        else if (hact_out_start) hact_out_r <= 1;
        else if (!hact_w)        hact_out_r <= 0;

Andrey Filippov's avatar
Andrey Filippov committed
224 225
        if (irst) sof_r <= 0;
        else      sof_r <= re && sof_w;
226

Andrey Filippov's avatar
Andrey Filippov committed
227 228
        if (irst) eof_r <= 0;
        else      eof_r <= re && eof_w;
229 230

    end
Andrey Filippov's avatar
Andrey Filippov committed
231
*/    
232 233 234 235


endmodule