`timescale 1ns / 1ps
module Crop_Pipeline #(
    parameter IN_WIDTH = 512,
    parameter IN_HEIGHT = 512,
    parameter OFFSET_X = 120,
    parameter OFFSET_Y = 256,
    // parameter TRANSLAYT_X = 120,
    // parameter TRANSLAYT_Y = 120,
    parameter OUT_WIDTH = 512,
    parameter OUT_HEIGHT = 512,
    parameter BLANK_COLOR = 6'h000000,
    parameter COLOR_DEPTH = 16
) (
    input wire clk,
    input wire reset,

    input  wire [COLOR_DEPTH - 1:0] in_data [3],
    output reg  [COLOR_DEPTH - 1:0] out_data[3],

    input  wire in_valid,
    output reg  out_valid,

    input  wire in_ready,
    output wire out_ready,

    input wire in_hsync,
    input wire in_fsync,

    output reg out_hsync,
    output reg out_fsync
);

  localparam PIPILINE = 3;

  reg [PIPILINE-1:0] pipeline_valid;
  wire pipeline_running;
  assign pipeline_running = in_ready | ~pipeline_valid[PIPILINE-1];

  reg [31:0] cnt_x, cnt_y, temp_x, temp_y;
  reg force_dis, force_en;
  reg [COLOR_DEPTH-1:0] data_cache0[3];
  reg [COLOR_DEPTH-1:0] data_cache1[3];

  //out_ready ：只要本模块可以接收数据就一直拉高
  assign out_ready = pipeline_running;
  //out_valid ：只要本模块可以发出数据就一直拉高
  assign out_valid = (pipeline_valid[PIPILINE-1] & ~force_dis) | force_en;

  //分别表示当前像素: 显示；被裁掉；空。
  reg [1:0] flag_crop;
  localparam CROP_ERROR = 2'b00, CROP_KEEP = 2'b01, CROP_GIVE_UP = 2'b10, CROP_BLANK = 2'b11;

  integer i;
  always @(posedge clk) begin
    if (reset) begin
      pipeline_valid <= 0;
      cnt_x <= 0;
      cnt_y <= 0;
      for (i = 0; i < 3; i++) data_cache0[i] <= 0;
      for (i = 0; i < 3; i++) data_cache1[i] <= 0;
      for (i = 0; i < 3; i++) out_data[i] <= 0;
      flag_crop <= 0;
      force_dis <= 0;
      force_en <= 0;
      out_hsync <= 0;
      out_fsync <= 0;
      temp_x <= 0;
      temp_y <= 0;
    end else if (pipeline_running) begin

      pipeline_valid <= {pipeline_valid[PIPILINE-2:0], in_valid};

      if (in_valid) begin  //when 00
        for (i = 0; i < 3; i++) data_cache0[i] <= in_data[i];
        cnt_x <= (in_hsync) ? (0) : (cnt_x + 1);
        cnt_y <= (in_hsync) ? ((in_fsync) ? (0) : (cnt_y + 1)) : (cnt_y);
      end

      if (pipeline_valid[0]) begin  //when 00
        for (i = 0; i < 3; i++) data_cache1[i] <= data_cache0[i];
        temp_x <= cnt_x;
        temp_y <= cnt_y;
        if (cnt_x < OFFSET_X || cnt_y < OFFSET_Y) flag_crop <= CROP_GIVE_UP;
        else if (cnt_x < OFFSET_X + OUT_WIDTH && cnt_y < OFFSET_Y + OUT_HEIGHT) begin
          if (cnt_x < IN_WIDTH && cnt_y < IN_HEIGHT) flag_crop <= CROP_KEEP;
          else flag_crop <= CROP_BLANK;
        end else flag_crop <= CROP_ERROR;
      end

      if (pipeline_valid[1]) begin
        for (i = 0; i < 3; i++) out_data[i] <= data_cache1[i];
        out_hsync <= (temp_x == OFFSET_X) && (temp_y >= OFFSET_Y);
        out_fsync <= (temp_x == OFFSET_X) && (temp_y == OFFSET_Y);
        case (flag_crop)
          CROP_ERROR: {force_dis, force_en} <= {1'b1, 1'b0};
          CROP_KEEP: {force_dis, force_en} <= {1'b0, 1'b0};
          CROP_GIVE_UP: {force_dis, force_en} <= {1'b1, 1'b0};
          CROP_BLANK:
          {force_dis, force_en} <= {1'b0, 1'b0};  //应该是01, 但我还没写BLANK逻辑
        endcase
      end
    end
  end


endmodule
