
module sram_sp_pcie_768x25 #(
  parameter WIDTH = 25,
  parameter DEPTH = 768,
  parameter IN_PIPE = 0,
  parameter OUT_PIPE = 1
)(
  input  wire                     CLK,
  input  wire                     CEB,
  input  wire                     WEB,
  input  wire [$clog2(DEPTH)-1:0] A,
  input  wire [WIDTH-1:0]         D,
  input  wire [WIDTH-1:0]         BWEB,
  input  wire                     SD,
  input  wire [1:0]               RTSEL,
  input  wire [1:0]               WTSEL,
  output wire [WIDTH-1:0]         Q
);

localparam ADDR_WIDTH = $clog2(DEPTH);
wire sram_ceb;
wire sram_web;
wire [WIDTH-1:0] sram_bweb;
wire [ADDR_WIDTH-1:0] sram_addr;
wire [WIDTH-1:0] sram_rdata;
wire [WIDTH-1:0] sram_wdata;

wire [2-1:0] WTSEL = mem_ctrl_bus[45:44];


`ifdef USE_N12_TSMC_SRAM
    if(DEPTH==768 && WIDTH==25) begin : GEN_768x25_SRAM
        TS1N12FFCLLUVLTA768X25M4SWSHOCP U_TS1N12FFCLLUVLTA768X25M4SWSHOCP (
          .CLK   (CLK),
          .CEB   (sram_ceb),
          .WEB   (sram_web),
          .BWEB  (sram_bweb),
          .A     (sram_addr),
          .D     (sram_wdata),
          .Q     (sram_rdata),
          .SLP   (1'b0),
          .DSLP  (1'b0),
          .SD    (SD),
          .RTSEL (RTSEL),
          .WTSEL (WTSEL),
          .FADIO (9'b0),
          .REDENIO (1'b0),
          .PUDELAY (  )
        );
    end
    else begin : ILLEGAL_SRAM_SIZE
        $display("Error: Unsupported SRAM size %d x %d for TSMC N12 SRAM", WIDTH, DEPTH);
    end

`elsif USE_N12_SNPS_SRAM

`elsif USE_N7_TSMC_SRAM

`elsif USE_N7_SNPS_SRAM

`else

    reg [WIDTH-1:0] ram [DEPTH-1:0];
    reg [WIDTH-1:0] rdata_ff;
    integer i;

    always @(posedge CLK) begin
      if (CEB == 1'b0) begin
        if (WEB == 1'b0) begin // write
          for (i = 0; i < WIDTH; i = i + 1) begin
            if (BWEB[i] == 1'b0) ram[A][i] <= D[i];
          end
        end
        else begin // read
          rdata_ff <= ram[A];
        end
      end
    end

    assign sram_rdata = rdata_ff;
`endif

// Input PIPE
generate
  if(IN_PIPE==1) begin : GEN_IN_PIPE_1
    reg          ceb_ff;
    reg          web_ff;
    reg [WIDTH-1:0]  bweb_ff;
    reg [ADDR_WIDTH-1:0] a_ff;
    reg [WIDTH-1:0]  d_ff;
    
    always @(posedge CLK) begin
      if(CEB==1'b0) begin
        ceb_ff <= 1'b0;
        web_ff <= WEB;
        bweb_ff <= BWEB;
        a_ff <= A;
        d_ff <= D;
      end
      else begin
        ceb_ff <= 1'b1;
      end
    end
    
    assign sram_ceb  = ceb_ff;
    assign sram_web  = web_ff;
    assign sram_bweb = bweb_ff;
    assign sram_addr = a_ff;
    assign sram_wdata = d_ff;
  end
  else begin : GEN_IN_PIPE_0
    assign sram_ceb  = CEB;
    assign sram_web  = WEB;
    assign sram_bweb = BWEB;
    assign sram_addr = A;
    assign sram_wdata = D;
  end
endgenerate

// Output PIPE
generate
  if(OUT_PIPE==1) begin : GEN_OUT_PIPE_1
    reg             sram_ren_ff;
    reg [WIDTH-1:0] sram_rdata_ff;
    
    always @(posedge CLK) begin
      if(CEB==1'b0 && WEB==1'b1) begin
        sram_ren_ff <= 1'b1;  // flag indicating read operation
      end
      else begin
        sram_ren_ff <= 1'b0;
      end
    end
    
    always @(posedge CLK) begin
      if(sram_ren_ff==1'b1) begin
        sram_rdata_ff <= sram_rdata;  // latch read data
      end
      else begin
        sram_rdata_ff <= sram_rdata_ff;
      end
    end

    assign Q = sram_rdata_ff;  // output latched data
  end
  else begin : GEN_OUT_PIPE_0
    assign Q = sram_rdata;  // direct output
  end

endgenerate

endmodule: $moduleName$