`timescale 1 ns / 100 ps
// ********************************************************************/
// Copyright 2008 Actel Corporation.  All rights reserved.
// IP Engineering
//
// ANY USE OR REDISTRIBUTION IN PART OR IN WHOLE MUST BE HANDLED IN
// ACCORDANCE WITH THE ACTEL LICENSE AGREEMENT AND MUST BE APPROVED
// IN ADVANCE IN WRITING.
//
// File:  ramblocks.vhd
//
// Description: Simple APB Bus Controller
//              Selects how to build the RAM block based on the family
//
// Rev: 2.4   24Jan08 IPB  : Production Release
//
// SVN Revision Information:
// SVN $Revision: 14690 $
// SVN $Date: 2010-12-16 16:30:22 +0000 (Thu, 16 Dec 2010) $
//
// Notes:
//
// *********************************************************************/

module SF_Zi1_COREABC_0_RAMBLOCKS (CLK, RESETN, WEN, ADDR, WD, RD);

    parameter  DWIDTH  = 0;
    parameter  FAMILY  = 0;

    input CLK;
    input RESETN;
    input WEN;
    input[7:0] ADDR;
    input[DWIDTH - 1:0] WD;
    output[DWIDTH - 1:0] RD;
    reg[DWIDTH - 1:0] RD;

    wire[DWIDTH - 1:0] RDW;

    wire[15:0] WDX;
    wire[15:0] RDX;
    wire[15:0] WDY;
    wire[15:0] RDY;
    wire[31:0] RDYY;
    wire RENX;
    wire Logic0;
    wire Logic1;
    wire[8:0] ADDR9;
    wire[31:0] RD32;
    wire[31:0] WD32;

    assign Logic0 = 1'b0 ;
    assign Logic1 = 1'b1 ;
    assign RENX = ~WEN ;
    assign ADDR9 = {1'b0, ADDR};

    generate
        if (FAMILY == 0)
        begin : UG0

            //---------------------------------------------------------------------------
            // Use Behavioural RAM
            //
            always @(posedge CLK)
            begin : xhdl_6
                reg[DWIDTH - 1:0] RAM[0:255];
                reg[7:0] maddr;
                reg[7:0] iaddr;

                iaddr = 0;
                maddr = 0;

                begin : xhdl_5
                    integer i;
                    for(i = 0; i <= 7; i = i + 1)
                    begin
                        // remove x's in sim
                        if ((ADDR[i]) == 1'b1)
                        begin
                            maddr[i] = 1'b1;
                        end
                    end
                end
                iaddr = maddr;
                if (WEN == 1'b1)
                begin
                    RAM[iaddr] = WD;
                end
                RD <= RAM[iaddr] ;
            end
        end
    endgenerate

    generate
        if (FAMILY == 11 | FAMILY == 12)
        begin : UG1

            if (DWIDTH == 8 | DWIDTH == 16)
            begin : UR816
                //---------------------------------------------------------------------------
                // AX
                // For 8/16 bit use a  256x16 memory  = 1 memory element
                // For 32 bit use a 128x32 memory  = 1 memory element
                SF_Zi1_COREABC_0_RAM256X16 UR (
                    .RWCLK(CLK),
                    .RESET(RESETN),
                    .WEN(WEN),
                    .REN(RENX),
                    .WADDR(ADDR),
                    .RADDR(ADDR),
                    .WD(WDX),
                    .RD(RDX)
                );
            end

            if (DWIDTH == 8)
            begin : UR8
                assign WDX = {8'b00000000, WD} ;
                wire[DWIDTH - 1:0] wire_xhdl8 = RDX[7:0] ;
                always @(wire_xhdl8)
                begin
                    RD <= wire_xhdl8;
                end
            end

            if (DWIDTH == 16)
            begin : UR16
                assign WDX = WD ;
                wire[DWIDTH - 1:0] wire_xhdl10 = RDX ;
                always @(wire_xhdl10)
                begin
                    RD <= wire_xhdl10;
                end
            end

            if (DWIDTH == 32)
            begin : UR32B
                SF_Zi1_COREABC_0_RAM256X16 URA (
                    .RWCLK(CLK),
                    .RESET(RESETN),
                    .WEN(WEN),
                    .REN(RENX),
                    .WADDR(ADDR),
                    .RADDR(ADDR),
                    .WD(WD[15:0]),
                    .RD(RDYY[15:0])
                );
                SF_Zi1_COREABC_0_RAM256X16 URB (
                    .RWCLK(CLK),
                    .RESET(RESETN),
                    .WEN(WEN),
                    .REN(RENX),
                    .WADDR(ADDR),
                    .RADDR(ADDR),
                    .WD(WD[31:16]),
                    .RD(RDYY[31:16])
                );
            end

            if (DWIDTH == 32)
            begin
                always @(RDYY)
                begin
                    RD <= RDYY;
                end
            end

        end
    endgenerate

    generate
        if (FAMILY == 14)
        begin : UG2

            genvar i;
            for (i = 0; i <= DWIDTH / 8 - 1; i = i + 1)
            begin : UR
                //---------------------------------------------------------------------------
                // APA
                // Use multiple 8-bit RAM
                //
                SF_Zi1_COREABC_0_RAM256X8 UR_xhdl11 (
                    .RWCLK(CLK),
                    .RESET(CLK),
                    .WEN(WEN),
                    .REN(Logic1),
                    .WADDR(ADDR),
                    .RADDR(ADDR),
                    .WD(WD[i * 8 + 7:i * 8]),
                    .RD(RDW[i * 8 + 7:i * 8])
                );
            end
            always@(RDW) RD <= RDW;
        end
    endgenerate

    generate
        if (  FAMILY == 15 | FAMILY == 16 | FAMILY == 17 | FAMILY == 18
            | FAMILY == 20 | FAMILY == 21 | FAMILY == 22 | FAMILY == 23 )	 //SAR73685
            begin : UG3
            //---------------------------------------------------------------------------
            // PA3/PA3E/PA3L/Fusion/SmartFusion/IGLOO/IGLOOe/IGLOO+
            //
            SF_Zi1_COREABC_0_RAM256X16 UR_xhdl12 (
                .RWCLK(CLK),
                .RESET(RESETN),
                .WEN(WEN),
                .REN(RENX),
                .WADDR(ADDR),
                .RADDR(ADDR),
                .WD(WDX),
                .RD(RDX)
            );

            if (DWIDTH == 8)
            begin : UR8
                assign WDX = {8'b00000000, WD} ;
                wire[DWIDTH - 1:0] wire_xhdl14 = RDX[7:0] ;
                always @(wire_xhdl14)
                begin
                    RD <= wire_xhdl14;
                end
            end

            if (DWIDTH == 16)
            begin : UR16
                assign WDX = WD ;
                wire[DWIDTH - 1:0] wire_xhdl16 = RDX ;
                always @(wire_xhdl16)
                begin
                    RD <= wire_xhdl16;
                end
            end

            if (DWIDTH == 32)
            begin : UR32
                // REN could simply be tied high in this circuit, but the Actel RAM models will generate a
                // warning message every time the memory is written.
                // So when WEN is high we force REN low !
                SF_Zi1_COREABC_0_RAM256X16 UR0 (
                    .RWCLK(CLK),
                    .RESET(RESETN),
                    .WEN(WEN),
                    .REN(RENX),
                    .WADDR(ADDR),
                    .RADDR(ADDR),
                    .WD(WDY),
                    .RD(RDY)
                );
                assign WDX = WD[15:0] ;
                assign WDY = WD[31:16] ;
                wire[DWIDTH - 1:0] wire_xhdl19 = {RDY, RDX} ;
                always @(wire_xhdl19)
                begin
                    RD <= wire_xhdl19;
                end
            end
        end
    endgenerate


endmodule
