//RAM-BASED移位寄存器
`timescale 1ns / 1ps

module SHIFT_REGISTER #(
    parameter reg [4:0] DATA_WIDTH = 16,  // 输入/输出数据位宽
    parameter IMAGE_WIDTH = 1936,  //MAX 2048
    parameter IFOUTIMME = 1'b0 //此项为0时，直至RAM存满IMAGE_WIDTH后再输出valid，为1时立即输出valid，无论是否存满
) (
    // 基本信号
    input wire clk,
    input wire reset,
    //  数据线
    input wire [DATA_WIDTH - 1:0] in_data,
    output wire [DATA_WIDTH - 1:0] out_data,
    //  有效信号
    input wire in_valid,  // 上一模块输出数据有效
    output wire out_valid  // 当前模块输出数据有效
);

  reg [10:0] addr_a, addr_b;
  wire cea, ceb;
  reg fulldone;

  reg in_valid_temp0, in_valid_temp1;
  always @(posedge clk) in_valid_temp0 <= in_valid && (fulldone || IFOUTIMME);
  always @(posedge clk) in_valid_temp1 <= in_valid_temp0;

  assign cea = in_valid;
  assign ceb = in_valid_temp0;
  assign out_valid = in_valid_temp1;

  always @(posedge clk) begin
    if (reset) fulldone <= 0;
    else if (addr_b == IMAGE_WIDTH - 1) fulldone <= 1;
    else fulldone <= fulldone;
  end


  always @(posedge clk) begin
    if (reset) begin
      addr_a <= IMAGE_WIDTH + 1;
      addr_b <= 0;
    end else if (cea) begin
      addr_a <= addr_a + 1;
      addr_b <= addr_b + 1;
    end else begin
      addr_a <= addr_a;
      addr_b <= addr_b;
    end
  end

  // Single-Double-Port-BRAM-IP Bypass Normal
  Gowin_SDPB Gowin_SDPB_inst (
      .clka (clk),   //input clka
      .clkb (clk),   //input clkb
      .reset(reset), //input reset

      .cea(cea),  //input cea
      .ceb(ceb),  //input ceb

      .ada(addr_a),  //input [10:0] ada
      .adb(addr_b),  //input [10:0] adb

      .din (in_data),  //input [15:0] din
      .dout(out_data), //output [15:0] dout

      .oce(1)  //input oce
  );

endmodule


