Commit a6ac2cd2 authored by Andrey Filippov's avatar Andrey Filippov
Browse files

working on the sensor input FIFO to compensate for clock domains crossing

parent 6021159e
Loading
Loading
Loading
Loading
+34 −6
Original line number Diff line number Diff line
@@ -57,6 +57,9 @@ module sensor_channel#(
    parameter SENS_CTRL_LD_DLY =   10,  // 10
    parameter SENS_CTRL_QUADRANTS =12,  // 17:12, enable - 20
    
    parameter SENSOR_DATA_WIDTH =  12,
    parameter SENSOR_FIFO_2DEPTH = 4,
    parameter SENSOR_FIFO_DELAY =  7,
    
    parameter IODELAY_GRP ="IODELAY_SENSOR", // may need different for different channels?
    parameter integer IDELAY_VALUE = 0,
@@ -114,10 +117,16 @@ module sensor_channel#(
    wire         sens_par12_status_start;
    
    wire         ipclk;   // Use in FIFO
    wire         ipclk2x; // Use in FIFO
//    wire         ipclk2x; // Use in FIFO?
    wire  [11:0] pxd_to_fifo;
    wire         vact_to_fifo;    // frame active @posedge  ipclk
    wire         hact_to_fifo;    // line active @posedge  ipclk
    
    // data from FIFO
    wire  [11:0] pxd;     // TODO: align MSB? parallel data, @posedge  ipclk
    wire         vact;    // frame active @posedge  ipclk
    wire         hact;    // line active @posedge  ipclk
    wire         sof; // start of frame
    wire         eof; // end of frame

    status_router2 status_router2_sensori (
        .rst       (rst),                     // input
@@ -205,7 +214,7 @@ module sensor_channel#(
        .rst                  (rst),                    // input
        .pclk                 (pclk),                   // input
        .ipclk                (ipclk),                  // output
        .ipclk2x              (ipclk2x),                // output
        .ipclk2x              (), // ipclk2x),          // output
        .vact                 (sns_dn[1]),              // input
        .hact                 (sns_dp[1]),              // input
        .bpf                  (sns_dn[0]),              // inout
@@ -215,9 +224,9 @@ module sensor_channel#(
        .arst                 (sns_dn[7]),              // inout
        .aro                  (sns_ctl),                // inout
        .dclk                 (sns_dp[0]),              // output
        .pxd_out              (pxd[11:0]),              // output[11:0] 
        .vact_out             (vact),                   // output
        .hact_out             (hact),                   // output: either delayed input, or regenerated from the leading edge and programmable duration
        .pxd_out              (pxd_to_fifo[11:0]),      // output[11:0] 
        .vact_out             (vact_to_fifo),                   // output
        .hact_out             (hact_to_fifo),                   // output: either delayed input, or regenerated from the leading edge and programmable duration
        .mclk                 (mclk),                   // input
        .cmd_ad               (cmd_ad),                 // input[7:0] 
        .cmd_stb              (cmd_stb),                // input
@@ -226,6 +235,25 @@ module sensor_channel#(
        .status_start         (sens_par12_status_start) // input
    );

    sensor_fifo #(
        .SENSOR_DATA_WIDTH  (SENSOR_DATA_WIDTH),
        .SENSOR_FIFO_2DEPTH (SENSOR_FIFO_2DEPTH),
        .SENSOR_FIFO_DELAY  (SENSOR_FIFO_DELAY)
    ) sensor_fifo_i (
        .rst         (rst),     // input
        .iclk        (ipclk), // input
        .pclk        (pclk), // input
        .pxd_in      (pxd_to_fifo), // input[11:0] 
        .vact        (vact_to_fifo), // input
        .hact        (hact_to_fifo), // input
        .pxd_out     (pxd), // output[11:0] 
        .data_valid  (hact), // output
        .sof         (sof), // output
        .eof         (eof) // output
    );




endmodule

sensor/sensor_fifo.v

0 → 100644
+120 −0
Original line number Diff line number Diff line
/*******************************************************************************
 * Module: sensor_fifo
 * Date:2015-05-19  
 * Author: andrey     
 * Description: Cross clock boundary for sensor data, synchronize to HACT
 *
 * Copyright (c) 2015 <set up in Preferences-Verilog/VHDL Editor-Templates> .
 * 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
)(
    input                          rst,
    input                          iclk, // input -synchronous clock
    input                          pclk, // internal lixel clock
    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;
    always @(posedge rst or posedge iclk) begin
        if (rst) {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};
    end

    fifo_cross_clocks #(
        .DATA_WIDTH(SENSOR_DATA_WIDTH+3),
        .DATA_DEPTH(SENSOR_FIFO_2DEPTH)
    ) fifo_cross_clocks_i (
        .rst        (rst), // input
        .rclk       (pclk), // input
        .wclk       (iclk), // input
        .we         (we), // input
        .re         (re), // input
        .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
        .half_empty () // output
    );

    dly_16 #(
        .WIDTH(1)
    ) hact_dly_16_i (
        .clk(pclk), // input
        .rst(rst), // input
        .dly(SENSOR_FIFO_DELAY), // input[3:0] 
        .din(pre_hact[0] && ! pre_hact[1]), // input[0:0] 
        .dout(hact_out_start) // output[0:0] 
    );
    
    // 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;
     
    always @(posedge rst or posedge iclk) begin
        if (rst) re_r <= 0;
        else     re_r <= pre_re;

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

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

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

        if      (rst)            hact_out_r <= 0;
        else if (hact_out_start) hact_out_r <= 1;
        else if (!hact_w)        hact_out_r <= 0;

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

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

    end
    


endmodule