module M65C02_RAM #(
    parameter pAddrSize = 10,
    parameter pDataSize = 8,
    parameter pFileName = "M65C02_RAM.txt"
)(
    input   Clk,
    
    input   ZP,                         // Emulate LUT-based Asynchronous RAM
    input   Ext,                        // Emulate BRAM-based Pipelined SyncSRAM
    
    input   WE,
    input   [(pAddrSize - 1):0] AI,
    input   [(pDataSize - 1):0] DI,
    output  [(pDataSize - 1):0] DO
);

localparam pRAM_Max = ((2**pAddrSize) - 1);

reg     [(pDataSize - 1):0] RAM [pRAM_Max:0];

reg     rWE;
reg     [(pAddrSize - 1):0] rAI;
reg     [(pDataSize - 1):0] rDI, rDO;

wire    W;
wire    [(pAddrSize - 1):0] A;
wire    [(pDataSize - 1):0] D;

always @(posedge Clk)
begin
    {rWE, rAI, rDI} <= #1 {WE, AI, DI};
end

assign W = ((ZP) ? WE : rWE);
assign A = ((ZP) ? AI : rAI);
assign D = ((ZP) ? DI : rDI);

initial
    $readmemh(pFileName, RAM, 0, pRAM_Max);

always @(posedge Clk)
begin
    if(W)
        RAM[A] <= #1 D;
end

always @(posedge Clk)
begin
    rDO <= #1 RAM[A];
end

assign DO = ((Ext) ? rDO : RAM[A]);

endmodule