// (C) 2001-2024 Intel Corporation. All rights reserved.
// Your use of Intel Corporation's design tools, logic functions and other 
// software and tools, and its AMPP partner logic functions, and any output 
// files from any of the foregoing (including device programming or simulation 
// files), and any associated documentation or information are expressly subject 
// to the terms and conditions of the Intel Program License Subscription 
// Agreement, Intel FPGA IP License Agreement, or other applicable 
// license agreement, including, without limitation, that your use is for the 
// sole purpose of programming logic devices manufactured by Intel and sold by 
// Intel or its authorized distributors.  Please refer to the applicable 
// agreement for further details.


// Copyright 2021 Intel Corporation. 
//
// This reference design file is subject licensed to you by the terms and 
// conditions of the applicable License Terms and Conditions for Hardware 
// Reference Designs and/or Design Examples (either as signed by you or 
// found at https://www.altera.com/common/legal/leg-license_agreement.html ).  
//
// As stated in the license, you agree to only use this reference design 
// solely in conjunction with Intel FPGAs or Intel CPLDs.  
//
// THE REFERENCE DESIGN IS PROVIDED "AS IS" WITHOUT ANY EXPRESS OR IMPLIED
// WARRANTY OF ANY KIND INCLUDING WARRANTIES OF MERCHANTABILITY, 
// NONINFRINGEMENT, OR FITNESS FOR A PARTICULAR PURPOSE. Intel does not 
// warrant or assume responsibility for the accuracy or completeness of any
// information, links or other items within the Reference Design and any 
// accompanying materials.
//
// In the event that you do not agree with such terms and conditions, do not
// use the reference design file.
/////////////////////////////////////////////////////////////////////////////

(* altera_attribute = "-name SYNCHRONIZER_IDENTIFICATION OFF" *)
module generic_mlab_sc #(
    parameter WIDTH = 8,
    parameter ADDR_WIDTH = 5,
    parameter FAMILY = "Other" // Agilex, S10, or Other
)(
    input clk,
    input [WIDTH-1:0] din,
    input [ADDR_WIDTH-1:0] waddr,
    input we,
    input re,
    input [ADDR_WIDTH-1:0] raddr,
    output [WIDTH-1:0] dout
);

