// ****************************************************************************/
// Actel Corporation Proprietary and Confidential
// Copyright 2010 Actel Corporation.  All rights reserved.
//
// 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.
//
// Description: CoreAXI - slave bfm 
//
// Revision Information:
// Date            Description
// ----            -----------------------------------------
// 07Feb11         
//
// SVN Revision Information:
// SVN $Revision: 11146 $
// SVN $Date: 2009-11-21 11:44:53 -0800 (Sat, 21 Nov 2009) $
//
// Resolved SARs
// SAR      Date     Who   Description
//
// Notes:
// 1. 
//
// ****************************************************************************/
`timescale 1ns/1ps
module axi_slave (
    // Global signals
        ACLK
    ,   ARESETN

    // SLAVE
    // AXI SLAVE write address channel signals
    ,   AWID
    ,   AWADDR
    ,   AWLEN
    ,   AWSIZE
    ,   AWBURST
    ,   AWLOCK
    ,   AWCACHE
    ,   AWPROT
    ,   AWVALID
    ,   AWREADY
    // AXI SLAVE write data channel signals
    ,   WID
    ,   WDATA
    ,   WSTRB
    ,   WLAST
    ,   WVALID
    ,   WREADY
    // AXI SLAVE write response channel signals
    ,   BID
    ,   BRESP
    ,   BVALID
    ,   BREADY
    // AXI SLAVE read address channel signals
    ,   ARID
    ,   ARADDR
    ,   ARLEN
    ,   ARSIZE
    ,   ARBURST
    ,   ARLOCK
    ,   ARCACHE
    ,   ARPROT
    ,   ARVALID
    ,   ARREADY
    // AXI SLAVE read response channel signals
    ,   RID
    ,   RDATA
    ,   RRESP
    ,   RLAST
    ,   RVALID
    ,   RREADY
);
    parameter AXI_AWIDTH        = 32;
    parameter AXI_DWIDTH        = 64;
    localparam BASE_ID_WIDTH = 0;
    parameter ID_WIDTH = 4;
    localparam AXI_STRBWIDTH    = AXI_DWIDTH/8;

    // Global signals
    input                          ACLK;
    input                          ARESETN;

    // SLAVE
    // AXI SLAVE write address channel signals
    input      [BASE_ID_WIDTH +  ID_WIDTH - 1:0]               AWID;
    input      [AXI_AWIDTH-1:0]    AWADDR;
    input      [3:0]               AWLEN;
    input      [2:0]               AWSIZE;
    input      [1:0]               AWBURST;
    input      [1:0]               AWLOCK;
    input      [3:0]               AWCACHE;
    input      [2:0]               AWPROT;
    input                          AWVALID;
    output                      AWREADY;
    // AXI SLAVE write data channel signals
    input      [BASE_ID_WIDTH +  ID_WIDTH - 1:0]               WID;
    input      [AXI_DWIDTH-1:0]    WDATA;
    input      [AXI_STRBWIDTH-1:0] WSTRB;
    input                          WLAST;
    input                          WVALID;
    output                      WREADY;
    // AXI SLAVE write response channel signals
    output reg [BASE_ID_WIDTH +  ID_WIDTH - 1:0]               BID;
    output reg [1:0]               BRESP;
    output reg                     BVALID;
    input                          BREADY;
    // AXI SLAVE read address channel signals
    input      [BASE_ID_WIDTH +  ID_WIDTH - 1:0]               ARID;
    input      [AXI_AWIDTH-1:0]    ARADDR;
    input      [3:0]               ARLEN;
    input      [2:0]               ARSIZE;
    input      [1:0]               ARBURST;
    input      [1:0]               ARLOCK;
    input      [3:0]               ARCACHE;
    input      [2:0]               ARPROT;
    input                          ARVALID;
    output                      ARREADY;
    // AXI SLAVE read response channel signals
    output reg [BASE_ID_WIDTH +  ID_WIDTH - 1:0]               RID;
    output reg [AXI_DWIDTH-1:0]    RDATA;
    output reg [1:0]               RRESP;
    output reg                     RLAST;
    output reg                     RVALID;
    input                          RREADY;
    integer                        i;

    wire WREADY;
    wire AWREADY;
    wire ARREADY;



    always @ (negedge ARESETN or posedge ACLK) begin
        if (!ARESETN) begin
            RID= 4'b0000;
            RDATA = {AXI_DWIDTH{1'b0}};
            RRESP = 2'b00;
            RLAST = 1'b0;
            RVALID = 1'b0;
        end else begin
        end
    end

// read data Channel task
    task reset_axi_rddatachan;
        begin
            @(posedge ACLK);
            RID    = 4'b0000;
            RDATA  = 64'h0000000000000000;
            RRESP  = 2'b00;
            RLAST  = 1'b0;
            RVALID = 1'b0;
        end
    endtask // reset_axi_rddatachan 

// read data Channel task
    task axi_respond_to_read;
        begin
            @(posedge ACLK);
            RID    = 4'b0000;
            RDATA  = 64'h0101010101010101;
            RRESP  = 2'b00;
            RLAST  = 1'b1;
            RVALID = 1'b1;
	    $display("READ DATA = %x", $time,RDATA);
            wait (RREADY);
            @(posedge ACLK);
            reset_axi_rddatachan;
        end
    endtask // axi_respond_to_read 

    always @ (negedge ARESETN or posedge ACLK) begin
        if (!ARESETN) begin
        end else begin
            if (ARVALID == 1'b1 && ARREADY == 1'b1) begin
                RID    = 4'b0000;
                RDATA  = 64'haaaa5555aaaa5555;
                //RDATA  = $random;
                RRESP  = 2'b00;
                RLAST  = 1'b1;
                RVALID = 1'b1;
                $display("%t READ DATA = %h", $time,RDATA);
            end else if (RVALID == 1'b1 && RREADY == 1'b1) begin
                RID    = 4'b0000;
                RDATA  = 64'h0000000000000000;
                RRESP  = 2'b00;
                RLAST  = 1'b0;
                RVALID = 1'b0;
            end
        end
    end

   assign AWREADY = 1'b1;
   assign WREADY  = 1'b1;
   assign ARREADY = 1'b1;


   //always @ (*) begin
   //    if (!ARESETN) begin
   //        ARREADY = 1'b1;
   //    end else begin
   //        if (ARVALID == 1'b1 && ARREADY == 1'b0) begin
   //            ARREADY <= 1'b1;
   //        end else begin
   //        end
   //    end
   //end

   //always @ (negedge ARESETN or posedge ACLK) begin
   //    if (!ARESETN) begin
   //        ARREADY = 1'b1;
   //    end else begin
   //        if (ARVALID == 1'b1 && ARREADY == 1'b0) begin
   //            ARREADY <= 1'b1;
   //        end else begin
   //            ARREADY <= 1'b0;
   //        end
   //    end
   //end

   //always @ (negedge ARESETN or posedge ACLK) begin
   //    if (!ARESETN) begin
   //        AWREADY = 1'b1;
   //    end else begin
   //        if (AWVALID == 1'b1 && AWREADY == 1'b0) begin
   //            AWREADY <= 1'b1;
   //        end else begin
   //            AWREADY <= 1'b0;
   //        end
   //    end
   //end

   //always @ (negedge ARESETN or posedge ACLK) begin
   //    if (!ARESETN) begin
   //        WREADY = 1'b1;
   //    end else begin
   //        if (WVALID == 1'b1 && WREADY == 1'b0) begin
   //            WREADY <= 1'b1;
   //        end else begin
   //            WREADY <= 1'b0;
   //        end
   //    end
   //end

    always @ (negedge ARESETN or posedge ACLK) begin
        if (!ARESETN) begin
            BID = 4'b0000;
            BRESP = 2'b00;
            BVALID = 1'b0;
        end else begin
            if (BREADY) begin
                BID = 4'b0000;
                BRESP = 2'b00;
                BVALID = 1'b0;
            end else if (WLAST == 1'b1 && WVALID == 1'b1 && WREADY == 1'b1) begin
                BID = 4'b0000;
                BRESP = 2'b00;
                BVALID = 1'b1;
            end
        end
    end

endmodule
