`timescale 1ns / 1ps

module isp_Pipeline #(
    parameter reg [15:0] IN_WIDTH    = 1936,
    parameter reg [15:0] IN_HEIGHT   = 1088,
    parameter            OFFSET_X    = 7,
    parameter            OFFSET_Y    = 3,
    parameter reg [15:0] OUT_WIDTH   = 1920,
    parameter reg [15:0] OUT_HEIGHT  = 1080,
    parameter reg [ 4:0] COLOR_DEPTH = 8,     // Can't Change!!!
    parameter reg [ 1:0] RAW_TYPE    = 3      // 0:grbg 1:rggb 2:bggr 3:gbrg
) (
    // 基本信号
    input wire clk,
    input wire reset,

    // 数据线
    input wire [15:0] in_data[3],  // 数据输入线，0、1、2分别表示第一、二、三行
    output wire [3 * COLOR_DEPTH - 1:0] out_data,

    // 数据有效信号
    input  wire in_valid,
    output wire out_valid,

    // 准备信号
    input  wire in_ready,
    output wire out_ready,

    // 颜色校正，低八位为小数位，高八位为整数位
    input wire [15:0] gain_red,
    input wire [15:0] gain_green,
    input wire [15:0] gain_blue,
    input wire blender_enable  // 是否启用颜色校正
);

  wire [15:0] Demosaic2_data[3];
  wire [15:0] Windows_data[9];
  wire [COLOR_DEPTH - 1 : 0] Blender_data[3];
  wire [COLOR_DEPTH - 1 : 0] Crop_data[3];
  wire Windows_valid, Demosaic2_valid, Blender_valid, Crop_valid;
  wire Windows_ready, Demosaic2_ready, Blender_ready, Crop_ready;
  wire Demosaic2_hsync, Blender_hsync, Crop_hsync;
  wire Demosaic2_fsync, Blender_fsync, Crop_fsync;
  assign out_valid = Crop_valid;
  assign out_ready = Windows_ready;
  assign out_data  = {Crop_data[2], Crop_data[1], Crop_data[0]};

  Windows #(
      .DATA_WIDTH(16)
  ) Windows_inst (
      .clk      (clk),
      .reset    (reset),
      .in_data  (in_data),
      .out_data (Windows_data),
      .in_valid (in_valid),
      .out_valid(Windows_valid),
      .in_ready (Demosaic2_ready),
      .out_ready(Windows_ready)
  );


  Demosaic_Pipeline #(
      .WINDOW_LENGTH(3),
      .TOTAL_WIDTH  (IN_WIDTH),
      .TOTAL_HEIGHT (IN_HEIGHT),
      .RAW_TYPE     (RAW_TYPE),
      .DATA_WIDTH   (16)
  ) Demosaic2_inst (
      .clk      (clk),
      .reset    (reset),
      .in_data  (Windows_data),
      .out_data (Demosaic2_data),
      .in_valid (Windows_valid),
      .out_valid(Demosaic2_valid),
      .in_ready (Blender_ready),
      .out_ready(Demosaic2_ready),
      .out_hsync(Demosaic2_hsync),
      .out_fsync(Demosaic2_fsync)
  );

  ColorBlender_Pipeline #(
      .IN_DEPTH(12),  // 输入图像的色深
      .OUT_DEPTH(COLOR_DEPTH)  // 输出图像的色深
  ) ColorBlender_inst (
      .clk      (clk),
      .reset    (reset),
      .in_data  (Demosaic2_data),
      .out_data (Blender_data),
      .in_valid (Demosaic2_valid),
      .out_valid(Blender_valid),
      .in_ready (Crop_ready),
      .out_ready(Blender_ready),
      .in_hsync (Demosaic2_hsync),
      .in_fsync (Demosaic2_fsync),
      .out_hsync(Blender_hsync),
      .out_fsync(Blender_fsync),

      .gain_red  (gain_red),
      .gain_green(gain_green),
      .gain_blue (gain_blue),
      .enable    (blender_enable)
  );

  Crop_Pipeline #(
      .IN_WIDTH   (IN_WIDTH),
      .IN_HEIGHT  (IN_HEIGHT),
      .OFFSET_X   (OFFSET_X),
      .OFFSET_Y   (OFFSET_Y),
      .OUT_WIDTH  (OUT_WIDTH),
      .OUT_HEIGHT (OUT_HEIGHT),
      .COLOR_DEPTH(COLOR_DEPTH)
  ) Crop_inst (
      .clk      (clk),
      .reset    (reset),
      .in_data  (Blender_data),
      .out_data (Crop_data),
      .in_valid (Blender_valid),
      .out_valid(Crop_valid),
      .in_ready (in_ready),
      .out_ready(Crop_ready),
      .in_hsync (Blender_hsync),
      .in_fsync (Blender_fsync),
      .out_hsync(Crop_hsync),
      .out_fsync(Crop_fsync)
  );

  // reg [15:0] data_out_temp[8192];
  // reg [31:0] now;
  // reg [2:0] cnt_www;
  // reg flag_ifdataerror;

  // initial cnt_www = 0;
  // always @(posedge reset) begin
  //     cnt_www <= cnt_www + 1;
  // end

  // integer i;
  // always @(posedge clk) begin
  //     if(reset) begin
  //         flag_ifdataerror <= 0;
  //         if(cnt_www==1) for(i=0;i<8192;i=i+1) data_out_temp[i] <= 0;
  //         now <= 0;
  //     end else if(Crop_valid && in_ready)begin
  //         now <= now + 1;
  //         if(cnt_www==1)begin
  //             if(now<8192) data_out_temp[now] <= Crop_data[0];
  //         end else if(cnt_www==2)begin
  //             flag_ifdataerror <= (data_out_temp[now] != Crop_data[0]);
  //         end else flag_ifdataerror <= flag_ifdataerror;
  //     end
  // end

endmodule