genvar i;
generate
if (FAMILY == "S10") begin    
    reg [WIDTH-1:0] wdata_hipi;
    always @(posedge clk) wdata_hipi <= din;
        
    for (i=0; i<WIDTH; i=i+1)  begin : ml
        wire wclk_w = clk; // fix strange tristate warning
        wire rclk_w = clk; // fix strange tristate warning
        fourteennm_mlab_cell lrm (
            .clk0(wclk_w),
            .ena0(we),
            .clk1(rclk_w),
            .ena1(re),
                
            // synthesis translate off
            .clr(1'b0),
            .devclrn(1'b1),
            .devpor(1'b1),
            // synthesis translate on           

            .portabyteenamasks(1'b1),
            .portadatain(wdata_hipi[i]),
            .portaaddr(waddr),
            .portbaddr(raddr),
            .portbdataout(dout[i])          
        );

        defparam lrm .mixed_port_feed_through_mode = "dont_care";
        defparam lrm .logical_ram_name = "lrm";
        defparam lrm .logical_ram_depth = 1 << ADDR_WIDTH;
        defparam lrm .logical_ram_width = WIDTH;
        defparam lrm .first_address = 0;
        defparam lrm .last_address = (1 << ADDR_WIDTH)-1;
        defparam lrm .first_bit_number = i;
        defparam lrm .data_width = 1;
        defparam lrm .address_width = ADDR_WIDTH;
        defparam lrm .port_b_data_out_clock = "clock1";
    end
    
end else if (FAMILY == "Agilex") begin    
        
    for (i=0; i<WIDTH; i=i+1)  begin : ml
        wire wclk_w = clk; // fix strange tristate warning
        wire rclk_w = clk; // fix strange tristate warning
        tennm_mlab_cell lrm (
            .clk0(wclk_w),
            .ena0(we),
            .clk1(rclk_w),
            .ena1(re),
                
            // synthesis translate off
            .clr(1'b0),
            .devclrn(1'b1),
            .devpor(1'b1),
            // synthesis translate on           

            .portabyteenamasks(1'b1),
            .portadatain(din[i]),
            .portaaddr(waddr),
            .portbaddr(raddr),
            .portbdataout(dout[i])          
        );

        defparam lrm .mixed_port_feed_through_mode = "dont_care";
        defparam lrm .logical_ram_name = "lrm";
        defparam lrm .logical_ram_depth = 1 << ADDR_WIDTH;
        defparam lrm .logical_ram_width = WIDTH;
        defparam lrm .first_address = 0;
        defparam lrm .last_address = (1 << ADDR_WIDTH)-1;
        defparam lrm .first_bit_number = i;
        defparam lrm .data_width = 1;
        defparam lrm .address_width = ADDR_WIDTH;
        defparam lrm .port_b_data_out_clock = "clock1";
    end
    
    
end else begin

    localparam DEPTH = 1 << ADDR_WIDTH;
    (* ramstyle = "mlab" *) reg [WIDTH-1:0] mem[0:DEPTH-1];

    reg [WIDTH-1:0] dout_r;
    always @(posedge clk) begin
        if (we)
            mem[waddr] <= din;
        if (re)
            dout_r <= mem[raddr];
    end
    assign dout = dout_r;

end
endgenerate    

endmodule
`ifdef QUESTA_INTEL_OEM
`pragma questa_oem_00 "Vd3tEFjpZj96rI/+F/VvE60mTEymAEQpoSTBEGkPZDn8vLE37C5u3t6a/YuDWdcpDICg4yaS41BVZL43rgMWoo/ODQa6HJ+98xz96XdaxZoH7knVWHHmdjwNoot126KwBXxYxMAyWcKq2a9b9HntBfzAKtQF4cCehbSzlUccpMg8lYZJJ73s4nMHdujybKqOU3uA0uLLaEuflzNF5/A5MXI1hPhdpBgL5/hYcV95h9NowH+sVmCMI2/JEoE994HUE+SdRYCBe9Su+oXhT02pq8o3GC/jc/nzjR0qhD4BDIEQMc76aXfmDPPPF+fMdThaCj1Wa+r+GR9zjXhRq325E4SefFRpFkNYwsHaqJzPF9xUpmHyxr0ZriCgUU+ovrKjcoVN1Fpxy1cniadUO8w3m4zTZ0oVkHHMuJ5daQ4q0C34pRwAzZtHe18gTi+raOARjNDR+SBFb6PHEIMvTwgbj9y4n9/oOSi+hz69MNtZI413Hpv9kP0/RKDGyPOor7wCYvYHvUt5Sqn0jCe69OXi85YkT/7PggqmG/gD7OU0H5fdvo2bPHcDgiJrOWblcmauWH6DAqe2CwyEo48s4/WHtjzsu2YTaE1eJA3fnSPLl5IQPIWyVbhlw0HKUnd9Es0Ll4vDwooc/5XGpmRuEpw1DFU6TAhxJk19jEIM6zBCJRhHIw6q1Y1ojiJE7IOO6gstRskFAcgldraOAvIuhfO8ZdaWSdLEP5tpf4hDcWEM3nOWpxr6UHIpcxzYTbSda7+x6S1wbjIh5KGceMYpNNEIh1T9AbRWDc+eUpG7InOsAeoucGbEkANVvXuOmfjKnzrqzfRU/V+YSFY7O6STGfA4BIX6PtvdbCGadRqzLTy46SSQkzXP13PxocnU7IF7heJyWM4Zd62lLPX/34SYc/4ZjNr0guuDME8QdGEOecqG5ZzIB5ggUE6DwnqzV1G22QUdpsBy55GsTs/JLj0T75cMPIGbGCDaPofIaPaD1eup2sZRCjf99nd/FIaUnc/13Kr/"
`endif