// ----------------------------------------------------------------------
// Copyright (c) 2015, The Regents of the University of California All
// rights reserved.
// 
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// 
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
// 
//     * Redistributions in binary form must reproduce the above
//       copyright notice, this list of conditions and the following
//       disclaimer in the documentation and/or other materials provided
//       with the distribution.
// 
//     * Neither the name of The Regents of the University of California
//       nor the names of its contributors may be used to endorse or
//       promote products derived from this software without specific
//       prior written permission.
// 
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL REGENTS OF THE
// UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
// TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
// DAMAGE.
// ----------------------------------------------------------------------
`include "riffa.vh"
module channel
    #(
      parameter C_DATA_WIDTH = 128,
      parameter C_MAX_READ_REQ = 2, // Max read: 000=128B, 001=256B, 010=512B, 011=1024B, 100=2048B, 101=4096B
      parameter C_DATA_WORD_WIDTH = clog2((C_DATA_WIDTH/32)+1)
      )
    (
     input                         CLK,
     input                         RST,
     input [2:0]                   CONFIG_MAX_READ_REQUEST_SIZE, // Maximum read payload: 000=128B, 001=256B, 010=512B, 011=1024B, 100=2048B, 101=4096B
     input [2:0]                   CONFIG_MAX_PAYLOAD_SIZE, // Maximum write payload: 000=128B, 001=256B, 010=512B, 011=1024B

     input [31:0]                  PIO_DATA, // Single word programmed I/O data
     input [C_DATA_WIDTH-1:0]      ENG_DATA, // Main incoming data 

     output                        SG_RX_BUF_RECVD, // Scatter gather RX buffer completely read (ready for next if applicable)
     input                         SG_RX_BUF_LEN_VALID, // Scatter gather RX buffer length valid
     input                         SG_RX_BUF_ADDR_HI_VALID, // Scatter gather RX buffer high address valid
     input                         SG_RX_BUF_ADDR_LO_VALID, // Scatter gather RX buffer low address valid

     output                        SG_TX_BUF_RECVD, // Scatter gather TX buffer completely read (ready for next if applicable)
     input                         SG_TX_BUF_LEN_VALID, // Scatter gather TX buffer length valid
     input                         SG_TX_BUF_ADDR_HI_VALID, // Scatter gather TX buffer high address valid
     input                         SG_TX_BUF_ADDR_LO_VALID, // Scatter gather TX buffer low address valid

     input                         TXN_RX_LEN_VALID, // Read transaction length valid
     input                         TXN_RX_OFF_LAST_VALID, // Read transaction offset/last valid
     output [31:0]                 TXN_RX_DONE_LEN, // Read transaction actual transfer length
     output                        TXN_RX_DONE, // Read transaction done
     input                         TXN_RX_DONE_ACK, // Read transaction actual transfer length read

     output                        TXN_TX, // Write transaction notification
     input                         TXN_TX_ACK, // Write transaction acknowledged
     output [31:0]                 TXN_TX_LEN, // Write transaction length
     output [31:0]                 TXN_TX_OFF_LAST, // Write transaction offset/last
     output [31:0]                 TXN_TX_DONE_LEN, // Write transaction actual transfer length
     output                        TXN_TX_DONE, // Write transaction done
     input                         TXN_TX_DONE_ACK, // Write transaction actual transfer length read

     output                        RX_REQ, // Read request
     input                         RX_REQ_ACK, // Read request accepted
     output [1:0]                  RX_REQ_TAG, // Read request data tag 
     output [63:0]                 RX_REQ_ADDR, // Read request address
     output [9:0]                  RX_REQ_LEN, // Read request length

     output                        TX_REQ, // Outgoing write request
     input                         TX_REQ_ACK, // Outgoing write request acknowledged
     output [63:0]                 TX_ADDR, // Outgoing write high address
     output [9:0]                  TX_LEN, // Outgoing write length (in 32 bit words)
     output [C_DATA_WIDTH-1:0]     TX_DATA, // Outgoing write data
     input                         TX_DATA_REN, // Outgoing write data read enable
     input                         TX_SENT, // Outgoing write complete

     input [C_DATA_WORD_WIDTH-1:0] MAIN_DATA_EN, // Main incoming data enable
     input                         MAIN_DONE, // Main incoming data complete
     input                         MAIN_ERR, // Main incoming data completed with error

     input [C_DATA_WORD_WIDTH-1:0] SG_RX_DATA_EN, // Scatter gather for RX incoming data enable
     input                         SG_RX_DONE, // Scatter gather for RX incoming data complete
     input                         SG_RX_ERR, // Scatter gather for RX incoming data completed with error

     input [C_DATA_WORD_WIDTH-1:0] SG_TX_DATA_EN, // Scatter gather for TX incoming data enable
     input                         SG_TX_DONE, // Scatter gather for TX incoming data complete
     input                         SG_TX_ERR, // Scatter gather for TX incoming data completed with error

     input                         CHNL_RX_CLK, // Channel read clock
     output                        CHNL_RX, // Channel read receive signal
     input                         CHNL_RX_ACK, // Channle read received signal
     output                        CHNL_RX_LAST, // Channel last read
     output [31:0]                 CHNL_RX_LEN, // Channel read length
     output [30:0]                 CHNL_RX_OFF, // Channel read offset
     output [C_DATA_WIDTH-1:0]     CHNL_RX_DATA, // Channel read data
     output                        CHNL_RX_DATA_VALID, // Channel read data valid
     input                         CHNL_RX_DATA_REN, // Channel read data has been recieved

     input                         CHNL_TX_CLK, // Channel write clock
     input                         CHNL_TX, // Channel write receive signal
     output                        CHNL_TX_ACK, // Channel write acknowledgement signal
     input                         CHNL_TX_LAST, // Channel last write
     input [31:0]                  CHNL_TX_LEN, // Channel write length (in 32 bit words)
     input [30:0]                  CHNL_TX_OFF, // Channel write offset
     input [C_DATA_WIDTH-1:0]      CHNL_TX_DATA, // Channel write data
     input                         CHNL_TX_DATA_VALID, // Channel write data valid
     output                        CHNL_TX_DATA_REN                         // Channel write data has been recieved
     );
    generate
        if(C_DATA_WIDTH == 32) begin
            channel_32 
                #(
                  .C_DATA_WIDTH(C_DATA_WIDTH), 
                  .C_MAX_READ_REQ(C_MAX_READ_REQ)
                  )
            channel 
                (/*AUTOINST*/
                 // Outputs
                 .SG_RX_BUF_RECVD           (SG_RX_BUF_RECVD),
                 .SG_TX_BUF_RECVD           (SG_TX_BUF_RECVD),
                 .TXN_RX_DONE_LEN           (TXN_RX_DONE_LEN[31:0]),
                 .TXN_RX_DONE               (TXN_RX_DONE),
                 .TXN_TX                    (TXN_TX),
                 .TXN_TX_LEN                (TXN_TX_LEN[31:0]),
                 .TXN_TX_OFF_LAST           (TXN_TX_OFF_LAST[31:0]),
                 .TXN_TX_DONE_LEN           (TXN_TX_DONE_LEN[31:0]),
                 .TXN_TX_DONE               (TXN_TX_DONE),
                 .RX_REQ                    (RX_REQ),
                 .RX_REQ_TAG                (RX_REQ_TAG[1:0]),
                 .RX_REQ_ADDR               (RX_REQ_ADDR[63:0]),
                 .RX_REQ_LEN                (RX_REQ_LEN[9:0]),
                 .TX_REQ                    (TX_REQ),
                 .TX_ADDR                   (TX_ADDR[63:0]),
                 .TX_LEN                    (TX_LEN[9:0]),
                 .TX_DATA                   (TX_DATA[C_DATA_WIDTH-1:0]),
                 .CHNL_RX                   (CHNL_RX),
                 .CHNL_RX_LAST              (CHNL_RX_LAST),
                 .CHNL_RX_LEN               (CHNL_RX_LEN[31:0]),
                 .CHNL_RX_OFF               (CHNL_RX_OFF[30:0]),
                 .CHNL_RX_DATA              (CHNL_RX_DATA[C_DATA_WIDTH-1:0]),
                 .CHNL_RX_DATA_VALID        (CHNL_RX_DATA_VALID),
                 .CHNL_TX_ACK               (CHNL_TX_ACK),
                 .CHNL_TX_DATA_REN          (CHNL_TX_DATA_REN),
                 // Inputs
                 .CLK                       (CLK),
                 .RST                       (RST),
                 .CONFIG_MAX_READ_REQUEST_SIZE(CONFIG_MAX_READ_REQUEST_SIZE[2:0]),
                 .CONFIG_MAX_PAYLOAD_SIZE   (CONFIG_MAX_PAYLOAD_SIZE[2:0]),
                 .PIO_DATA                  (PIO_DATA[31:0]),
                 .ENG_DATA                  (ENG_DATA[C_DATA_WIDTH-1:0]),
                 .SG_RX_BUF_LEN_VALID       (SG_RX_BUF_LEN_VALID),
                 .SG_RX_BUF_ADDR_HI_VALID   (SG_RX_BUF_ADDR_HI_VALID),
                 .SG_RX_BUF_ADDR_LO_VALID   (SG_RX_BUF_ADDR_LO_VALID),
                 .SG_TX_BUF_LEN_VALID       (SG_TX_BUF_LEN_VALID),
                 .SG_TX_BUF_ADDR_HI_VALID   (SG_TX_BUF_ADDR_HI_VALID),
                 .SG_TX_BUF_ADDR_LO_VALID   (SG_TX_BUF_ADDR_LO_VALID),
                 .TXN_RX_LEN_VALID          (TXN_RX_LEN_VALID),
                 .TXN_RX_OFF_LAST_VALID     (TXN_RX_OFF_LAST_VALID),
                 .TXN_RX_DONE_ACK           (TXN_RX_DONE_ACK),
                 .TXN_TX_ACK                (TXN_TX_ACK),
                 .TXN_TX_DONE_ACK           (TXN_TX_DONE_ACK),
                 .RX_REQ_ACK                (RX_REQ_ACK),
                 .TX_REQ_ACK                (TX_REQ_ACK),
                 .TX_DATA_REN               (TX_DATA_REN),
                 .TX_SENT                   (TX_SENT),
                 .MAIN_DATA_EN              (MAIN_DATA_EN[C_DATA_WORD_WIDTH-1:0]),
                 .MAIN_DONE                 (MAIN_DONE),
                 .MAIN_ERR                  (MAIN_ERR),
                 .SG_RX_DATA_EN             (SG_RX_DATA_EN[C_DATA_WORD_WIDTH-1:0]),
                 .SG_RX_DONE                (SG_RX_DONE),
                 .SG_RX_ERR                 (SG_RX_ERR),
                 .SG_TX_DATA_EN             (SG_TX_DATA_EN[C_DATA_WORD_WIDTH-1:0]),
                 .SG_TX_DONE                (SG_TX_DONE),
                 .SG_TX_ERR                 (SG_TX_ERR),
                 .CHNL_RX_CLK               (CHNL_RX_CLK),
                 .CHNL_RX_ACK               (CHNL_RX_ACK),
                 .CHNL_RX_DATA_REN          (CHNL_RX_DATA_REN),
                 .CHNL_TX_CLK               (CHNL_TX_CLK),
                 .CHNL_TX                   (CHNL_TX),
                 .CHNL_TX_LAST              (CHNL_TX_LAST),
                 .CHNL_TX_LEN               (CHNL_TX_LEN[31:0]),
                 .CHNL_TX_OFF               (CHNL_TX_OFF[30:0]),
                 .CHNL_TX_DATA              (CHNL_TX_DATA[C_DATA_WIDTH-1:0]),
                 .CHNL_TX_DATA_VALID        (CHNL_TX_DATA_VALID));
        end else if(C_DATA_WIDTH == 64) begin
            channel_64 
                #(
                  .C_DATA_WIDTH(C_DATA_WIDTH), 
                  .C_MAX_READ_REQ(C_MAX_READ_REQ)
                  )
            channel 
                (/*AUTOINST*/
                 // Outputs
                 .SG_RX_BUF_RECVD           (SG_RX_BUF_RECVD),
                 .SG_TX_BUF_RECVD           (SG_TX_BUF_RECVD),
                 .TXN_RX_DONE_LEN           (TXN_RX_DONE_LEN[31:0]),
                 .TXN_RX_DONE               (TXN_RX_DONE),
                 .TXN_TX                    (TXN_TX),
                 .TXN_TX_LEN                (TXN_TX_LEN[31:0]),
                 .TXN_TX_OFF_LAST           (TXN_TX_OFF_LAST[31:0]),
                 .TXN_TX_DONE_LEN           (TXN_TX_DONE_LEN[31:0]),
                 .TXN_TX_DONE               (TXN_TX_DONE),
                 .RX_REQ                    (RX_REQ),
                 .RX_REQ_TAG                (RX_REQ_TAG[1:0]),
                 .RX_REQ_ADDR               (RX_REQ_ADDR[63:0]),
                 .RX_REQ_LEN                (RX_REQ_LEN[9:0]),
                 .TX_REQ                    (TX_REQ),
                 .TX_ADDR                   (TX_ADDR[63:0]),
                 .TX_LEN                    (TX_LEN[9:0]),
                 .TX_DATA                   (TX_DATA[C_DATA_WIDTH-1:0]),
                 .CHNL_RX                   (CHNL_RX),
                 .CHNL_RX_LAST              (CHNL_RX_LAST),
                 .CHNL_RX_LEN               (CHNL_RX_LEN[31:0]),
                 .CHNL_RX_OFF               (CHNL_RX_OFF[30:0]),
                 .CHNL_RX_DATA              (CHNL_RX_DATA[C_DATA_WIDTH-1:0]),
                 .CHNL_RX_DATA_VALID        (CHNL_RX_DATA_VALID),
                 .CHNL_TX_ACK               (CHNL_TX_ACK),
                 .CHNL_TX_DATA_REN          (CHNL_TX_DATA_REN),
                 // Inputs
                 .CLK                       (CLK),
                 .RST                       (RST),
                 .CONFIG_MAX_READ_REQUEST_SIZE(CONFIG_MAX_READ_REQUEST_SIZE[2:0]),
                 .CONFIG_MAX_PAYLOAD_SIZE   (CONFIG_MAX_PAYLOAD_SIZE[2:0]),
                 .PIO_DATA                  (PIO_DATA[31:0]),
                 .ENG_DATA                  (ENG_DATA[C_DATA_WIDTH-1:0]),
                 .SG_RX_BUF_LEN_VALID       (SG_RX_BUF_LEN_VALID),
                 .SG_RX_BUF_ADDR_HI_VALID   (SG_RX_BUF_ADDR_HI_VALID),
                 .SG_RX_BUF_ADDR_LO_VALID   (SG_RX_BUF_ADDR_LO_VALID),
                 .SG_TX_BUF_LEN_VALID       (SG_TX_BUF_LEN_VALID),
                 .SG_TX_BUF_ADDR_HI_VALID   (SG_TX_BUF_ADDR_HI_VALID),
                 .SG_TX_BUF_ADDR_LO_VALID   (SG_TX_BUF_ADDR_LO_VALID),
                 .TXN_RX_LEN_VALID          (TXN_RX_LEN_VALID),
                 .TXN_RX_OFF_LAST_VALID     (TXN_RX_OFF_LAST_VALID),
                 .TXN_RX_DONE_ACK           (TXN_RX_DONE_ACK),
                 .TXN_TX_ACK                (TXN_TX_ACK),
                 .TXN_TX_DONE_ACK           (TXN_TX_DONE_ACK),
                 .RX_REQ_ACK                (RX_REQ_ACK),
                 .TX_REQ_ACK                (TX_REQ_ACK),
                 .TX_DATA_REN               (TX_DATA_REN),
                 .TX_SENT                   (TX_SENT),
                 .MAIN_DATA_EN              (MAIN_DATA_EN[C_DATA_WORD_WIDTH-1:0]),
                 .MAIN_DONE                 (MAIN_DONE),
                 .MAIN_ERR                  (MAIN_ERR),
                 .SG_RX_DATA_EN             (SG_RX_DATA_EN[C_DATA_WORD_WIDTH-1:0]),
                 .SG_RX_DONE                (SG_RX_DONE),
                 .SG_RX_ERR                 (SG_RX_ERR),
                 .SG_TX_DATA_EN             (SG_TX_DATA_EN[C_DATA_WORD_WIDTH-1:0]),
                 .SG_TX_DONE                (SG_TX_DONE),
                 .SG_TX_ERR                 (SG_TX_ERR),
                 .CHNL_RX_CLK               (CHNL_RX_CLK),
                 .CHNL_RX_ACK               (CHNL_RX_ACK),
                 .CHNL_RX_DATA_REN          (CHNL_RX_DATA_REN),
                 .CHNL_TX_CLK               (CHNL_TX_CLK),
                 .CHNL_TX                   (CHNL_TX),
                 .CHNL_TX_LAST              (CHNL_TX_LAST),
                 .CHNL_TX_LEN               (CHNL_TX_LEN[31:0]),
                 .CHNL_TX_OFF               (CHNL_TX_OFF[30:0]),
                 .CHNL_TX_DATA              (CHNL_TX_DATA[C_DATA_WIDTH-1:0]),
                 .CHNL_TX_DATA_VALID        (CHNL_TX_DATA_VALID));
        end else if(C_DATA_WIDTH == 128) begin
            channel_128
                #(
                  .C_DATA_WIDTH(C_DATA_WIDTH), 
                  .C_MAX_READ_REQ(C_MAX_READ_REQ)
                  )
            channel 
                (/*AUTOINST*/
                 // Outputs
                 .SG_RX_BUF_RECVD           (SG_RX_BUF_RECVD),
                 .SG_TX_BUF_RECVD           (SG_TX_BUF_RECVD),
                 .TXN_RX_DONE_LEN           (TXN_RX_DONE_LEN[31:0]),
                 .TXN_RX_DONE               (TXN_RX_DONE),
                 .TXN_TX                    (TXN_TX),
                 .TXN_TX_LEN                (TXN_TX_LEN[31:0]),
                 .TXN_TX_OFF_LAST           (TXN_TX_OFF_LAST[31:0]),
                 .TXN_TX_DONE_LEN           (TXN_TX_DONE_LEN[31:0]),
                 .TXN_TX_DONE               (TXN_TX_DONE),
                 .RX_REQ                    (RX_REQ),
                 .RX_REQ_TAG                (RX_REQ_TAG[1:0]),
                 .RX_REQ_ADDR               (RX_REQ_ADDR[63:0]),
                 .RX_REQ_LEN                (RX_REQ_LEN[9:0]),
                 .TX_REQ                    (TX_REQ),
                 .TX_ADDR                   (TX_ADDR[63:0]),
                 .TX_LEN                    (TX_LEN[9:0]),
                 .TX_DATA                   (TX_DATA[C_DATA_WIDTH-1:0]),
                 .CHNL_RX                   (CHNL_RX),
                 .CHNL_RX_LAST              (CHNL_RX_LAST),
                 .CHNL_RX_LEN               (CHNL_RX_LEN[31:0]),
                 .CHNL_RX_OFF               (CHNL_RX_OFF[30:0]),
                 .CHNL_RX_DATA              (CHNL_RX_DATA[C_DATA_WIDTH-1:0]),
                 .CHNL_RX_DATA_VALID        (CHNL_RX_DATA_VALID),
                 .CHNL_TX_ACK               (CHNL_TX_ACK),
                 .CHNL_TX_DATA_REN          (CHNL_TX_DATA_REN),
                 // Inputs
                 .CLK                       (CLK),
                 .RST                       (RST),
                 .CONFIG_MAX_READ_REQUEST_SIZE(CONFIG_MAX_READ_REQUEST_SIZE[2:0]),
                 .CONFIG_MAX_PAYLOAD_SIZE   (CONFIG_MAX_PAYLOAD_SIZE[2:0]),
                 .PIO_DATA                  (PIO_DATA[31:0]),
                 .ENG_DATA                  (ENG_DATA[C_DATA_WIDTH-1:0]),
                 .SG_RX_BUF_LEN_VALID       (SG_RX_BUF_LEN_VALID),
                 .SG_RX_BUF_ADDR_HI_VALID   (SG_RX_BUF_ADDR_HI_VALID),
                 .SG_RX_BUF_ADDR_LO_VALID   (SG_RX_BUF_ADDR_LO_VALID),
                 .SG_TX_BUF_LEN_VALID       (SG_TX_BUF_LEN_VALID),
                 .SG_TX_BUF_ADDR_HI_VALID   (SG_TX_BUF_ADDR_HI_VALID),
                 .SG_TX_BUF_ADDR_LO_VALID   (SG_TX_BUF_ADDR_LO_VALID),
                 .TXN_RX_LEN_VALID          (TXN_RX_LEN_VALID),
                 .TXN_RX_OFF_LAST_VALID     (TXN_RX_OFF_LAST_VALID),
                 .TXN_RX_DONE_ACK           (TXN_RX_DONE_ACK),
                 .TXN_TX_ACK                (TXN_TX_ACK),
                 .TXN_TX_DONE_ACK           (TXN_TX_DONE_ACK),
                 .RX_REQ_ACK                (RX_REQ_ACK),
                 .TX_REQ_ACK                (TX_REQ_ACK),
                 .TX_DATA_REN               (TX_DATA_REN),
                 .TX_SENT                   (TX_SENT),
                 .MAIN_DATA_EN              (MAIN_DATA_EN[C_DATA_WORD_WIDTH-1:0]),
                 .MAIN_DONE                 (MAIN_DONE),
                 .MAIN_ERR                  (MAIN_ERR),
                 .SG_RX_DATA_EN             (SG_RX_DATA_EN[C_DATA_WORD_WIDTH-1:0]),
                 .SG_RX_DONE                (SG_RX_DONE),
                 .SG_RX_ERR                 (SG_RX_ERR),
                 .SG_TX_DATA_EN             (SG_TX_DATA_EN[C_DATA_WORD_WIDTH-1:0]),
                 .SG_TX_DONE                (SG_TX_DONE),
                 .SG_TX_ERR                 (SG_TX_ERR),
                 .CHNL_RX_CLK               (CHNL_RX_CLK),
                 .CHNL_RX_ACK               (CHNL_RX_ACK),
                 .CHNL_RX_DATA_REN          (CHNL_RX_DATA_REN),
                 .CHNL_TX_CLK               (CHNL_TX_CLK),
                 .CHNL_TX                   (CHNL_TX),
                 .CHNL_TX_LAST              (CHNL_TX_LAST),
                 .CHNL_TX_LEN               (CHNL_TX_LEN[31:0]),
                 .CHNL_TX_OFF               (CHNL_TX_OFF[30:0]),
                 .CHNL_TX_DATA              (CHNL_TX_DATA[C_DATA_WIDTH-1:0]),
                 .CHNL_TX_DATA_VALID        (CHNL_TX_DATA_VALID));
        end 
    endgenerate
endmodule
// Local Variables:
// verilog-library-directories:("." "import")
// End:
