
module ${SramWrapName} #(
    parameter WIDTH = ${Width},
    parameter DEPTH = ${Depth},
    parameter IN_PIPE = 0,
    parameter OUT_PIPE = 1
)(
    input wire CLK,       // Write/Read Clock, Sync type SRAM
    input wire WEB,       // Write Enable, Active-low
    input wire [$clog2(DEPTH)-1:0] AA,  // Write Address
    input wire [WIDTH-1:0] D,           // Write Data
    input wire [WIDTH-1:0] BWEB,        // Bit mask Write Enable, Active-low
    input wire REB,                     // Read Enable, Active-low
    input wire [$clog2(DEPTH)-1:0] AB,  // Read Address
    
    input wire mem_ctrl_bus_sd,
    input wire [64 -1:0] mem_ctrl_bus,
    
    output wire [WIDTH-1:0] Q           // Read Data Output
);

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

    wire SD     = mem_ctrl_bus_sd;
    wire [2 -1:0] RTSEL  = mem_ctrl_bus[63:62];
    wire [2 -1:0] MTSEL  = mem_ctrl_bus[59:58];
    wire [2 -1:0] WTSEL  = mem_ctrl_bus[55:54];

    `ifdef USE_N12_TSMC_SRAM
    generate
        if(DEPTH==${Depth} && WIDTH==${Width}) begin : GEN_${Depth}X${Width}_SRAM
            localparam RTSEL_VAL = 2'b01;
            localparam WTSEL_VAL = 2'b01;
            localparam MTSEL_VAL = 2'b01;
            
            ${ReferenceName} U_${ReferenceName} (
                .CLK   (CLK         ),
                .WEB   (sram_web    ),
                .AA    (sram_waddr  ),
                .D     (sram_wdata  ),
                .BWEB  (sram_bweb   ),
                .REB   (sram_reb    ),
                .AB    (sram_raddr  ),
                .Q     (sram_rdata  ),
                //.BIST  (1'b0), 
                //.WEBM  (1'b0),
                //.AMA   ({ADDR_WIDTH{1'b0}}),
                //.DM    (0)
                //.BWEBM (0),
                //.REBM  (1'b0),
                //.AMB   ({ADDR_WIDTH{1'b0}}),
                .RTSEL (RTSEL),
                .WTSEL (WTSEL),
                .MTSEL (MTSEL),
                .SLP   (1'b0),    
                .DSLP  (1'b0),    
                .SD    (SD),      
                .PUDELAY ( ),     
                .FADIO (9'd0),    
                .REDENIO (1'b0)   
            );
        end
        else begin : ILLEAGAL_SIZE_SRAM
            //$display("\tERROR %m : Illegal SRAM size. %t\n", $realtime);
        end
    endgenerate
`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 (WEB == 1'b0) begin // write
            for (i = 0; i < WIDTH; i = i + 1) begin
                if (BWEB[i] == 1'b0) 
                    ram[AA][i] <= D[i]; 
            end
        end
    end

    // 读操作
    always @(posedge CLK) begin
        if (REB == 1'b0) begin // read
            rdata_ff <= ram[AB];  
        end
    end
    assign sram_rdata = rdata_ff;
`endif

// Input PIPE
generate
    if(IN_PIPE==1) begin : GEN_IN_PIPE_1
        reg          web_ff;
        reg [WIDTH-1:0]  bweb_ff;
        reg [ADDR_WIDTH-1:0] aa_ff;
        reg [ADDR_WIDTH-1:0] ab_ff;
        reg [WIDTH-1:0]  d_ff;
        reg          reb_ff;
        
        always @(posedge CLK) begin
            if(WEB==1'b0) begin
                web_ff  <= 1'b0;
                bweb_ff <= BWEB;
                aa_ff   <= AA;
                d_ff    <= D;
            end
            else begin
                web_ff  <= 1'b1;
            end
        end
        
        always @(posedge CLK) begin
            if(REB==1'b0) begin
                reb_ff  <= 1'b0;
                ab_ff   <= AB;
            end
            else begin
                reb_ff  <= 1'b1;
            end
        end
        
        assign sram_web   = web_ff;
        assign sram_waddr = aa_ff;
        assign sram_wdata = d_ff;
        assign sram_bweb  = bweb_ff;
        assign sram_reb   = reb_ff;
        assign sram_raddr = ab_ff;
    end
    else begin : GEN_IN_PIPE_0
        assign sram_web   = WEB;
        assign sram_waddr = AA;
        assign sram_wdata = D;
        assign sram_bweb  = BWEB;
        assign sram_reb   = REB;
        assign sram_raddr = AB;
    end
endgenerate

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(REB == 1'b0) begin
                sram_ren_ff <= 1'b1;  
            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; 
            end
            else begin
                sram_rdata_ff <= sram_rdata_ff;  // 保持上一个值
            end
        end
        assign Q = sram_rdata_ff; 
    end
    else begin : GEN_OUT_PIPE_0
        assign Q = sram_rdata; 
    end
endgenerate

endmodule