//==============================================================================
// Copyright (C) 2023, Advanced Micro Devices, Inc. All rights reserved.
// SPDX-License-Identifier: MIT
//
//==============================================================================
`timescale 1ns/1ps

module axi_5to2_interconnect_to_sys_mem #(
  parameter C_AXI_DATA_WIDTH = 512,
  parameter C_AXI_ADDR_WIDTH = 64
) (
  input             s_axi_rdma_get_wqe_awid,
  input    [63 : 0] s_axi_rdma_get_wqe_awaddr,
  input     [3 : 0] s_axi_rdma_get_wqe_awqos,
  input     [7 : 0] s_axi_rdma_get_wqe_awlen,
  input     [2 : 0] s_axi_rdma_get_wqe_awsize,
  input     [1 : 0] s_axi_rdma_get_wqe_awburst,
  input     [3 : 0] s_axi_rdma_get_wqe_awcache,
  input     [2 : 0] s_axi_rdma_get_wqe_awprot,
  input             s_axi_rdma_get_wqe_awvalid,
  output            s_axi_rdma_get_wqe_awready,
  input   [511 : 0] s_axi_rdma_get_wqe_wdata,
  input    [63 : 0] s_axi_rdma_get_wqe_wstrb,
  input             s_axi_rdma_get_wqe_wlast,
  input             s_axi_rdma_get_wqe_wvalid,
  output            s_axi_rdma_get_wqe_wready,
  input             s_axi_rdma_get_wqe_awlock,
  output            s_axi_rdma_get_wqe_bid,
  output    [1 : 0] s_axi_rdma_get_wqe_bresp,
  output            s_axi_rdma_get_wqe_bvalid,
  input             s_axi_rdma_get_wqe_bready,
  input             s_axi_rdma_get_wqe_arid,
  input    [63 : 0] s_axi_rdma_get_wqe_araddr,
  input     [7 : 0] s_axi_rdma_get_wqe_arlen,
  input     [2 : 0] s_axi_rdma_get_wqe_arsize,
  input     [1 : 0] s_axi_rdma_get_wqe_arburst,
  input     [3 : 0] s_axi_rdma_get_wqe_arcache,
  input     [2 : 0] s_axi_rdma_get_wqe_arprot,
  input             s_axi_rdma_get_wqe_arvalid,
  output            s_axi_rdma_get_wqe_arready,
  output            s_axi_rdma_get_wqe_rid,
  output  [511 : 0] s_axi_rdma_get_wqe_rdata,
  output    [1 : 0] s_axi_rdma_get_wqe_rresp,
  output            s_axi_rdma_get_wqe_rlast,
  output            s_axi_rdma_get_wqe_rvalid,
  input             s_axi_rdma_get_wqe_rready,
  input             s_axi_rdma_get_wqe_arlock,
  input     [3 : 0] s_axi_rdma_get_wqe_arqos,

  input     [1 : 0] s_axi_rdma_get_payload_awid,
  input    [63 : 0] s_axi_rdma_get_payload_awaddr,
  input     [3 : 0] s_axi_rdma_get_payload_awqos,
  input     [7 : 0] s_axi_rdma_get_payload_awlen,
  input     [2 : 0] s_axi_rdma_get_payload_awsize,
  input     [1 : 0] s_axi_rdma_get_payload_awburst,
  input     [3 : 0] s_axi_rdma_get_payload_awcache,
  input     [2 : 0] s_axi_rdma_get_payload_awprot,
  input             s_axi_rdma_get_payload_awvalid,
  output            s_axi_rdma_get_payload_awready,
  input   [511 : 0] s_axi_rdma_get_payload_wdata,
  input    [63 : 0] s_axi_rdma_get_payload_wstrb,
  input             s_axi_rdma_get_payload_wlast,
  input             s_axi_rdma_get_payload_wvalid,
  output            s_axi_rdma_get_payload_wready,
  input             s_axi_rdma_get_payload_awlock,
  output    [1 : 0] s_axi_rdma_get_payload_bid,
  output    [1 : 0] s_axi_rdma_get_payload_bresp,
  output            s_axi_rdma_get_payload_bvalid,
  input             s_axi_rdma_get_payload_bready,
  input     [1 : 0] s_axi_rdma_get_payload_arid,
  input    [63 : 0] s_axi_rdma_get_payload_araddr,
  input     [7 : 0] s_axi_rdma_get_payload_arlen,
  input     [2 : 0] s_axi_rdma_get_payload_arsize,
  input     [1 : 0] s_axi_rdma_get_payload_arburst,
  input     [3 : 0] s_axi_rdma_get_payload_arcache,
  input     [2 : 0] s_axi_rdma_get_payload_arprot,
  input             s_axi_rdma_get_payload_arvalid,
  output            s_axi_rdma_get_payload_arready,
  output    [1 : 0] s_axi_rdma_get_payload_rid,
  output  [511 : 0] s_axi_rdma_get_payload_rdata,
  output    [1 : 0] s_axi_rdma_get_payload_rresp,
  output            s_axi_rdma_get_payload_rlast,
  output            s_axi_rdma_get_payload_rvalid,
  input             s_axi_rdma_get_payload_rready,
  input             s_axi_rdma_get_payload_arlock,
  input     [3 : 0] s_axi_rdma_get_payload_arqos,

  input             s_axi_rdma_completion_awid,
  input    [63 : 0] s_axi_rdma_completion_awaddr,
  input     [3 : 0] s_axi_rdma_completion_awqos,
  input     [7 : 0] s_axi_rdma_completion_awlen,
  input     [2 : 0] s_axi_rdma_completion_awsize,
  input     [1 : 0] s_axi_rdma_completion_awburst,
  input     [3 : 0] s_axi_rdma_completion_awcache,
  input     [2 : 0] s_axi_rdma_completion_awprot,
  input             s_axi_rdma_completion_awvalid,
  output            s_axi_rdma_completion_awready,
  input   [511 : 0] s_axi_rdma_completion_wdata,
  input    [63 : 0] s_axi_rdma_completion_wstrb,
  input             s_axi_rdma_completion_wlast,
  input             s_axi_rdma_completion_wvalid,
  output            s_axi_rdma_completion_wready,
  input             s_axi_rdma_completion_awlock,
  output            s_axi_rdma_completion_bid,
  output    [1 : 0] s_axi_rdma_completion_bresp,
  output            s_axi_rdma_completion_bvalid,
  input             s_axi_rdma_completion_bready,
  input             s_axi_rdma_completion_arid,
  input    [63 : 0] s_axi_rdma_completion_araddr,
  input     [7 : 0] s_axi_rdma_completion_arlen,
  input     [2 : 0] s_axi_rdma_completion_arsize,
  input     [1 : 0] s_axi_rdma_completion_arburst,
  input     [3 : 0] s_axi_rdma_completion_arcache,
  input     [2 : 0] s_axi_rdma_completion_arprot,
  input             s_axi_rdma_completion_arvalid,
  output            s_axi_rdma_completion_arready,
  output            s_axi_rdma_completion_rid,
  output  [511 : 0] s_axi_rdma_completion_rdata,
  output    [1 : 0] s_axi_rdma_completion_rresp,
  output            s_axi_rdma_completion_rlast,
  output            s_axi_rdma_completion_rvalid,
  input             s_axi_rdma_completion_rready,
  input             s_axi_rdma_completion_arlock,
  input     [3 : 0] s_axi_rdma_completion_arqos,

  input             s_axi_rdma_send_write_payload_awid,
  input    [63 : 0] s_axi_rdma_send_write_payload_awaddr,
  input     [3 : 0] s_axi_rdma_send_write_payload_awqos,
  input     [7 : 0] s_axi_rdma_send_write_payload_awlen,
  input     [2 : 0] s_axi_rdma_send_write_payload_awsize,
  input     [1 : 0] s_axi_rdma_send_write_payload_awburst,
  input     [3 : 0] s_axi_rdma_send_write_payload_awcache,
  input     [2 : 0] s_axi_rdma_send_write_payload_awprot,
  input             s_axi_rdma_send_write_payload_awvalid,
  output            s_axi_rdma_send_write_payload_awready,
  input   [511 : 0] s_axi_rdma_send_write_payload_wdata,
  input    [63 : 0] s_axi_rdma_send_write_payload_wstrb,
  input             s_axi_rdma_send_write_payload_wlast,
  input             s_axi_rdma_send_write_payload_wvalid,
  output            s_axi_rdma_send_write_payload_wready,
  input             s_axi_rdma_send_write_payload_awlock,
  output            s_axi_rdma_send_write_payload_bid,
  output    [1 : 0] s_axi_rdma_send_write_payload_bresp,
  output            s_axi_rdma_send_write_payload_bvalid,
  input             s_axi_rdma_send_write_payload_bready,
  input             s_axi_rdma_send_write_payload_arid,
  input    [63 : 0] s_axi_rdma_send_write_payload_araddr,
  input     [7 : 0] s_axi_rdma_send_write_payload_arlen,
  input     [2 : 0] s_axi_rdma_send_write_payload_arsize,
  input     [1 : 0] s_axi_rdma_send_write_payload_arburst,
  input     [3 : 0] s_axi_rdma_send_write_payload_arcache,
  input     [2 : 0] s_axi_rdma_send_write_payload_arprot,
  input             s_axi_rdma_send_write_payload_arvalid,
  output            s_axi_rdma_send_write_payload_arready,
  output            s_axi_rdma_send_write_payload_rid,
  output  [511 : 0] s_axi_rdma_send_write_payload_rdata,
  output    [1 : 0] s_axi_rdma_send_write_payload_rresp,
  output            s_axi_rdma_send_write_payload_rlast,
  output            s_axi_rdma_send_write_payload_rvalid,
  input             s_axi_rdma_send_write_payload_rready,
  input             s_axi_rdma_send_write_payload_arlock,
  input     [3 : 0] s_axi_rdma_send_write_payload_arqos,

  input             s_axi_rdma_rsp_payload_awid,
  input    [63 : 0] s_axi_rdma_rsp_payload_awaddr,
  input     [3 : 0] s_axi_rdma_rsp_payload_awqos,
  input     [7 : 0] s_axi_rdma_rsp_payload_awlen,
  input     [2 : 0] s_axi_rdma_rsp_payload_awsize,
  input     [1 : 0] s_axi_rdma_rsp_payload_awburst,
  input     [3 : 0] s_axi_rdma_rsp_payload_awcache,
  input     [2 : 0] s_axi_rdma_rsp_payload_awprot,
  input             s_axi_rdma_rsp_payload_awvalid,
  output            s_axi_rdma_rsp_payload_awready,
  input   [511 : 0] s_axi_rdma_rsp_payload_wdata,
  input    [63 : 0] s_axi_rdma_rsp_payload_wstrb,
  input             s_axi_rdma_rsp_payload_wlast,
  input             s_axi_rdma_rsp_payload_wvalid,
  output            s_axi_rdma_rsp_payload_wready,
  input             s_axi_rdma_rsp_payload_awlock,
  output            s_axi_rdma_rsp_payload_bid,
  output    [1 : 0] s_axi_rdma_rsp_payload_bresp,
  output            s_axi_rdma_rsp_payload_bvalid,
  input             s_axi_rdma_rsp_payload_bready,
  input             s_axi_rdma_rsp_payload_arid,
  input    [63 : 0] s_axi_rdma_rsp_payload_araddr,
  input     [7 : 0] s_axi_rdma_rsp_payload_arlen,
  input     [2 : 0] s_axi_rdma_rsp_payload_arsize,
  input     [1 : 0] s_axi_rdma_rsp_payload_arburst,
  input     [3 : 0] s_axi_rdma_rsp_payload_arcache,
  input     [2 : 0] s_axi_rdma_rsp_payload_arprot,
  input             s_axi_rdma_rsp_payload_arvalid,
  output            s_axi_rdma_rsp_payload_arready,
  output            s_axi_rdma_rsp_payload_rid,
  output  [511 : 0] s_axi_rdma_rsp_payload_rdata,
  output    [1 : 0] s_axi_rdma_rsp_payload_rresp,
  output            s_axi_rdma_rsp_payload_rlast,
  output            s_axi_rdma_rsp_payload_rvalid,
  input             s_axi_rdma_rsp_payload_rready,
  input             s_axi_rdma_rsp_payload_arlock,
  input     [3 : 0] s_axi_rdma_rsp_payload_arqos,

  output      [2:0] m_axi_sys_mem_awid,
  output     [63:0] m_axi_sys_mem_awaddr,
  output      [7:0] m_axi_sys_mem_awlen,
  output      [2:0] m_axi_sys_mem_awsize,
  output      [1:0] m_axi_sys_mem_awburst,
  output            m_axi_sys_mem_awlock,
  output      [3:0] m_axi_sys_mem_awqos,
  output      [3:0] m_axi_sys_mem_awregion,
  output      [3:0] m_axi_sys_mem_awcache,
  output      [2:0] m_axi_sys_mem_awprot,
  output            m_axi_sys_mem_awvalid,
  input             m_axi_sys_mem_awready,
  output    [511:0] m_axi_sys_mem_wdata,
  output     [63:0] m_axi_sys_mem_wstrb,
  output            m_axi_sys_mem_wlast,
  output            m_axi_sys_mem_wvalid,
  input             m_axi_sys_mem_wready,
  input       [2:0] m_axi_sys_mem_bid,
  input       [1:0] m_axi_sys_mem_bresp,
  input             m_axi_sys_mem_bvalid,
  output            m_axi_sys_mem_bready,
  output      [2:0] m_axi_sys_mem_arid,
  output     [63:0] m_axi_sys_mem_araddr,
  output      [7:0] m_axi_sys_mem_arlen,
  output      [2:0] m_axi_sys_mem_arsize,
  output      [1:0] m_axi_sys_mem_arburst,
  output            m_axi_sys_mem_arlock,
  output      [3:0] m_axi_sys_mem_arqos,
  output      [3:0] m_axi_sys_mem_arregion,
  output      [3:0] m_axi_sys_mem_arcache,
  output      [2:0] m_axi_sys_mem_arprot,
  output            m_axi_sys_mem_arvalid,
  input             m_axi_sys_mem_arready,
  input       [2:0] m_axi_sys_mem_rid,
  input     [511:0] m_axi_sys_mem_rdata,
  input       [1:0] m_axi_sys_mem_rresp,
  input             m_axi_sys_mem_rlast,
  input             m_axi_sys_mem_rvalid,
  output            m_axi_sys_mem_rready,

  output      [2:0] m_axi_sys_to_dev_crossbar_awid,
  output     [63:0] m_axi_sys_to_dev_crossbar_awaddr,
  output      [7:0] m_axi_sys_to_dev_crossbar_awlen,
  output      [2:0] m_axi_sys_to_dev_crossbar_awsize,
  output      [1:0] m_axi_sys_to_dev_crossbar_awburst,
  output            m_axi_sys_to_dev_crossbar_awlock,
  output      [3:0] m_axi_sys_to_dev_crossbar_awqos,
  output      [3:0] m_axi_sys_to_dev_crossbar_awregion,
  output      [3:0] m_axi_sys_to_dev_crossbar_awcache,
  output      [2:0] m_axi_sys_to_dev_crossbar_awprot,
  output            m_axi_sys_to_dev_crossbar_awvalid,
  input             m_axi_sys_to_dev_crossbar_awready,
  output    [511:0] m_axi_sys_to_dev_crossbar_wdata,
  output     [63:0] m_axi_sys_to_dev_crossbar_wstrb,
  output            m_axi_sys_to_dev_crossbar_wlast,
  output            m_axi_sys_to_dev_crossbar_wvalid,
  input             m_axi_sys_to_dev_crossbar_wready,
  input       [2:0]  m_axi_sys_to_dev_crossbar_bid,
  input       [1:0] m_axi_sys_to_dev_crossbar_bresp,
  input             m_axi_sys_to_dev_crossbar_bvalid,
  output            m_axi_sys_to_dev_crossbar_bready,
  output      [2:0]   m_axi_sys_to_dev_crossbar_arid,
  output     [63:0] m_axi_sys_to_dev_crossbar_araddr,
  output      [7:0] m_axi_sys_to_dev_crossbar_arlen,
  output      [2:0] m_axi_sys_to_dev_crossbar_arsize,
  output      [1:0] m_axi_sys_to_dev_crossbar_arburst,
  output            m_axi_sys_to_dev_crossbar_arlock,
  output      [3:0] m_axi_sys_to_dev_crossbar_arqos,
  output      [3:0] m_axi_sys_to_dev_crossbar_arregion,
  output      [3:0] m_axi_sys_to_dev_crossbar_arcache,
  output      [2:0] m_axi_sys_to_dev_crossbar_arprot,
  output            m_axi_sys_to_dev_crossbar_arvalid,
  input             m_axi_sys_to_dev_crossbar_arready,
  input       [2:0] m_axi_sys_to_dev_crossbar_rid,
  input     [511:0] m_axi_sys_to_dev_crossbar_rdata,
  input       [1:0] m_axi_sys_to_dev_crossbar_rresp,
  input             m_axi_sys_to_dev_crossbar_rlast,
  input             m_axi_sys_to_dev_crossbar_rvalid,
  output            m_axi_sys_to_dev_crossbar_rready,

  input axis_aclk,
  input axis_arestn
);

localparam C_NUM_MASTERS = 5;
localparam C_NUM_SLAVES = 2;

localparam C_RDMA_GET_WQE_IDX     = 0;
localparam C_RDMA_GET_PAYLOAD_IDX = 1;
localparam C_RDMA_COMPLETION_IDX  = 2;
localparam C_RDMA_GET_SEND_WRITE_PAYLOAD_IDX = 3;
localparam C_RDMA_RSP_PAYLOAD_IDX = 4;

localparam C_SYS_MEM_IDX     = 0;
localparam C_SYS_TO_DEV_CROSSBAR_IDX = 1;

logic   [C_NUM_MASTERS*3-1 : 0] s_axi_awid;
logic  [C_NUM_MASTERS*64-1 : 0] s_axi_awaddr;
logic   [C_NUM_MASTERS*8-1 : 0] s_axi_awlen;
logic   [C_NUM_MASTERS*3-1 : 0] s_axi_awsize;
logic   [C_NUM_MASTERS*2-1 : 0] s_axi_awburst;
logic     [C_NUM_MASTERS-1 : 0] s_axi_awlock;
logic   [C_NUM_MASTERS*4-1 : 0] s_axi_awcache;
logic   [C_NUM_MASTERS*3-1 : 0] s_axi_awprot;
logic   [C_NUM_MASTERS*4-1 : 0] s_axi_awqos;
logic     [C_NUM_MASTERS-1 : 0] s_axi_awvalid;
logic     [C_NUM_MASTERS-1 : 0] s_axi_awready;
logic [C_NUM_MASTERS*512-1 : 0] s_axi_wdata;
logic  [C_NUM_MASTERS*64-1 : 0] s_axi_wstrb;
logic     [C_NUM_MASTERS-1 : 0] s_axi_wlast;
logic     [C_NUM_MASTERS-1 : 0] s_axi_wvalid;
logic     [C_NUM_MASTERS-1 : 0] s_axi_wready;
logic   [C_NUM_MASTERS*3-1 : 0] s_axi_bid;
logic   [C_NUM_MASTERS*2-1 : 0] s_axi_bresp;
logic     [C_NUM_MASTERS-1 : 0] s_axi_bvalid;
logic     [C_NUM_MASTERS-1 : 0] s_axi_bready;
logic   [C_NUM_MASTERS*3-1 : 0] s_axi_arid;
logic  [C_NUM_MASTERS*64-1 : 0] s_axi_araddr;
logic   [C_NUM_MASTERS*8-1 : 0] s_axi_arlen;
logic   [C_NUM_MASTERS*3-1 : 0] s_axi_arsize;
logic   [C_NUM_MASTERS*2-1 : 0] s_axi_arburst;
logic     [C_NUM_MASTERS-1 : 0] s_axi_arlock;
logic   [C_NUM_MASTERS*4-1 : 0] s_axi_arcache;
logic   [C_NUM_MASTERS*3-1 : 0] s_axi_arprot;
logic   [C_NUM_MASTERS*4-1 : 0] s_axi_arqos;
logic     [C_NUM_MASTERS-1 : 0] s_axi_arvalid;
logic     [C_NUM_MASTERS-1 : 0] s_axi_arready;
logic   [C_NUM_MASTERS*3-1 : 0] s_axi_rid;
logic [C_NUM_MASTERS*512-1 : 0] s_axi_rdata;
logic   [C_NUM_MASTERS*2-1 : 0] s_axi_rresp;
logic     [C_NUM_MASTERS-1 : 0] s_axi_rlast;
logic     [C_NUM_MASTERS-1 : 0] s_axi_rvalid;
logic     [C_NUM_MASTERS-1 : 0] s_axi_rready;

logic   [C_NUM_SLAVES*3-1 : 0] m_axi_awid;
logic  [C_NUM_SLAVES*64-1 : 0] m_axi_awaddr;
logic   [C_NUM_SLAVES*8-1 : 0] m_axi_awlen;
logic   [C_NUM_SLAVES*3-1 : 0] m_axi_awsize;
logic   [C_NUM_SLAVES*2-1 : 0] m_axi_awburst;
logic     [C_NUM_SLAVES-1 : 0] m_axi_awlock;
logic   [C_NUM_SLAVES*4-1 : 0] m_axi_awcache;
logic   [C_NUM_SLAVES*3-1 : 0] m_axi_awprot;
logic   [C_NUM_SLAVES*4-1 : 0] m_axi_awqos;
logic     [C_NUM_SLAVES-1 : 0] m_axi_awvalid;
logic     [C_NUM_SLAVES-1 : 0] m_axi_awready;
logic [C_NUM_SLAVES*512-1 : 0] m_axi_wdata;
logic  [C_NUM_SLAVES*64-1 : 0] m_axi_wstrb;
logic     [C_NUM_SLAVES-1 : 0] m_axi_wlast;
logic     [C_NUM_SLAVES-1 : 0] m_axi_wvalid;
logic     [C_NUM_SLAVES-1 : 0] m_axi_wready;
logic   [C_NUM_SLAVES*3-1 : 0] m_axi_bid;
logic   [C_NUM_SLAVES*2-1 : 0] m_axi_bresp;
logic     [C_NUM_SLAVES-1 : 0] m_axi_bvalid;
logic     [C_NUM_SLAVES-1 : 0] m_axi_bready;
logic   [C_NUM_SLAVES*3-1 : 0] m_axi_arid;
logic  [C_NUM_SLAVES*64-1 : 0] m_axi_araddr;
logic   [C_NUM_SLAVES*8-1 : 0] m_axi_arlen;
logic   [C_NUM_SLAVES*3-1 : 0] m_axi_arsize;
logic   [C_NUM_SLAVES*2-1 : 0] m_axi_arburst;
logic     [C_NUM_SLAVES-1 : 0] m_axi_arlock;
logic   [C_NUM_SLAVES*4-1 : 0] m_axi_arcache;
logic   [C_NUM_SLAVES*3-1 : 0] m_axi_arprot;
logic   [C_NUM_SLAVES*4-1 : 0] m_axi_arqos;
logic     [C_NUM_SLAVES-1 : 0] m_axi_arvalid;
logic     [C_NUM_SLAVES-1 : 0] m_axi_arready;
logic   [C_NUM_SLAVES*3-1 : 0] m_axi_rid;
logic [C_NUM_SLAVES*512-1 : 0] m_axi_rdata;
logic   [C_NUM_SLAVES*2-1 : 0] m_axi_rresp;
logic     [C_NUM_SLAVES-1 : 0] m_axi_rlast;
logic     [C_NUM_SLAVES-1 : 0] m_axi_rvalid;
logic     [C_NUM_SLAVES-1 : 0] m_axi_rready;

// AXI slave signals for getting wqe from system memory
//assign s_axi_awid   [C_RDMA_GET_WQE_IDX *2 +: 2]         = {1'b0, s_axi_rdma_get_wqe_awid};
assign s_axi_awid   [C_RDMA_GET_WQE_IDX *3 +: 3]         = s_axi_rdma_get_wqe_awvalid ? 3'd0 : 3'd0;
assign s_axi_awaddr [C_RDMA_GET_WQE_IDX *64 +: 64]       = s_axi_rdma_get_wqe_awaddr;
assign s_axi_awqos  [C_RDMA_GET_WQE_IDX *4 +: 4]         = s_axi_rdma_get_wqe_awqos;
assign s_axi_awlen  [C_RDMA_GET_WQE_IDX *8 +: 8]         = s_axi_rdma_get_wqe_awlen;
assign s_axi_awsize [C_RDMA_GET_WQE_IDX *3 +: 3]         = s_axi_rdma_get_wqe_awsize;
assign s_axi_awburst[C_RDMA_GET_WQE_IDX *2 +: 2]         = s_axi_rdma_get_wqe_awburst;
assign s_axi_awcache[C_RDMA_GET_WQE_IDX *4 +: 4]         = s_axi_rdma_get_wqe_awcache;
assign s_axi_awprot [C_RDMA_GET_WQE_IDX *3 +: 3]         = s_axi_rdma_get_wqe_awprot;
assign s_axi_awvalid[C_RDMA_GET_WQE_IDX *1 +: 1]         = s_axi_rdma_get_wqe_awvalid;
assign s_axi_rdma_get_wqe_awready                        = s_axi_awready[C_RDMA_GET_WQE_IDX *1 +: 1];
assign s_axi_wdata  [C_RDMA_GET_WQE_IDX *512 +: 512]     = s_axi_rdma_get_wqe_wdata;
assign s_axi_wstrb  [C_RDMA_GET_WQE_IDX *64 +: 64]       = s_axi_rdma_get_wqe_wstrb;
assign s_axi_wlast  [C_RDMA_GET_WQE_IDX *1 +: 1]         = s_axi_rdma_get_wqe_wlast;
assign s_axi_wvalid [C_RDMA_GET_WQE_IDX *1 +: 1]         = s_axi_rdma_get_wqe_wvalid;
assign s_axi_rdma_get_wqe_wready                         = s_axi_wready[C_RDMA_GET_WQE_IDX *1 +: 1];
assign s_axi_awlock [C_RDMA_GET_WQE_IDX *1 +: 1]         = s_axi_rdma_get_wqe_awlock;
assign s_axi_rdma_get_wqe_bid                            = s_axi_bid[C_RDMA_GET_WQE_IDX *3 +: 1];
assign s_axi_rdma_get_wqe_bresp                          = s_axi_bresp[C_RDMA_GET_WQE_IDX *2 +: 2];
assign s_axi_rdma_get_wqe_bvalid                         = s_axi_bvalid[C_RDMA_GET_WQE_IDX *1 +: 1];
assign s_axi_bready [C_RDMA_GET_WQE_IDX *1 +: 1]         = s_axi_rdma_get_wqe_bready;
//assign s_axi_arid   [C_RDMA_GET_WQE_IDX *2 +: 2]         = {1'b0, s_axi_rdma_get_wqe_arid};
assign s_axi_arid   [C_RDMA_GET_WQE_IDX *3 +: 3]         = s_axi_rdma_get_wqe_arvalid ? 3'd0 : 3'd0;
assign s_axi_araddr [C_RDMA_GET_WQE_IDX *64 +: 64]       = s_axi_rdma_get_wqe_araddr;
assign s_axi_arlen  [C_RDMA_GET_WQE_IDX *8  +: 8]        = s_axi_rdma_get_wqe_arlen;
assign s_axi_arsize [C_RDMA_GET_WQE_IDX *3  +: 3]        = s_axi_rdma_get_wqe_arsize;
assign s_axi_arburst[C_RDMA_GET_WQE_IDX *2  +: 2]        = s_axi_rdma_get_wqe_arburst;
assign s_axi_arcache[C_RDMA_GET_WQE_IDX *4  +: 4]        = s_axi_rdma_get_wqe_arcache;
assign s_axi_arprot [C_RDMA_GET_WQE_IDX *3  +: 3]        = s_axi_rdma_get_wqe_arprot;
assign s_axi_arvalid[C_RDMA_GET_WQE_IDX *1  +: 1]        = s_axi_rdma_get_wqe_arvalid;
assign s_axi_rdma_get_wqe_arready                        = s_axi_arready[C_RDMA_GET_WQE_IDX *1 +: 1];
assign s_axi_rdma_get_wqe_rid                            = s_axi_rid[C_RDMA_GET_WQE_IDX *3 +: 1];
assign s_axi_rdma_get_wqe_rdata                          = s_axi_rdata[C_RDMA_GET_WQE_IDX *512 +: 512];
assign s_axi_rdma_get_wqe_rresp                          = s_axi_rresp[C_RDMA_GET_WQE_IDX *2 +: 2];
assign s_axi_rdma_get_wqe_rlast                          = s_axi_rlast[C_RDMA_GET_WQE_IDX *1 +: 1];
assign s_axi_rdma_get_wqe_rvalid                         = s_axi_rvalid[C_RDMA_GET_WQE_IDX *1 +: 1];
assign s_axi_rready [C_RDMA_GET_WQE_IDX *1 +: 1]         = s_axi_rdma_get_wqe_rready;
assign s_axi_arlock [C_RDMA_GET_WQE_IDX *1 +: 1]         = s_axi_rdma_get_wqe_arlock;
assign s_axi_arqos  [C_RDMA_GET_WQE_IDX *4 +: 4]         = s_axi_rdma_get_wqe_arqos;

// AXI slave signals for getting payload from system memory
//assign axi_awid   [C_RDMA_GET_PAYLOAD_IDX*2 +: 2]      = {1'b0, s_axi_rdma_get_payload_awid};
assign s_axi_awid   [C_RDMA_GET_PAYLOAD_IDX*3 +: 3]      = s_axi_rdma_get_payload_awvalid ? 3'd1 : 3'd0;
assign s_axi_awaddr [C_RDMA_GET_PAYLOAD_IDX *64 +: 64]   = s_axi_rdma_get_payload_awaddr;
assign s_axi_awqos  [C_RDMA_GET_PAYLOAD_IDX *4 +: 4]     = s_axi_rdma_get_payload_awqos;
assign s_axi_awlen  [C_RDMA_GET_PAYLOAD_IDX *8 +: 8]     = s_axi_rdma_get_payload_awlen;
assign s_axi_awsize [C_RDMA_GET_PAYLOAD_IDX *3 +: 3]     = s_axi_rdma_get_payload_awsize;
assign s_axi_awburst[C_RDMA_GET_PAYLOAD_IDX *2 +: 2]     = s_axi_rdma_get_payload_awburst;
assign s_axi_awcache[C_RDMA_GET_PAYLOAD_IDX *4 +: 4]     = s_axi_rdma_get_payload_awcache;
assign s_axi_awprot [C_RDMA_GET_PAYLOAD_IDX *3 +: 3]     = s_axi_rdma_get_payload_awprot;
assign s_axi_awvalid[C_RDMA_GET_PAYLOAD_IDX *1 +: 1]     = s_axi_rdma_get_payload_awvalid;
assign s_axi_rdma_get_payload_awready                    = s_axi_awready[C_RDMA_GET_PAYLOAD_IDX *1 +: 1];
assign s_axi_wdata  [C_RDMA_GET_PAYLOAD_IDX *512 +: 512] = s_axi_rdma_get_payload_wdata;
assign s_axi_wstrb  [C_RDMA_GET_PAYLOAD_IDX *64 +: 64]   = s_axi_rdma_get_payload_wstrb;
assign s_axi_wlast  [C_RDMA_GET_PAYLOAD_IDX *1 +: 1]     = s_axi_rdma_get_payload_wlast;
assign s_axi_wvalid [C_RDMA_GET_PAYLOAD_IDX *1 +: 1]     = s_axi_rdma_get_payload_wvalid;
assign s_axi_rdma_get_payload_wready                     = s_axi_wready[C_RDMA_GET_PAYLOAD_IDX *1 +: 1];
assign s_axi_awlock [C_RDMA_GET_PAYLOAD_IDX *1 +: 1]     = s_axi_rdma_get_payload_awlock;
assign s_axi_rdma_get_payload_bid                        = s_axi_bid[C_RDMA_GET_PAYLOAD_IDX *3 +: 2];
assign s_axi_rdma_get_payload_bresp                      = s_axi_bresp[C_RDMA_GET_PAYLOAD_IDX *2 +: 2];
assign s_axi_rdma_get_payload_bvalid                     = s_axi_bvalid[C_RDMA_GET_PAYLOAD_IDX *1 +: 1];
assign s_axi_bready [C_RDMA_GET_PAYLOAD_IDX *1 +: 1]     = s_axi_rdma_get_payload_bready;
//assign s_axi_arid   [C_RDMA_GET_PAYLOAD_IDX *2 +: 2]     = {1'b0, s_axi_rdma_get_payload_arid};
assign s_axi_arid   [C_RDMA_GET_PAYLOAD_IDX *3 +: 3]     = s_axi_rdma_get_payload_arvalid ? 3'd1: 3'd0;
assign s_axi_araddr [C_RDMA_GET_PAYLOAD_IDX *64 +: 64]   = s_axi_rdma_get_payload_araddr;
assign s_axi_arlen  [C_RDMA_GET_PAYLOAD_IDX *8  +: 8]    = s_axi_rdma_get_payload_arlen;
assign s_axi_arsize [C_RDMA_GET_PAYLOAD_IDX *3  +: 3]    = s_axi_rdma_get_payload_arsize;
assign s_axi_arburst[C_RDMA_GET_PAYLOAD_IDX *2  +: 2]    = s_axi_rdma_get_payload_arburst;
assign s_axi_arcache[C_RDMA_GET_PAYLOAD_IDX *4  +: 4]    = s_axi_rdma_get_payload_arcache;
assign s_axi_arprot [C_RDMA_GET_PAYLOAD_IDX *3  +: 3]    = s_axi_rdma_get_payload_arprot;
assign s_axi_arvalid[C_RDMA_GET_PAYLOAD_IDX *1  +: 1]    = s_axi_rdma_get_payload_arvalid;
assign s_axi_rdma_get_payload_arready                    = s_axi_arready[C_RDMA_GET_PAYLOAD_IDX *1 +: 1];
assign s_axi_rdma_get_payload_rid                        = s_axi_rid[C_RDMA_GET_PAYLOAD_IDX *3 +: 2];
assign s_axi_rdma_get_payload_rdata                      = s_axi_rdata[C_RDMA_GET_PAYLOAD_IDX *512 +: 512];
assign s_axi_rdma_get_payload_rresp                      = s_axi_rresp[C_RDMA_GET_PAYLOAD_IDX *2 +: 2];
assign s_axi_rdma_get_payload_rlast                      = s_axi_rlast[C_RDMA_GET_PAYLOAD_IDX *1 +: 1];
assign s_axi_rdma_get_payload_rvalid                     = s_axi_rvalid[C_RDMA_GET_PAYLOAD_IDX *1 +: 1];
assign s_axi_rready [C_RDMA_GET_PAYLOAD_IDX *1 +: 1]     = s_axi_rdma_get_payload_rready;
assign s_axi_arlock [C_RDMA_GET_PAYLOAD_IDX *1 +: 1]     = s_axi_rdma_get_payload_arlock;
assign s_axi_arqos  [C_RDMA_GET_PAYLOAD_IDX *4 +: 4]     = s_axi_rdma_get_payload_arqos;

// AXI slave signals for data access from qdma mm channel
//assign axi_awid   [C_RDMA_COMPLETION_IDX*2 +: 2]       = {1'b0, s_axi_rdma_completion_awid};
assign s_axi_awid   [C_RDMA_COMPLETION_IDX*3 +: 3]       = s_axi_rdma_completion_awvalid ? 3'd2 : 3'd0;
assign s_axi_awaddr [C_RDMA_COMPLETION_IDX *64 +: 64]    = s_axi_rdma_completion_awaddr;
assign s_axi_awqos  [C_RDMA_COMPLETION_IDX *4 +: 4]      = s_axi_rdma_completion_awqos;
assign s_axi_awlen  [C_RDMA_COMPLETION_IDX *8 +: 8]      = s_axi_rdma_completion_awlen;
assign s_axi_awsize [C_RDMA_COMPLETION_IDX *3 +: 3]      = s_axi_rdma_completion_awsize;
assign s_axi_awburst[C_RDMA_COMPLETION_IDX *2 +: 2]      = s_axi_rdma_completion_awburst;
assign s_axi_awcache[C_RDMA_COMPLETION_IDX *4 +: 4]      = s_axi_rdma_completion_awcache;
assign s_axi_awprot [C_RDMA_COMPLETION_IDX *3 +: 3]      = s_axi_rdma_completion_awprot;
assign s_axi_awvalid[C_RDMA_COMPLETION_IDX *1 +: 1]      = s_axi_rdma_completion_awvalid;
assign s_axi_rdma_completion_awready                     = s_axi_awready[C_RDMA_COMPLETION_IDX *1 +: 1];
assign s_axi_wdata  [C_RDMA_COMPLETION_IDX *512 +: 512]  = s_axi_rdma_completion_wdata;
assign s_axi_wstrb  [C_RDMA_COMPLETION_IDX *64 +: 64]    = s_axi_rdma_completion_wstrb;
assign s_axi_wlast  [C_RDMA_COMPLETION_IDX *1 +: 1]      = s_axi_rdma_completion_wlast;
assign s_axi_wvalid [C_RDMA_COMPLETION_IDX *1 +: 1]      = s_axi_rdma_completion_wvalid;
assign s_axi_rdma_completion_wready                      = s_axi_wready[C_RDMA_COMPLETION_IDX *1 +: 1];
assign s_axi_awlock [C_RDMA_COMPLETION_IDX *1 +: 1]      = s_axi_rdma_completion_awlock;
assign s_axi_rdma_completion_bid                         = s_axi_bid[C_RDMA_COMPLETION_IDX *3 +: 1];
assign s_axi_rdma_completion_bresp                       = s_axi_bresp[C_RDMA_COMPLETION_IDX *2 +: 2];
assign s_axi_rdma_completion_bvalid                      = s_axi_bvalid[C_RDMA_COMPLETION_IDX *1 +: 1];
assign s_axi_bready [C_RDMA_COMPLETION_IDX *1 +: 1]      = s_axi_rdma_completion_bready;
//assign s_axi_arid   [C_RDMA_COMPLETION_IDX *2 +: 2]      = {1'b0, s_axi_rdma_completion_arid};
assign s_axi_arid   [C_RDMA_COMPLETION_IDX *3 +: 3]      = s_axi_rdma_completion_arvalid ? 3'd2 : 3'd0;
assign s_axi_araddr [C_RDMA_COMPLETION_IDX *64 +: 64]    = s_axi_rdma_completion_araddr;
assign s_axi_arlen  [C_RDMA_COMPLETION_IDX *8  +: 8]     = s_axi_rdma_completion_arlen;
assign s_axi_arsize [C_RDMA_COMPLETION_IDX *3  +: 3]     = s_axi_rdma_completion_arsize;
assign s_axi_arburst[C_RDMA_COMPLETION_IDX *2  +: 2]     = s_axi_rdma_completion_arburst;
assign s_axi_arcache[C_RDMA_COMPLETION_IDX *4  +: 4]     = s_axi_rdma_completion_arcache;
assign s_axi_arprot [C_RDMA_COMPLETION_IDX *3  +: 3]     = s_axi_rdma_completion_arprot;
assign s_axi_arvalid[C_RDMA_COMPLETION_IDX *1  +: 1]     = s_axi_rdma_completion_arvalid;
assign s_axi_rdma_completion_arready                     = s_axi_arready[C_RDMA_COMPLETION_IDX *1 +: 1];
assign s_axi_rdma_completion_rid                         = s_axi_rid[C_RDMA_COMPLETION_IDX *3 +: 1];
assign s_axi_rdma_completion_rdata                       = s_axi_rdata[C_RDMA_COMPLETION_IDX *512 +: 512];
assign s_axi_rdma_completion_rresp                       = s_axi_rresp[C_RDMA_COMPLETION_IDX *2 +: 2];
assign s_axi_rdma_completion_rlast                       = s_axi_rlast[C_RDMA_COMPLETION_IDX *1 +: 1];
assign s_axi_rdma_completion_rvalid                      = s_axi_rvalid[C_RDMA_COMPLETION_IDX *1 +: 1];
assign s_axi_rready [C_RDMA_COMPLETION_IDX *1 +: 1]      = s_axi_rdma_completion_rready;
assign s_axi_arlock [C_RDMA_COMPLETION_IDX *1 +: 1]      = s_axi_rdma_completion_arlock;
assign s_axi_arqos  [C_RDMA_COMPLETION_IDX *4 +: 4]      = s_axi_rdma_completion_arqos;

// AXI slave signals for storing payload from RDMA send or write
//assign axi_awid   [C_RDMA_GET_SEND_WRITE_PAYLOAD_IDX *2 +: 2]         = {1'b0, s_axi_rdma_send_write_payload_awid};
assign s_axi_awid   [C_RDMA_GET_SEND_WRITE_PAYLOAD_IDX *3 +: 3]         = s_axi_rdma_send_write_payload_awvalid ? 3'd3 : 3'd0;
assign s_axi_awaddr [C_RDMA_GET_SEND_WRITE_PAYLOAD_IDX *64 +: 64]       = s_axi_rdma_send_write_payload_awaddr;
assign s_axi_awqos  [C_RDMA_GET_SEND_WRITE_PAYLOAD_IDX *4 +: 4]         = s_axi_rdma_send_write_payload_awqos;
assign s_axi_awlen  [C_RDMA_GET_SEND_WRITE_PAYLOAD_IDX *8 +: 8]         = s_axi_rdma_send_write_payload_awlen;
assign s_axi_awsize [C_RDMA_GET_SEND_WRITE_PAYLOAD_IDX *3 +: 3]         = s_axi_rdma_send_write_payload_awsize;
assign s_axi_awburst[C_RDMA_GET_SEND_WRITE_PAYLOAD_IDX *2 +: 2]         = s_axi_rdma_send_write_payload_awburst;
assign s_axi_awcache[C_RDMA_GET_SEND_WRITE_PAYLOAD_IDX *4 +: 4]         = s_axi_rdma_send_write_payload_awcache;
assign s_axi_awprot [C_RDMA_GET_SEND_WRITE_PAYLOAD_IDX *3 +: 3]         = s_axi_rdma_send_write_payload_awprot;
assign s_axi_awvalid[C_RDMA_GET_SEND_WRITE_PAYLOAD_IDX *1 +: 1]         = s_axi_rdma_send_write_payload_awvalid;
assign s_axi_rdma_send_write_payload_awready                            = s_axi_awready[C_RDMA_GET_SEND_WRITE_PAYLOAD_IDX *1 +: 1];
assign s_axi_wdata  [C_RDMA_GET_SEND_WRITE_PAYLOAD_IDX *512 +: 512]     = s_axi_rdma_send_write_payload_wdata;
assign s_axi_wstrb  [C_RDMA_GET_SEND_WRITE_PAYLOAD_IDX *64 +: 64]       = s_axi_rdma_send_write_payload_wstrb;
assign s_axi_wlast  [C_RDMA_GET_SEND_WRITE_PAYLOAD_IDX *1 +: 1]         = s_axi_rdma_send_write_payload_wlast;
assign s_axi_wvalid [C_RDMA_GET_SEND_WRITE_PAYLOAD_IDX *1 +: 1]         = s_axi_rdma_send_write_payload_wvalid;

assign s_axi_awlock [C_RDMA_GET_SEND_WRITE_PAYLOAD_IDX *1 +: 1]         = s_axi_rdma_send_write_payload_awlock;
assign s_axi_rdma_send_write_payload_bid                                = s_axi_bid[C_RDMA_GET_SEND_WRITE_PAYLOAD_IDX *3 +: 1];
assign s_axi_rdma_send_write_payload_bresp                              = s_axi_bresp[C_RDMA_GET_SEND_WRITE_PAYLOAD_IDX *2 +: 2];
assign s_axi_rdma_send_write_payload_bvalid                             = s_axi_bvalid[C_RDMA_GET_SEND_WRITE_PAYLOAD_IDX *1 +: 1];
assign s_axi_bready [C_RDMA_GET_SEND_WRITE_PAYLOAD_IDX *1 +: 1]         = s_axi_rdma_send_write_payload_bready;
//assign s_axi_arid   [C_RDMA_GET_SEND_WRITE_PAYLOAD_IDX *2 +: 2]         = {1'b0, s_axi_rdma_send_write_payload_arid};
assign s_axi_arid   [C_RDMA_GET_SEND_WRITE_PAYLOAD_IDX *3 +: 3]         = s_axi_rdma_send_write_payload_arvalid ? 3'd3 : 3'd0;
assign s_axi_araddr [C_RDMA_GET_SEND_WRITE_PAYLOAD_IDX *64 +: 64]       = s_axi_rdma_send_write_payload_araddr;
assign s_axi_arlen  [C_RDMA_GET_SEND_WRITE_PAYLOAD_IDX *8  +: 8]        = s_axi_rdma_send_write_payload_arlen;
assign s_axi_arsize [C_RDMA_GET_SEND_WRITE_PAYLOAD_IDX *3  +: 3]        = s_axi_rdma_send_write_payload_arsize;
assign s_axi_arburst[C_RDMA_GET_SEND_WRITE_PAYLOAD_IDX *2  +: 2]        = s_axi_rdma_send_write_payload_arburst;
assign s_axi_arcache[C_RDMA_GET_SEND_WRITE_PAYLOAD_IDX *4  +: 4]        = s_axi_rdma_send_write_payload_arcache;
assign s_axi_arprot [C_RDMA_GET_SEND_WRITE_PAYLOAD_IDX *3  +: 3]        = s_axi_rdma_send_write_payload_arprot;
assign s_axi_arvalid[C_RDMA_GET_SEND_WRITE_PAYLOAD_IDX *1  +: 1]        = s_axi_rdma_send_write_payload_arvalid;
assign s_axi_rdma_send_write_payload_arready                            = s_axi_arready[C_RDMA_GET_SEND_WRITE_PAYLOAD_IDX *1 +: 1];
assign s_axi_rdma_send_write_payload_rid                                = s_axi_rid[C_RDMA_GET_SEND_WRITE_PAYLOAD_IDX *3 +: 1];
assign s_axi_rdma_send_write_payload_rdata                              = s_axi_rdata[C_RDMA_GET_SEND_WRITE_PAYLOAD_IDX *512 +: 512];
assign s_axi_rdma_send_write_payload_rresp                              = s_axi_rresp[C_RDMA_GET_SEND_WRITE_PAYLOAD_IDX *2 +: 2];
assign s_axi_rdma_send_write_payload_rlast                              = s_axi_rlast[C_RDMA_GET_SEND_WRITE_PAYLOAD_IDX *1 +: 1];
assign s_axi_rdma_send_write_payload_rvalid                             = s_axi_rvalid[C_RDMA_GET_SEND_WRITE_PAYLOAD_IDX *1 +: 1];
assign s_axi_rready [C_RDMA_GET_SEND_WRITE_PAYLOAD_IDX *1 +: 1]         = s_axi_rdma_send_write_payload_rready;
assign s_axi_arlock [C_RDMA_GET_SEND_WRITE_PAYLOAD_IDX *1 +: 1]         = s_axi_rdma_send_write_payload_arlock;
assign s_axi_arqos  [C_RDMA_GET_SEND_WRITE_PAYLOAD_IDX *4 +: 4]         = s_axi_rdma_send_write_payload_arqos;

// AXI slave signals for storing payload from RDMA read response
//assign axi_awid   [C_RDMA_RSP_PAYLOAD_IDX*2 +: 2]       = {1'b0, s_axi_rdma_rsp_payload_awid};
assign s_axi_awid   [C_RDMA_RSP_PAYLOAD_IDX*3 +: 3]       = s_axi_rdma_rsp_payload_awvalid ? 3'd4 : 3'd0;
assign s_axi_awaddr [C_RDMA_RSP_PAYLOAD_IDX *64 +: 64]    = s_axi_rdma_rsp_payload_awaddr;
assign s_axi_awqos  [C_RDMA_RSP_PAYLOAD_IDX *4 +: 4]      = s_axi_rdma_rsp_payload_awqos;
assign s_axi_awlen  [C_RDMA_RSP_PAYLOAD_IDX *8 +: 8]      = s_axi_rdma_rsp_payload_awlen;
assign s_axi_awsize [C_RDMA_RSP_PAYLOAD_IDX *3 +: 3]      = s_axi_rdma_rsp_payload_awsize;
assign s_axi_awburst[C_RDMA_RSP_PAYLOAD_IDX *2 +: 2]      = s_axi_rdma_rsp_payload_awburst;
assign s_axi_awcache[C_RDMA_RSP_PAYLOAD_IDX *4 +: 4]      = s_axi_rdma_rsp_payload_awcache;
assign s_axi_awprot [C_RDMA_RSP_PAYLOAD_IDX *3 +: 3]      = s_axi_rdma_rsp_payload_awprot;
assign s_axi_awvalid[C_RDMA_RSP_PAYLOAD_IDX *1 +: 1]      = s_axi_rdma_rsp_payload_awvalid;
assign s_axi_rdma_rsp_payload_awready                     = s_axi_awready[C_RDMA_RSP_PAYLOAD_IDX *1 +: 1];
assign s_axi_wdata  [C_RDMA_RSP_PAYLOAD_IDX *512 +: 512]  = s_axi_rdma_rsp_payload_wdata;
assign s_axi_wstrb  [C_RDMA_RSP_PAYLOAD_IDX *64 +: 64]    = s_axi_rdma_rsp_payload_wstrb;
assign s_axi_wlast  [C_RDMA_RSP_PAYLOAD_IDX *1 +: 1]      = s_axi_rdma_rsp_payload_wlast;
assign s_axi_wvalid [C_RDMA_RSP_PAYLOAD_IDX *1 +: 1]      = s_axi_rdma_rsp_payload_wvalid;
assign s_axi_rdma_rsp_payload_wready                      = s_axi_wready[C_RDMA_RSP_PAYLOAD_IDX *1 +: 1];
assign s_axi_awlock [C_RDMA_RSP_PAYLOAD_IDX *1 +: 1]      = s_axi_rdma_rsp_payload_awlock;
assign s_axi_rdma_rsp_payload_bid                         = s_axi_bid[C_RDMA_RSP_PAYLOAD_IDX *3 +: 1];
assign s_axi_rdma_rsp_payload_bresp                       = s_axi_bresp[C_RDMA_RSP_PAYLOAD_IDX *2 +: 2];
assign s_axi_rdma_rsp_payload_bvalid                      = s_axi_bvalid[C_RDMA_RSP_PAYLOAD_IDX *1 +: 1];
assign s_axi_bready [C_RDMA_RSP_PAYLOAD_IDX *1 +: 1]      = s_axi_rdma_rsp_payload_bready;
//assign axi_arid   [C_RDMA_RSP_PAYLOAD_IDX *2 +: 2]      = {1'b0, s_axi_rdma_rsp_payload_arid};
assign s_axi_arid   [C_RDMA_RSP_PAYLOAD_IDX *3 +: 3]      = s_axi_rdma_rsp_payload_arvalid ? 3'd4 : 3'd0;
assign s_axi_araddr [C_RDMA_RSP_PAYLOAD_IDX *64 +: 64]    = s_axi_rdma_rsp_payload_araddr;
assign s_axi_arlen  [C_RDMA_RSP_PAYLOAD_IDX *8  +: 8]     = s_axi_rdma_rsp_payload_arlen;
assign s_axi_arsize [C_RDMA_RSP_PAYLOAD_IDX *3  +: 3]     = s_axi_rdma_rsp_payload_arsize;
assign s_axi_arburst[C_RDMA_RSP_PAYLOAD_IDX *2  +: 2]     = s_axi_rdma_rsp_payload_arburst;
assign s_axi_arcache[C_RDMA_RSP_PAYLOAD_IDX *4  +: 4]     = s_axi_rdma_rsp_payload_arcache;
assign s_axi_arprot [C_RDMA_RSP_PAYLOAD_IDX *3  +: 3]     = s_axi_rdma_rsp_payload_arprot;
assign s_axi_arvalid[C_RDMA_RSP_PAYLOAD_IDX *1  +: 1]     = s_axi_rdma_rsp_payload_arvalid;
assign s_axi_rdma_rsp_payload_arready                     = s_axi_arready[C_RDMA_RSP_PAYLOAD_IDX *1 +: 1];
assign s_axi_rdma_rsp_payload_rid                         = s_axi_rid[C_RDMA_RSP_PAYLOAD_IDX *3 +: 1];
assign s_axi_rdma_rsp_payload_rdata                       = s_axi_rdata[C_RDMA_RSP_PAYLOAD_IDX *512 +: 512];
assign s_axi_rdma_rsp_payload_rresp                       = s_axi_rresp[C_RDMA_RSP_PAYLOAD_IDX *2 +: 2];
assign s_axi_rdma_rsp_payload_rlast                       = s_axi_rlast[C_RDMA_RSP_PAYLOAD_IDX *1 +: 1];
assign s_axi_rdma_rsp_payload_rvalid                      = s_axi_rvalid[C_RDMA_RSP_PAYLOAD_IDX *1 +: 1];
assign s_axi_rready [C_RDMA_RSP_PAYLOAD_IDX *1 +: 1]      = s_axi_rdma_rsp_payload_rready;
assign s_axi_arlock [C_RDMA_RSP_PAYLOAD_IDX *1 +: 1]      = s_axi_rdma_rsp_payload_arlock;
assign s_axi_arqos  [C_RDMA_RSP_PAYLOAD_IDX *4 +: 4]      = s_axi_rdma_rsp_payload_arqos;

//AXI signals to system memory
//assign m_axi_awid   [C_SYS_MEM_IDX *2 +: 2]         = {1'b0, m_axi_sys_mem_awid};
assign m_axi_sys_mem_awid                     = m_axi_awid   [C_SYS_MEM_IDX *3 +: 3];
assign m_axi_sys_mem_awaddr                   = m_axi_awaddr [C_SYS_MEM_IDX *64 +: 64];
assign m_axi_sys_mem_awqos                    = m_axi_awqos  [C_SYS_MEM_IDX *4 +: 4];
assign m_axi_sys_mem_awlen                    = m_axi_awlen  [C_SYS_MEM_IDX *8 +: 8];
assign m_axi_sys_mem_awsize                   = m_axi_awsize [C_SYS_MEM_IDX *3 +: 3];
assign m_axi_sys_mem_awburst                  = m_axi_awburst[C_SYS_MEM_IDX *2 +: 2];
assign m_axi_sys_mem_awcache                  = m_axi_awcache[C_SYS_MEM_IDX *4 +: 4];
assign m_axi_sys_mem_awprot                   = m_axi_awprot [C_SYS_MEM_IDX *3 +: 3];
assign m_axi_sys_mem_awvalid                  = m_axi_awvalid[C_SYS_MEM_IDX *1 +: 1];
assign m_axi_awready[C_SYS_MEM_IDX *1 +: 1]   = m_axi_sys_mem_awready;
assign m_axi_sys_mem_wdata                    = m_axi_wdata  [C_SYS_MEM_IDX *512 +: 512];
assign m_axi_sys_mem_wstrb                    = m_axi_wstrb  [C_SYS_MEM_IDX *64 +: 64];
assign m_axi_sys_mem_wlast                    = m_axi_wlast  [C_SYS_MEM_IDX *1 +: 1];
assign m_axi_sys_mem_wvalid                   = m_axi_wvalid [C_SYS_MEM_IDX *1 +: 1];
assign m_axi_wready[C_SYS_MEM_IDX *1 +: 1]    = m_axi_sys_mem_wready;
assign m_axi_sys_mem_awlock                   = m_axi_awlock [C_SYS_MEM_IDX *1 +: 1];
assign m_axi_bid[C_SYS_MEM_IDX *3 +: 3]       = m_axi_sys_mem_bid;
assign m_axi_bresp[C_SYS_MEM_IDX *2 +: 2]     = m_axi_sys_mem_bresp;
assign m_axi_bvalid[C_SYS_MEM_IDX *1 +: 1]    = m_axi_sys_mem_bvalid;
assign m_axi_sys_mem_bready                   = m_axi_bready [C_SYS_MEM_IDX *1 +: 1];
//assign m_axi_sys_mem_arid                   = m_axi_arid   [C_SYS_MEM_IDX *2 +: 2];
assign m_axi_sys_mem_arid                     = m_axi_arid   [C_SYS_MEM_IDX *3 +: 3];
assign m_axi_sys_mem_araddr                   = m_axi_araddr [C_SYS_MEM_IDX *64 +: 64];
assign m_axi_sys_mem_arlen                    = m_axi_arlen  [C_SYS_MEM_IDX *8  +: 8];
assign m_axi_sys_mem_arsize                   = m_axi_arsize [C_SYS_MEM_IDX *3  +: 3];
assign m_axi_sys_mem_arburst                  = m_axi_arburst[C_SYS_MEM_IDX *2  +: 2];
assign m_axi_sys_mem_arcache                  = m_axi_arcache[C_SYS_MEM_IDX *4  +: 4];
assign m_axi_sys_mem_arprot                   = m_axi_arprot [C_SYS_MEM_IDX *3  +: 3];
assign m_axi_sys_mem_arvalid                  = m_axi_arvalid[C_SYS_MEM_IDX *1  +: 1];
assign m_axi_arready[C_SYS_MEM_IDX *1 +: 1]   = m_axi_sys_mem_arready;
assign m_axi_rid[C_SYS_MEM_IDX *3 +: 3]       = m_axi_sys_mem_rid;
assign m_axi_rdata[C_SYS_MEM_IDX *512 +: 512] = m_axi_sys_mem_rdata;
assign m_axi_rresp[C_SYS_MEM_IDX *2 +: 2]     = m_axi_sys_mem_rresp;
assign m_axi_rlast[C_SYS_MEM_IDX *1 +: 1]     = m_axi_sys_mem_rlast;
assign m_axi_rvalid[C_SYS_MEM_IDX *1 +: 1]    = m_axi_sys_mem_rvalid;
assign m_axi_sys_mem_rready                   = m_axi_rready [C_SYS_MEM_IDX *1 +: 1];
assign m_axi_sys_mem_arlock                   = m_axi_arlock [C_SYS_MEM_IDX *1 +: 1];
assign m_axi_sys_mem_arqos                    = m_axi_arqos  [C_SYS_MEM_IDX *4 +: 4];

//AXI signals to device memory
//assign m_axi_awid   [C_SYS_TO_DEV_CROSSBAR_IDX *2 +: 2]         = {1'b0, m_axi_sys_to_dev_crossbar_awid};
assign m_axi_sys_to_dev_crossbar_awid         = m_axi_awid   [C_SYS_TO_DEV_CROSSBAR_IDX *3 +: 3];
assign m_axi_sys_to_dev_crossbar_awaddr       = m_axi_awaddr [C_SYS_TO_DEV_CROSSBAR_IDX *64 +: 64];
assign m_axi_sys_to_dev_crossbar_awqos        = m_axi_awqos  [C_SYS_TO_DEV_CROSSBAR_IDX *4 +: 4];
assign m_axi_sys_to_dev_crossbar_awlen        = m_axi_awlen  [C_SYS_TO_DEV_CROSSBAR_IDX *8 +: 8];
assign m_axi_sys_to_dev_crossbar_awsize       = m_axi_awsize [C_SYS_TO_DEV_CROSSBAR_IDX *3 +: 3];
assign m_axi_sys_to_dev_crossbar_awburst      = m_axi_awburst[C_SYS_TO_DEV_CROSSBAR_IDX *2 +: 2];
assign m_axi_sys_to_dev_crossbar_awcache      = m_axi_awcache[C_SYS_TO_DEV_CROSSBAR_IDX *4 +: 4];
assign m_axi_sys_to_dev_crossbar_awprot       = m_axi_awprot [C_SYS_TO_DEV_CROSSBAR_IDX *3 +: 3];
assign m_axi_sys_to_dev_crossbar_awvalid      = m_axi_awvalid[C_SYS_TO_DEV_CROSSBAR_IDX *1 +: 1];
assign m_axi_awready[C_SYS_TO_DEV_CROSSBAR_IDX *1 +: 1]          = m_axi_sys_to_dev_crossbar_awready;
assign m_axi_sys_to_dev_crossbar_wdata        = m_axi_wdata  [C_SYS_TO_DEV_CROSSBAR_IDX *512 +: 512];
assign m_axi_sys_to_dev_crossbar_wstrb        = m_axi_wstrb  [C_SYS_TO_DEV_CROSSBAR_IDX *64 +: 64];
assign m_axi_sys_to_dev_crossbar_wlast        = m_axi_wlast  [C_SYS_TO_DEV_CROSSBAR_IDX *1 +: 1];
assign m_axi_sys_to_dev_crossbar_wvalid       = m_axi_wvalid [C_SYS_TO_DEV_CROSSBAR_IDX *1 +: 1];
assign m_axi_wready[C_SYS_TO_DEV_CROSSBAR_IDX *1 +: 1]           = m_axi_sys_to_dev_crossbar_wready;
assign m_axi_sys_to_dev_crossbar_awlock       = m_axi_awlock [C_SYS_TO_DEV_CROSSBAR_IDX *1 +: 1];
assign m_axi_bid[C_SYS_TO_DEV_CROSSBAR_IDX *3 +: 3]              = m_axi_sys_to_dev_crossbar_bid;
assign m_axi_bresp[C_SYS_TO_DEV_CROSSBAR_IDX *2 +: 2]            = m_axi_sys_to_dev_crossbar_bresp;
assign m_axi_bvalid[C_SYS_TO_DEV_CROSSBAR_IDX *1 +: 1]           = m_axi_sys_to_dev_crossbar_bvalid;
assign m_axi_sys_to_dev_crossbar_bready       = m_axi_bready [C_SYS_TO_DEV_CROSSBAR_IDX *1 +: 1];
//assign m_axi_sys_to_dev_crossbar_arid         = m_axi_arid   [C_SYS_TO_DEV_CROSSBAR_IDX *2 +: 2];
assign m_axi_sys_to_dev_crossbar_arid         = m_axi_arid   [C_SYS_TO_DEV_CROSSBAR_IDX *3 +: 3];
assign m_axi_sys_to_dev_crossbar_araddr       = m_axi_araddr [C_SYS_TO_DEV_CROSSBAR_IDX *64 +: 64];
assign m_axi_sys_to_dev_crossbar_arlen        = m_axi_arlen  [C_SYS_TO_DEV_CROSSBAR_IDX *8  +: 8];
assign m_axi_sys_to_dev_crossbar_arsize       = m_axi_arsize [C_SYS_TO_DEV_CROSSBAR_IDX *3  +: 3];
assign m_axi_sys_to_dev_crossbar_arburst      = m_axi_arburst[C_SYS_TO_DEV_CROSSBAR_IDX *2  +: 2];
assign m_axi_sys_to_dev_crossbar_arcache      = m_axi_arcache[C_SYS_TO_DEV_CROSSBAR_IDX *4  +: 4];
assign m_axi_sys_to_dev_crossbar_arprot       = m_axi_arprot [C_SYS_TO_DEV_CROSSBAR_IDX *3  +: 3];
assign m_axi_sys_to_dev_crossbar_arvalid      = m_axi_arvalid[C_SYS_TO_DEV_CROSSBAR_IDX *1  +: 1];
assign m_axi_arready[C_SYS_TO_DEV_CROSSBAR_IDX *1 +: 1]          = m_axi_sys_to_dev_crossbar_arready;
assign m_axi_rid[C_SYS_TO_DEV_CROSSBAR_IDX *3 +: 3]              = m_axi_sys_to_dev_crossbar_rid;
assign m_axi_rdata[C_SYS_TO_DEV_CROSSBAR_IDX *512 +: 512]        = m_axi_sys_to_dev_crossbar_rdata;
assign m_axi_rresp[C_SYS_TO_DEV_CROSSBAR_IDX *2 +: 2]            = m_axi_sys_to_dev_crossbar_rresp;
assign m_axi_rlast[C_SYS_TO_DEV_CROSSBAR_IDX *1 +: 1]            = m_axi_sys_to_dev_crossbar_rlast;
assign m_axi_rvalid[C_SYS_TO_DEV_CROSSBAR_IDX *1 +: 1]           = m_axi_sys_to_dev_crossbar_rvalid;
assign m_axi_sys_to_dev_crossbar_rready       = m_axi_rready [C_SYS_TO_DEV_CROSSBAR_IDX *1 +: 1];
assign m_axi_sys_to_dev_crossbar_arlock       = m_axi_arlock [C_SYS_TO_DEV_CROSSBAR_IDX *1 +: 1];
assign m_axi_sys_to_dev_crossbar_arqos        = m_axi_arqos  [C_SYS_TO_DEV_CROSSBAR_IDX *4 +: 4];

sys_mem_5to2_axi_crossbar sys_mem_5to2_axi_crossbar_inst (
  .m_axi_awaddr    (m_axi_awaddr),
  .m_axi_awprot    (m_axi_awprot),
  .m_axi_awvalid   (m_axi_awvalid),
  .m_axi_awready   (m_axi_awready),
  .m_axi_awsize    (m_axi_awsize),
  .m_axi_awburst   (m_axi_awburst),
  .m_axi_awcache   (m_axi_awcache),
  .m_axi_awlen     (m_axi_awlen),
  .m_axi_awlock    (m_axi_awlock),
  .m_axi_awqos     (m_axi_awqos),
  .m_axi_awregion  (m_axi_awregion),
  .m_axi_awid      (m_axi_awid),
  .m_axi_wdata     (m_axi_wdata),
  .m_axi_wstrb     (m_axi_wstrb),
  .m_axi_wvalid    (m_axi_wvalid),
  .m_axi_wready    (m_axi_wready),
  .m_axi_wlast     (m_axi_wlast),
  .m_axi_bresp     (m_axi_bresp),
  .m_axi_bvalid    (m_axi_bvalid),
  .m_axi_bready    (m_axi_bready),
  .m_axi_bid       (m_axi_bid),
  .m_axi_araddr    (m_axi_araddr),
  .m_axi_arprot    (m_axi_arprot),
  .m_axi_arvalid   (m_axi_arvalid),
  .m_axi_arready   (m_axi_arready),
  .m_axi_arsize    (m_axi_arsize),
  .m_axi_arburst   (m_axi_arburst),
  .m_axi_arcache   (m_axi_arcache),
  .m_axi_arlock    (m_axi_arlock),
  .m_axi_arlen     (m_axi_arlen),
  .m_axi_arqos     (m_axi_arqos),
  .m_axi_arregion  (m_axi_arregion),
  .m_axi_arid      (m_axi_arid),
  .m_axi_rdata     (m_axi_rdata),
  .m_axi_rresp     (m_axi_rresp),
  .m_axi_rvalid    (m_axi_rvalid),
  .m_axi_rready    (m_axi_rready),
  .m_axi_rlast     (m_axi_rlast),
  .m_axi_rid       (m_axi_rid),

  .s_axi_awid      (s_axi_awid),
  .s_axi_awaddr    (s_axi_awaddr),
  .s_axi_awqos     (s_axi_awqos),
  .s_axi_awlen     (s_axi_awlen),
  .s_axi_awsize    (s_axi_awsize),
  .s_axi_awburst   (s_axi_awburst),
  .s_axi_awcache   (s_axi_awcache),
  .s_axi_awprot    (s_axi_awprot),
  .s_axi_awvalid   (s_axi_awvalid),
  .s_axi_awready   (s_axi_awready),
  .s_axi_wdata     (s_axi_wdata),
  .s_axi_wstrb     (s_axi_wstrb),
  .s_axi_wlast     (s_axi_wlast),
  .s_axi_wvalid    (s_axi_wvalid),
  .s_axi_wready    (s_axi_wready),
  .s_axi_awlock    (s_axi_awlock),
  .s_axi_bid       (s_axi_bid),
  .s_axi_bresp     (s_axi_bresp),
  .s_axi_bvalid    (s_axi_bvalid),
  .s_axi_bready    (s_axi_bready),
  .s_axi_arid      (s_axi_arid),
  .s_axi_araddr    (s_axi_araddr),
  .s_axi_arlen     (s_axi_arlen),
  .s_axi_arsize    (s_axi_arsize),
  .s_axi_arburst   (s_axi_arburst),
  .s_axi_arcache   (s_axi_arcache),
  .s_axi_arprot    (s_axi_arprot),
  .s_axi_arvalid   (s_axi_arvalid),
  .s_axi_arready   (s_axi_arready),
  .s_axi_rid       (s_axi_rid),
  .s_axi_rdata     (s_axi_rdata),
  .s_axi_rresp     (s_axi_rresp),
  .s_axi_rlast     (s_axi_rlast),
  .s_axi_rvalid    (s_axi_rvalid),
  .s_axi_rready    (s_axi_rready),
  .s_axi_arlock    (s_axi_arlock),
  .s_axi_arqos     (s_axi_arqos),

  .aclk   (axis_aclk),
  .aresetn(axis_arestn)
);

endmodule: axi_5to2_interconnect_to_sys_mem

assign s_axi_rdma_send_write_payload_wready                             = s_axi_wready[C_RDMA_GET_SEND_WRITE_PAYLOAD_IDX *1 +: 1];


/*
* Copyright 2019 Xilinx Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*    http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

`pragma protect begin_protected
`pragma protect version = 2
`pragma protect encrypt_agent = "XILINX"
`pragma protect encrypt_agent_info = "Xilinx Encryption Tool 2022.1"
`pragma protect begin_commonblock
`pragma protect control error_handling = "delegated"
`pragma protect control runtime_visibility = "delegated"
`pragma protect control child_visibility = "delegated"
`pragma protect control decryption=(activity==simulation) ? "false" : "true"

`pragma protect begin_toolblock
`pragma protect rights_digest_method="sha256"
`pragma protect key_keyowner = "Xilinx", key_keyname= "xilinxt_2020_08", key_method = "rsa", key_block
CaihNQWwu+qKJWjcmdIgzgKIXQ8l3vMImmWHnChjYqoa51yMcErBScyiE64YZSDih9WCUqsVfjEZ
HfdPZ9ljuyASaDAJWOBnJBbhrePBDPO5jKkFmPbv80QoBXSWaNMFc5sW0Ulg3lCiE5qq9SVr7IMd
vkFVewJkI9IJKPXIqEiYLMio527A7EkzJrjUXC11BQnTYghbA5n7/6q2WIDOwjQ+BdLZXxGdIUKi
ihIieqBZEgdd6vwETSGv3sSorIwnUPSueC94L800xEEoFQmghwgPGvLA3IEIqt1YNZfrY4rcuvTH
rxE5ve/ar6tMYP0QdSitAf/UOVre3EWtsP+Jcw==

`pragma protect control xilinx_configuration_visible = "false"
`pragma protect control xilinx_enable_modification = "false"
`pragma protect control xilinx_enable_probing = "false"
`pragma protect control xilinx_enable_netlist_export = "false"
`pragma protect control xilinx_enable_bitstream = "true"
`pragma protect control decryption=(xilinx_activity==simulation) ? "false" : "true"
`pragma protect end_toolblock="IxINXwVvXQ/n7KwTaYrPoEaEACBK27oPy3cRIdl/LOI="
`pragma protect data_method = "AES128-CBC"
`pragma protect encoding = (enctype = "BASE64", line_length = 76, bytes = 880)
`pragma protect data_block
EiGu1ShDtOnFp1/lwt6VhcUR8yhnAB8O5e1xLbmtU8hFkeRUrpaBl1HAfyRFT7nbtX9ANec6bT/6
M5F1wZGG5qSvkCUW8yVN2ibhwe39b3gqpxlAM0Rk2b5g0GPQS0EovauYN9XAQquN58ggK/O+KDM0
63s7X7It+p/RSFzWWRGZS+v0XTm+D2a1XMT2uisqh8PefOCoBySO44oktKTY504wlCSc5omNSe+u
zOKrUyvkLauqfVr0IymzexsmShoC8a5rxCwtiHWtuZd3ISZeseAH4yuuIE22EaResPkSs0AOtuxW
LUa+5ziMFj1jUrwyX7edUaYFWubmHAbAkkw9Hm+C6bamM5RNvdj0nJ6+9kR3k9JEEwFcMnpU/+T7
AyStZ42jqyndQBD+fvcXAhE7unT9l7MeF6FPz+f4fj9QLQ9uKKfDT4Z/nUyAujR54s7JMJPusI/1
6kmMjc0VDkHnbDi2wkCweAVtI13pMf21kgykit61e5wC9yuUa3wMmmwN0K5j3CFUalZcs5zyaUEU
RFQ6sxbZKoizpkyYAVpfJ5ooRM+2IwCcC/xaZGuC28xR1sA7FuTz8gJHfj+31ej4SmCB90pf8a1j
v5GMWH/IC2k1qDCu3Nv9vlIh9ddPqzd8V2kbzHKQIixQUYVEYd6XzNzpOSAo7YP0yS1vkaxpM13/
tmu8VZm2h2JkrlzFuDwth9ORNpQM+dxpUbIiNRz188RAIvel6yq9G8g7YjGY6Jq1qeGPfgm2uqIE
OYHDHJww2kjAzMfBu4zQRXixjhSL5YOVbevDsp++Yot323jrunN6b3HYs5T3zX64N23723OKUorb
BzfFPVvrOEw7oa31ZqgZSsWbWZMOkcIa955Zi5oSnEOq4KNx1IMlwiRrRVmeW2nzDZyOT/6kkiV5
Ay+TkZF19zF0PKmiNq0809vsxErEHL/7oYdQDYLNmot/tAe+f381qkRVEbZrjA0uWw8e7xnBZXdh
276B2htPR1ezVeOX25aKI5B2G/pH+lUnzW5CqMGEcgS1yReFHycsSdJkPGQDl0uTLiAZLicoj2v3
CAT2TDbLr2Obrdb1Xpom03ZaOT0ImqBumdzSoPD+eRvc0qT6AoCHxmNojpf4C2WADh3N57ctHcPk
V7HEOkM7H6joRSQhUNMkeuqXc/t6IH5R7g==
`pragma protect end_protected

//


// Copyright 2023 ETH Zurich and University of Bologna.
// Solderpad Hardware License, Version 0.51, see LICENSE for details.
// SPDX-License-Identifier: SHL-0.51
//
// Yvan Tortorella <yvan.tortorella@unibo.it>
//

import fpnew_pkg::*;
import hci_package::*;
import redmule_pkg::*;

module redmule_castin #(
  parameter int unsigned DATA_W = redmule_pkg::DATA_W,
  parameter fpnew_pkg::fmt_logic_t   FpFmtConfig  = FpFmtConfig,
  parameter fpnew_pkg::ifmt_logic_t  IntFmtConfig = IntFmtConfig,
  parameter fpnew_pkg::fp_format_e   DstFormat    = FPFORMAT,
  parameter fpnew_pkg::operation_e   Operation    = CAST_OP,
  parameter logic Pipe                            = 1'b0    ,
  localparam int unsigned BW = hci_package::DEFAULT_BW      ,
  localparam int unsigned OW = ADDR_W                       ,
  localparam int unsigned UW = hci_package::DEFAULT_UW      ,
  localparam int unsigned WIDTH = fpnew_pkg::maximum(fpnew_pkg::max_fp_width(FpFmtConfig),
                                                     fpnew_pkg::max_int_width(IntFmtConfig))
)(
  input  logic                   clk_i    ,
  input  logic                   rst_ni   ,
  input  logic                   clear_i  ,
  input  logic                   cast_i   ,
  input  logic [DATA_W-1:0]      src_i    ,
  input  fpnew_pkg::fp_format_e  src_fmt_i,
  output logic [DATA_W-1:0]      dst_o
);

localparam int unsigned NUM_CAST = DATA_W/BITW;

logic [DATA_W-1:0] src_int;

assign src_int[DATA_W-DW_CUT-1:0] = src_i[DATA_W-DW_CUT-1:0];
assign src_int[DATA_W-1:DATA_W-DW_CUT] = '0;

logic [DATA_W-1:0] dst_int;
logic [NUM_CAST-1:0][WIDTH-1:0] result ,
                                operand;

generate
  for (genvar i = 0; i < NUM_CAST; i++) begin : gen_cast_units

    assign operand [i] = {{ZEROBITS{1'b0}}, src_int[i*MIN_FMT+:MIN_FMT]};

    fpnew_cast_multi #(
      .FpFmtConfig    ( FpFmtConfig  ),
      .IntFmtConfig   ( IntFmtConfig )
    ) redmule_cast_i  (
      .clk_i          ( clk_i          ),
      .rst_ni         ( rst_ni         ),
      .operands_i     ( operand [i]    ),
      .is_boxed_i     ( '1             ),
      .rnd_mode_i     ( fpnew_pkg::RNE ),
      .op_i           ( Operation      ),
      .op_mod_i       ( '0             ),
      .src_fmt_i      ( src_fmt_i      ),
      .dst_fmt_i      ( DstFormat      ),
      .int_fmt_i      ( INT_SRC        ),
      .tag_i          ( '0             ),
      .mask_i         ( '0             ),
      .aux_i          ( '0             ),
      .in_valid_i     ( '1             ),
      .in_ready_o     (                ),
      .flush_i        ( '0             ),
      .result_o       ( result [i]     ),
      .status_o       (                ),
      .extension_bit_o(                ),
      .tag_o          (                ),
      .mask_o         (                ),
      .aux_o          (                ),
      .out_valid_o    (                ),
      .out_ready_i    ( '1             ),
      .busy_o         (                )
    );

    assign  dst_int [i*WIDTH+:WIDTH] = result[i];

  end

endgenerate

assign dst_o = cast_i ? dst_int : src_i;

endmodule : redmule_castin

localparam int unsigned NARRBITW = fpnew_pkg::fp_width(fpnew_pkg::FP8);
// localparam int unsigned ZEROBITS = WIDTH - NARRBITW;
localparam int unsigned ZEROBITS = MIN_FMT;


//////////////////////////////////////////////////////////////////////////////
//  Copyright 2014 Dov Stamler (dov.stamler@gmail.com)
//
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
//////////////////////////////////////////////////////////////////////////////

`ifndef I2C_MASTER_DRIVER__SV
`define I2C_MASTER_DRIVER__SV

// Class: i2c_master_driver
// Master driver begins driving an I2C transaction when an <i2c_sequence_item> is received from the
// agents sequencer and the I2C bus is not busy. When the bus is busy, the driver will wait for the
// bus to release and then begin the transaction. The pin wiggles are a function
// of the current sequence item and the agents <i2c_master_cfg> objects members values.
class i2c_master_driver extends uvm_driver #(i2c_sequence_item);
    `uvm_component_utils(i2c_master_driver)

    virtual i2c_if      sigs;
    i2c_master_cfg      cfg;
    i2c_common_methods  common_mthds;                         // object holding common methods used by multiple I2C components

    bit                 bus_is_busy;                          // set on a start detection, dropped on a stop detection
    bit                 stop_scl;                             // used to notify SCL thread to terminate
    bit                 abritration_current_drive_value;      // arbitration process uses this to compare current to bus value
    bit                 abritration_checking_enabled;         // only when driving the bus should the arbitration be checking
    event               start_detection_e;                    // triggered on a start detection
    event               stop_detection_e;                     // triggered on a stop detection

    // bus timing values represented in clocking block cycles
    int                 num_of_clocks_for_scl_high_period;    // calculated number of clock cycles for a SCL high period
    int                 num_of_clocks_for_scl_low_period;     // calculated number of clock cycles for a SCL low period
    int                 num_of_clocks_for_t_hd_sta_min;       // start hold time before SCL toggle
    int                 num_of_clocks_for_t_hd_dat_max;       // data hold time from SCL negedge
    int                 num_of_clocks_for_t_su_dat_min;       // data setup time to SCL posedge
    int                 num_of_clocks_for_t_su_sta_min;       // repeated start SDA toggle from SCL negedge
    int                 num_of_clocks_for_t_su_sto_min;       // setup time from SCL posedge to SDA assert
    int                 num_of_clocks_for_t_buf_min;          // buffer time between stop and start conditions

    extern function              new(string name = "i2c_master_driver", uvm_component parent);
    extern virtual function void build_phase(uvm_phase phase);
    extern virtual task          run_phase(uvm_phase phase);
    extern virtual task          monitor_for_start_condition();
    extern virtual task          monitor_for_stop_condition();
    extern virtual task          report_if_bus_is_busy();
    extern virtual task          calculate_closest_scl_frequency_to_configuration();
    extern virtual task          calculate_all_bus_timing_variables_in_num_of_clocks();
    extern virtual task          drive_transaction();
    extern virtual task          toggle_scl();
    extern virtual task          create_start_condition(uvm_phase phase);
    extern virtual task          create_stop_condition(uvm_phase phase);
    extern virtual task          transmit_address();
    extern virtual task          get_slave_ack(output logic ack);
    extern virtual task          setup_for_a_continuous_start();
    extern virtual task          transmit_write_data();
    extern virtual task          receive_read_data();
    extern virtual task          transmit_ack_for_read(bit ack = 0);
    extern virtual task          drive_data_bit_to_sda(logic data_bit);
    extern virtual task          check_if_arbitration_is_lost(output logic arbitration_lost);

endclass: i2c_master_driver

//------------------------------------------------------------------------//
function i2c_master_driver::new(string name = "i2c_master_driver", uvm_component parent);
  super.new(name, parent);

endfunction: new

//------------------------------------------------------------------------//
function void i2c_master_driver::build_phase(uvm_phase phase);
  super.build_phase(phase);

  //set initial values
  bus_is_busy                     = 0;
  abritration_current_drive_value = 0;
  abritration_checking_enabled    = 0;

  common_mthds = i2c_common_methods::type_id::create("common_mthds", this);
  common_mthds.sigs = sigs;

endfunction: build_phase

//------------------------------------------------------------------------//
// task: run_phase
// run phase is called by UVM flow. Driver is active during this phase.
task i2c_master_driver::run_phase(uvm_phase phase);
  process         thread_process[$];
  int             thread_number                               = 0;
  bit             drive_thread_check_if_arbitration_was_lost  = 0;
  super.run_phase(phase);

  common_mthds.calculate_input_clock_period();// set the clocking block period for the common_mthds object, must be done in the run_phase to guarantee clock is toggling
  calculate_all_bus_timing_variables_in_num_of_clocks();
  calculate_closest_scl_frequency_to_configuration();

  fork
    forever common_mthds.drive_x_to_outputs_during_reset();
    forever monitor_for_start_condition(); // used to verify if bus is free
    forever monitor_for_stop_condition();  // used to verify if bus is free
    forever report_if_bus_is_busy();

    forever begin
      fork
        begin // drive thread
          thread_process[thread_number] = process::self();

          if(drive_thread_check_if_arbitration_was_lost) drive_thread_check_if_arbitration_was_lost = 0; // use the previously item since it wasn't transmitted

          wait(!bus_is_busy);
          do begin

            create_start_condition( .phase(phase) );
            drive_transaction();
            req.print();

            seq_item_port.item_done();
            seq_item_port.try_next_item(req); // if another item is ready process it now, create a continuous start
          end
          while(req);

          create_stop_condition( .phase(phase) );

        end

        // termination thread. terminate the drive thread if arbitration is lost.
        // terminate this thread once the drive thread has completed
        begin
          int wait_for_thread_number = thread_number;
          logic arbitration_lost = '0;

          while(!arbitration_lost &&
                (thread_process[wait_for_thread_number].status != process::FINISHED) ) check_if_arbitration_is_lost( .arbitration_lost(arbitration_lost) );

          if (thread_process[wait_for_thread_number].status != process::FINISHED) thread_process[wait_for_thread_number].kill();
          if (arbitration_lost) begin
            `uvm_info(get_type_name(),  $sformatf("arbitration has been lost"), UVM_NONE )
            drive_thread_check_if_arbitration_was_lost = 1; //notify the drive thread so the next round won't pull a new item from the sequencer
          end
        end

      join_any

      thread_number++;

    end
  join

endtask: run_phase

//------------------------------------------------------------------------//
// monitor if a different master created a start condition. This is used
// to determine if the bus is busy.
task i2c_master_driver::monitor_for_start_condition();

  common_mthds.monitor_for_start_condition( .start_e(start_detection_e) );
  if(start_detection_e.triggered) `uvm_info(get_type_name(),  $sformatf("Start detected"), UVM_FULL )

endtask: monitor_for_start_condition

//------------------------------------------------------------------------//
// monitor if a different master created a stop condition. used to determine when the bus is clear.
task i2c_master_driver::monitor_for_stop_condition();

  common_mthds.monitor_for_stop_condition( .stop_e(stop_detection_e) );
  if(stop_detection_e.triggered) `uvm_info(get_type_name(),  $sformatf("Stop detected"), UVM_FULL )

endtask: monitor_for_stop_condition

//------------------------------------------------------------------------//
// raise bus_is_busy on a start condition, drop bus_is_busy on a stop condition.
// bus is busy only after t_hd time.
task i2c_master_driver::report_if_bus_is_busy();

  wait(start_detection_e.triggered);
  repeat(num_of_clocks_for_t_hd_sta_min) @(sigs.drv_cb);
  bus_is_busy = 1;
  `uvm_info(get_type_name(),  $sformatf("bus busy set"), UVM_FULL )

  wait(stop_detection_e.triggered);
  repeat(num_of_clocks_for_t_buf_min) @(sigs.drv_cb); // don't release the bus for the buffer time between a start and stop
  bus_is_busy = 0;
 `uvm_info(get_type_name(),  $sformatf("bus busy cleared"), UVM_FULL )

endtask: report_if_bus_is_busy

//------------------------------------------------------------------------//
// the requested SCL frequency is an exact number where the driver works with
// a clocking block. calculate the closest frequency value to the requested SCL frequency in clock cycles.
task i2c_master_driver::calculate_closest_scl_frequency_to_configuration();
  int      num_of_input_clock_for_scl   = 0;
  realtime requested_period             = 0;

  requested_period = 1s / (1000 * cfg.requested_scl_frequency_in_khz); // convert from KHz to seconds
  num_of_input_clock_for_scl = common_mthds.calculate_number_of_clocks_for_time( .time_value(requested_period) );

  //set values used by SCL creation task, for an odd number of cycles, split the high and low period to different values
  if (num_of_input_clock_for_scl % 2) begin
    num_of_clocks_for_scl_high_period = (num_of_input_clock_for_scl - 1) /2;
    num_of_clocks_for_scl_low_period  = (num_of_input_clock_for_scl) /2;
  end
  else begin
    num_of_clocks_for_scl_high_period = (num_of_input_clock_for_scl) /2;
    num_of_clocks_for_scl_low_period  = (num_of_input_clock_for_scl) /2;
  end

  `uvm_info(get_type_name(),  $sformatf("SCL: number of clocks per period = %0d, closest period = %0t", num_of_input_clock_for_scl, num_of_input_clock_for_scl * common_mthds.input_clock_period_in_ps), UVM_MEDIUM )
  `uvm_info(get_type_name(),  $sformatf("SCL: closest frequency = %0d KHz", 1s/( 1000* num_of_input_clock_for_scl * common_mthds.input_clock_period_in_ps * 1ps) ), UVM_MEDIUM )

endtask: calculate_closest_scl_frequency_to_configuration

//------------------------------------------------------------------------//
// bus timing is represent in exact time value. driver drives bus with a clocking
// block therefore, calculate the closest times for each variable based on the
// clocking block period.
// min values are not floored since then the requested value won't be met.
task i2c_master_driver::calculate_all_bus_timing_variables_in_num_of_clocks();

  num_of_clocks_for_t_hd_sta_min = common_mthds.calculate_number_of_clocks_for_time( .time_value(cfg.t_hd_sta_min), .floor_calculation(0) );
  num_of_clocks_for_t_hd_dat_max = common_mthds.calculate_number_of_clocks_for_time( .time_value(cfg.t_hd_dat_max), .floor_calculation(1) );
  num_of_clocks_for_t_su_dat_min = common_mthds.calculate_number_of_clocks_for_time( .time_value(cfg.t_su_dat_min), .floor_calculation(0) );
  num_of_clocks_for_t_su_sta_min = common_mthds.calculate_number_of_clocks_for_time( .time_value(cfg.t_su_sta_min), .floor_calculation(0) );
  num_of_clocks_for_t_su_sto_min = common_mthds.calculate_number_of_clocks_for_time( .time_value(cfg.t_su_sto_min), .floor_calculation(0) );
  num_of_clocks_for_t_buf_min    = common_mthds.calculate_number_of_clocks_for_time( .time_value(cfg.t_buf_min),    .floor_calculation(0) );

  `uvm_info(get_type_name(),  $sformatf("num_of_clocks_for_t_hd_sta_min = %d", num_of_clocks_for_t_hd_sta_min) , UVM_FULL )
  `uvm_info(get_type_name(),  $sformatf("num_of_clocks_for_t_hd_dat_max = %d", num_of_clocks_for_t_hd_dat_max) , UVM_FULL )
  `uvm_info(get_type_name(),  $sformatf("num_of_clocks_for_t_su_dat_min = %d", num_of_clocks_for_t_su_dat_min) , UVM_FULL )
  `uvm_info(get_type_name(),  $sformatf("num_of_clocks_for_t_su_sta_min = %d", num_of_clocks_for_t_su_sta_min) , UVM_FULL )
  `uvm_info(get_type_name(),  $sformatf("num_of_clocks_for_t_su_sto_min = %d", num_of_clocks_for_t_su_sto_min) , UVM_FULL )
  `uvm_info(get_type_name(),  $sformatf("num_of_clocks_for_t_buf_min    = %d", num_of_clocks_for_t_buf_min) ,    UVM_FULL )

endtask:calculate_all_bus_timing_variables_in_num_of_clocks

//------------------------------------------------------------------------//
task i2c_master_driver::drive_transaction();
  logic ack = 1;
  stop_scl  = 0;

  `uvm_info(get_type_name(),  $sformatf("drive_transaction start"), UVM_FULL )

  fork // creating start condition has completed previously, begin SCL toggle
    toggle_scl();
  join_none

  transmit_address();
  get_slave_ack( .ack(ack) );
  if (ack === 1'b0) begin //0 = ACK, 1 = NACK
    case(req.direction_e)
      I2C_DIR_WRITE: transmit_write_data();
      I2C_DIR_READ:  receive_read_data();
      default:       `uvm_error(get_type_name(),  $sformatf("requested %s direction is not supported", req.direction_e.name() ) )
    endcase
  end

endtask: drive_transaction

//------------------------------------------------------------------------//
task i2c_master_driver::toggle_scl();
 `uvm_info(get_type_name(),  $sformatf("toggle_scl start"), UVM_NONE )

  @(sigs.drv_cb); //synchronize to current clock
  while(!stop_scl) begin
    sigs.drv_cb.scl_out <= 1'b0;
    repeat(num_of_clocks_for_scl_low_period) @(sigs.drv_cb);

    sigs.drv_cb.scl_out <= 1'b1;
    wait(sigs.drv_cb.scl_in === 1'b1); // if the slave stretches the clock, wait for it to release
    repeat(num_of_clocks_for_scl_high_period) @(sigs.drv_cb);
  end

  stop_scl = 0;

  `uvm_info(get_type_name(),  $sformatf("toggle_scl end"), UVM_NONE )
endtask: toggle_scl

//------------------------------------------------------------------------//
task i2c_master_driver::create_start_condition(uvm_phase phase);
  `uvm_info(get_type_name(),  $sformatf("create_start_condition start"), UVM_FULL )

  if (bus_is_busy) setup_for_a_continuous_start();
  else             phase.raise_objection(this); // when grabbing the bus, raise objection

  if (sigs.drv_cb.scl_in !== 1'b1) `uvm_fatal(get_type_name(),  $sformatf("creating start condition but SCL is not high") )
  sigs.drv_cb.sda_out <= 1'b0;

  repeat(num_of_clocks_for_t_hd_sta_min) @(sigs.drv_cb);

  `uvm_info(get_type_name(),  $sformatf("create_start_condition end"), UVM_FULL )
endtask: create_start_condition

//------------------------------------------------------------------------//
task i2c_master_driver::create_stop_condition(uvm_phase phase);

  wait(sigs.drv_cb.scl_in === 1'b0);
  repeat(num_of_clocks_for_t_hd_dat_max) @(sigs.drv_cb);
  sigs.drv_cb.sda_out <= 1'b0; //prepare SDA to rise when clock is high

  wait(sigs.drv_cb.scl_in === 1'b1);
  repeat(num_of_clocks_for_t_su_sto_min) @(sigs.drv_cb);
  sigs.drv_cb.sda_out <= 1'b1;

  stop_scl = 1;

  repeat(num_of_clocks_for_t_buf_min) @(sigs.drv_cb);

  phase.drop_objection(this);

endtask: create_stop_condition

//------------------------------------------------------------------------//
task i2c_master_driver::transmit_address();

  for(int i = cfg.address_num_of_bits; i; i--) drive_data_bit_to_sda( .data_bit(req.address[i-1]) );
  drive_data_bit_to_sda( .data_bit( logic'(req.direction_e) ) );

endtask: transmit_address

//------------------------------------------------------------------------//
task i2c_master_driver::get_slave_ack(output logic ack);

  wait(sigs.drv_cb.scl_in === 1'b0); // wait for negedge where the slave drives the ack value
  wait(sigs.drv_cb.scl_in === 1'b1); // read the value when SCL is high
  ack = sigs.drv_cb.sda_in;

endtask:get_slave_ack

//------------------------------------------------------------------------//
task i2c_master_driver::setup_for_a_continuous_start();
  `uvm_info(get_type_name(),  $sformatf("setup_for_a_continuous_start start"), UVM_FULL )

  wait(sigs.drv_cb.scl_in === 1'b0);
  repeat(num_of_clocks_for_t_hd_dat_max) @(sigs.drv_cb);
  sigs.drv_cb.sda_out <= 1'b1; //prepare SDA to fall when clock is high

  stop_scl = 1; // SCL will be restarted after the continuous start is complete

  wait(sigs.drv_cb.scl_in === 1'b1);
  //repeat(num_of_clocks_for_scl_high_period) @(sigs.drv_cb); // TBD
  repeat(num_of_clocks_for_t_su_sta_min) @(sigs.drv_cb); //continuous start setup time

  `uvm_info(get_type_name(),  $sformatf("setup_for_a_continuous_start end"), UVM_FULL )
endtask: setup_for_a_continuous_start

//------------------------------------------------------------------------//
task i2c_master_driver::transmit_write_data();
  logic ack;

  for(int data_word = 0; data_word < req.data.size(); data_word++) begin
    // transmit current data word 1 bit at a time MSB to LSB, data is always 8 bit
    for(int i = 8; i ; i--)  drive_data_bit_to_sda( .data_bit(req.data[data_word][i-1]) );

    get_slave_ack( .ack(ack) ); // get the ack from the slave for each data word
    if (ack === 1'b1) break;    // received a NACK, stop transmitting data words
  end

endtask: transmit_write_data

//------------------------------------------------------------------------//
task i2c_master_driver::receive_read_data();
  int         number_of_read_words = req.data.size();
  logic [7:0] received_data        = '0;

  if (number_of_read_words === 0) `uvm_error(get_type_name(),  $sformatf("number_of_read_words = %0d", number_of_read_words) )
  req.data.delete(); //remove any data that exists so that only data received will be in the data queue

  for(int current_read_word = 0; current_read_word < number_of_read_words; current_read_word++) begin

    // if the master previously responded with an ACK, release the SDA line here for the next read word
    // so the slave won't be blocked for transmission.
    if (sigs.drv_cb.sda_in === 1'b0) begin
      wait(sigs.drv_cb.scl_in === 1'b0);
      repeat(num_of_clocks_for_t_hd_dat_max) @(sigs.drv_cb);
      sigs.drv_cb.sda_out <= 1'b1;
    end

    // get data from slave
    for(int i = 8; i ; i--) begin
      wait(sigs.drv_cb.scl_in === 1'b0);
      wait(sigs.drv_cb.scl_in === 1'b1);
      req.data[current_read_word][i-1] = sigs.drv_cb.sda_in;
      `uvm_info(get_type_name(),  $sformatf("i = %0d, sigs.drv_cb.sda_in = %0h, req.data[%0d] = %0h", i, sigs.drv_cb.sda_in, current_read_word,req.data[current_read_word]), UVM_FULL )
    end

    if ( (current_read_word+1) !== number_of_read_words)  transmit_ack_for_read( .ack(0) );
    else                                                  transmit_ack_for_read( .ack(1) ); // last read word, return NACK

    `uvm_info(get_type_name(),  $sformatf("req.data[%0d] = %0h", current_read_word, req.data[current_read_word]), UVM_NONE )
  end

endtask: receive_read_data

//------------------------------------------------------------------------//
task i2c_master_driver::transmit_ack_for_read(bit ack = 0);
  drive_data_bit_to_sda( .data_bit(ack) );
endtask: transmit_ack_for_read

//------------------------------------------------------------------------//
// data is driven on the SDA only when the SCL is low and after the t_hd_dat.
// t_hd_dat moves the data transition from the SCL falling edge.
task i2c_master_driver::drive_data_bit_to_sda(logic data_bit);
  abritration_checking_enabled = 1; // checking arbitration only when data is driven to the bus by the driver

  wait(sigs.drv_cb.scl_in === 1'b0);
  repeat(num_of_clocks_for_t_hd_dat_max) @(sigs.drv_cb);
  sigs.drv_cb.sda_out             <= data_bit;
  abritration_current_drive_value  = data_bit;
  wait(sigs.drv_cb.scl_in === 1'b1);

  abritration_checking_enabled = 0;
endtask: drive_data_bit_to_sda

//------------------------------------------------------------------------//
task i2c_master_driver::check_if_arbitration_is_lost(output logic arbitration_lost);
  arbitration_lost = '0;
  `uvm_info(get_type_name(),  $sformatf("check_if_arbitration_is_lost start"), UVM_FULL )

  wait(sigs.drv_cb.scl_in === 1'b0);
  wait(sigs.drv_cb.scl_in === 1'b1);
  if (abritration_checking_enabled) begin //arbitration is verified when SCL is high
    `uvm_info(get_type_name(),  $sformatf("sigs.drv_cb.sda_in = %0h, arbitration_current_drive_value = %0h", sigs.drv_cb.sda_in, abritration_current_drive_value), UVM_FULL )
    if(sigs.drv_cb.sda_in !== abritration_current_drive_value) arbitration_lost = 1'b1;
  end

endtask: check_if_arbitration_is_lost

`endif //I2C_MASTER_DRIVER__SV

else                                           seq_item_port.get_next_item(req); //wait for a sequence item from the sequencer


`timescale 1 ns/1 ns

module merge(
    input  wire        rst,
    input  wire        clk,
    input  wire        i_et,
    input  wire        i_vl  [1:8],
    input  wire [ 4:0] i_oc  [1:8],
    input  wire [14:0] i_pv  [1:8],
    input  wire [ 3:0] i_pc  [1:8],
    input  wire [ 4:0] i_zc  [1:8],
    input  wire [ 8:0] i_bv  [1:8],
    input  wire [ 3:0] i_bc  [1:8],
    output reg         o_vl  [1:8],
    output reg  [ 4:0] o_oc  [1:8],
    output reg  [14:0] o_pv  [1:8],
    output reg  [ 3:0] o_pc  [1:8],
    output reg  [ 4:0] o_zc  [1:8],
    output reg  [ 8:0] o_bv  [1:8],
    output reg  [ 3:0] o_bc  [1:8]
);

reg        a_vl [1:7];
reg [ 4:0] a_oc [1:7];
reg [14:0] a_pv [1:7];
reg [ 3:0] a_pc [1:7];
reg [ 4:0] a_zc [1:7];
reg [ 8:0] a_bv [1:7];
reg [ 3:0] a_bc [1:7];

always @ (posedge clk) begin
    for(int i=1; i<=7; i++) begin
        if(rst) begin
            a_vl[i] <= 1'b0;
            o_vl[i] <= 1'b0;
        end else if(i_et) begin
            a_vl[i] <= 1'b0;
            o_vl[i] <= a_vl[i] | i_vl[i];
            o_oc[i] <= i_vl[i] ? i_oc[i] : a_oc[i];
            o_pv[i] <= i_vl[i] ? i_pv[i] : a_pv[i];

            o_pc[i] <= i_vl[i] ? i_pc[i] : a_pc[i];
            o_zc[i] <= i_vl[i] ? i_zc[i] : a_zc[i];
            o_bv[i] <= i_vl[i] ? i_bv[i] : a_bv[i];
            o_bc[i] <= i_vl[i] ? i_bc[i] : a_bc[i];
        end else if(i_vl[i]) begin


module csi2_crc_calc
(
  input                 clk_i,
  input                 rst_i,
  input  [31 : 0]       tdata_i,
  input  [3 : 0]        tstrb_i,
  input                 tvalid_i,
  input                 tlast_i,
  output logic          crc_passed_o,
  output logic          crc_failed_o
);

localparam int CSI2_CRC_POLY = 16'h1021;

logic [15 : 0] main_crc;
logic [15 : 0] crc_8bit;
logic [15 : 0] crc_8bit_prev;
logic [15 : 0] crc_16bit;
logic [15 : 0] crc_16bit_prev;
logic [15 : 0] crc_24bit;
logic [15 : 0] crc_24bit_prev;
logic          payload_in_progress;
logic          long_pkt_payload_valid;
logic [31 : 0] long_pkt_payload;
logic          long_pkt_eop;
logic          long_pkt_eop_d1;
logic          crc_passed;
logic          crc_failed;

assign long_pkt_payload       = tdata_i;
assign long_pkt_payload_valid = tvalid_i && payload_in_progress;
assign long_pkt_eop           = tlast_i && payload_in_progress;

always_ff @( posedge clk_i, posedge rst_i )
  if( rst_i )
    payload_in_progress <= '0;
  else
    if( !payload_in_progress && tvalid_i &&
        tdata_i[7 : 0] > 8'hf )
      payload_in_progress <= 1'b1;
    else
      if( payload_in_progress && tvalid_i &&
          tlast_i )
        payload_in_progress <= 1'b0;

always_ff @( posedge clk_i, posedge rst_i )
  if( rst_i )
    long_pkt_eop_d1 <= 1'b0;
  else
    long_pkt_eop_d1 <= long_pkt_eop;

crc_calc #(
  .POLY         ( CSI2_CRC_POLY          ),
  .CRC_SIZE     ( 16                     ),
  .DATA_WIDTH   ( 32                     ),
  .INIT         ( 16'hffff               ),
  .REF_IN       ( 1                      ),
  .REF_OUT      ( 1                      ),
  .XOR_OUT      ( 16'h0                  )
) main_calc (
  .clk_i        ( clk_i                  ),
  .rst_i        ( rst_i                  ),
  .soft_reset_i ( long_pkt_eop_d1        ),
  .valid_i      ( long_pkt_payload_valid ),
  .data_i       ( long_pkt_payload       ),
  .crc_o        ( main_crc               )
);

always_comb
  begin
    crc_8bit      = main_crc;
    crc_8bit_prev = main_crc;
    for( int i = 0; i < 8; i++ )
      begin
        crc_8bit[15] = crc_8bit_prev[0] ^ long_pkt_payload[i];
        for( int j = 1; j < 16; j++ )
          if( CSI2_CRC_POLY[j] )
            crc_8bit[15 - j] = crc_8bit_prev[16 - j] ^ crc_8bit_prev[0] ^
                               long_pkt_payload[i];
          else
            crc_8bit[15 - j] = crc_8bit_prev[16 - j];
        crc_8bit_prev = crc_8bit;
      end
  end

always_comb
  begin
    crc_16bit      = main_crc;
    crc_16bit_prev = main_crc;
    for( int i = 0; i < 16; i++ )
      begin
        crc_16bit[15] = crc_16bit_prev[0] ^ long_pkt_payload[i];
        for( int j = 1; j < 16; j++ )
          if( CSI2_CRC_POLY[j] )
            crc_16bit[15 - j] = crc_16bit_prev[16 - j] ^ crc_16bit_prev[0] ^
                                long_pkt_payload[i];
          else
            crc_16bit[15 - j] = crc_16bit_prev[16 - j];
        crc_16bit_prev = crc_16bit;
      end
  end

always_comb

                               long_pkt_payload[i];
          else
            crc_24bit[15 - j] = crc_24bit_prev[16 - j];
        crc_24bit_prev = crc_24bit;
      end
  end

assign crc_passed = ( long_pkt_eop &&
                      ( ( tstrb_i == 4'b0001 && crc_8bit  == '0 ) ||
                        ( tstrb_i == 4'b0011 && crc_16bit == '0 ) ||
                        ( tstrb_i == 4'b0111 && crc_24bit == '0 ) ||
                        ( tstrb_i == 4'b1111 && main_crc  == '0 ) ) );

assign crc_failed = ( long_pkt_eop &&
                      ( ( tstrb_i == 4'b0001 && crc_8bit  != '0 ) ||
                        ( tstrb_i == 4'b0011 && crc_16bit != '0 ) ||
                        ( tstrb_i == 4'b0111 && crc_24bit != '0 ) ||
                        ( tstrb_i == 4'b1111 && main_crc  != '0 ) ) );

always_ff @( posedge clk_i, posedge rst_i )
  if( rst_i )
    begin
      crc_passed_o <= '0;
      crc_failed_o <= '0;
    end
  else
    begin
      crc_passed_o <= crc_passed;
      crc_failed_o <= crc_failed;
    end

endmodule

  begin
    crc_24bit      = main_crc;
    crc_24bit_prev = main_crc;
    for( int i = 0; i < 24; i++ )
      begin


module mux4 (input logic [31:0] d0, d1, d2, d3, input logic [1:0] s,
			output logic [31:0] y);
always_comb begin
	case(s)


`include "../constants_local.sv"
`include "../constants.sv"

`include "../Modules/SMCore/SPCore/ALU/ALU.sv"
`include "../Modules/SMCore/SPCore/RegisterFile/RegisterFile.sv"
`include "../Modules/SMCore/SPCore/Mux/Mux3x16.sv"

`include "../Modules/SMCore/SPCore/SPCore.sv"
`include "../Modules/SMCore/SPCore/N_SPCores.sv"

`include "../Modules/SMCore/Scheduler/PC/PC.sv"
`include "../Modules/SMCore/Scheduler/CU/CU.sv"
`include "../Modules/SMCore/Scheduler/PStack/PStack.sv"

`include "../Modules/SMCore/Scheduler/Scheduler.sv"
`include "../Modules/MemoryController/MemoryController_NCores.sv"

`include "../Modules/SMCore/SMCore.sv"

`include "../Modules/DataMemory/DataMemory.sv"
`include "../Modules/InstructionMemory/InstructionMemory.sv"

`timescale 1ns/10ps

module smcore_tb;

    //Filet to save memory content
    integer  mem_dumpfile;

    //Reset
    reg reset;
    initial begin
        reset=1; #5 reset=0; //reset PC register at the begining
    end

    //Clock
    parameter clk_period = 20;
	reg clk = 1'b0;
	always begin
		#(clk_period/2) clk <= !clk;
	end
    wire memclk;
    // assign memclk=~clk;

    wire  [`DATAMEM_ADDR_WIDTH-1:0]   DataAddress;
    wire  [`DATA_WORD_LENGTH-1:0]     DataToWrite;
    wire   [`DATA_WORD_LENGTH-1:0]     DataToRead;
    wire  DataMemWrEn;

    // Modules
    DataMemory DMem(memclk,DataMemWrEn,DataAddress,DataToWrite,DataToRead);
    InstructionMemory IMem(clk,inst_addr,inst);
    SMCore SMCore(inst_addr,inst,DataAddress,DataToWrite,DataToRead,DataMemWrEn, clk, reset);

    // Dump Variables to file
	initial begin
		$dumpfile("dump.vcd");
		$dumpvars(0,smcore_tb);
	end

    // Logging
    initial begin
        $monitor("DMem[0]= %d   DMem[1]= %d DMem[2]= %d   DMem[3]= %d \n ",DMem.RAM[0],DMem.RAM[1],DMem.RAM[2],DMem.RAM[3]);
    end

    //Finish simulation when there are no more instructions in the instruction memory
    always @(posedge clk) begin
        if (SMCore.Scheduler.CU.state == 19) begin //STATE_END

            // Save memory to file
            mem_dumpfile = $fopen("MemoryFiles/memory_out.hex","w"); // Change the "w" to "a" to append data to an existing file
            for (integer i = 0;i < 32;i = i + 1)
                $fdisplay(mem_dumpfile,"%d ",DMem.RAM[i]);

            //Finish
            $display("------------------------\nEnding Simulation \n------------------------\n");
            $finish;
        end
    end

endmodule

    assign memclk=clk;

    //Connections to Instruction Memory
    wire  [`INSTMEM_ADDR_WIDTH-1:0]   inst_addr;


`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 10/31/2018 09:33:27 PM
// Design Name:
// Module Name: CodeBlinker
// Project Name:
// Target Devices:
// Tool Versions:
// Description: Blinks LED based on value, and also keeps LED on for a minimum time if the OK signal flickers
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////

// !OK: On solid
// When OK goes high:
// (stays on dim for certain time)
// (blinks based on code)
// ('.' indicates some delay; '..' is twice the delay)
// 0: dim .... off
// 1: dim .... off .. on . off .. on . off .. [forever]
// 2: dim .... off .. on . off. on. off .. on . off. on. off .. [forever]

module CodeBlinker(
    input clk,
	input ok,
	input [2:0] code,
	output reg led
    );

	// If we know the input clock, we can use reasonable rates for LED blinking
	parameter IN_CLK_MHZ = 32'd100;

	// Defines
	localparam LED_ON = 1'b0;
	localparam LED_OFF = 1'b1;

    // Default values for outputs
	initial led = LED_ON;

	// Declare states
	localparam S_NOK = 0;     	// ok input is false- LED is ON
	localparam S_OFF = 1;	 	// Displaying code- off time
	localparam S_ON = 2;      	// Displaying code- on time
	localparam S_CYCLEWAIT = 3;  // Done displaying code- wait with LED off before repeating

	// Declare state register and other state variables
	reg	[2:0] state = S_NOK;
	reg [2:0] curCodeDisp = 0;

	// Divides incoming clock
	localparam BASE_DELAY = 32'd672000 * IN_CLK_MHZ;
	localparam DELAY_STRETCH = BASE_DELAY << 2; // Lower 2 bits must be 0 for LED to be on solid in state S_NOK
	localparam DELAY_BLINK = BASE_DELAY;
	localparam DELAY_CYCLE = BASE_DELAY << 1;
	reg signed [31:0] counter = DELAY_CYCLE;

	// Debouncing inputs
	reg s_ok;
	reg [2:0] s_code;

	// Output depends only on the state and the countdown counter
	always @(negedge clk)
	begin

		// Sample inputs/update outputs on negative edge. Logic happens on positive edge
		s_ok <= ok;
		s_code <= code;

		case (state)
			S_ON:
				led = LED_ON;

		    S_NOK:
				led = | counter[1:0]; // Only on 1/4 duty

			default:
				led = LED_OFF;
		endcase
	end

	always @(posedge clk)
	begin
		if (!s_ok)
			begin
				state <= S_NOK;
				counter <= DELAY_STRETCH;
			end
		else
			begin
				if (counter > 0)
					counter <= counter - 1;
				else
					begin

							S_NOK:
								begin
									state <= S_CYCLEWAIT;
								end

							S_OFF:
								begin
									counter <= DELAY_BLINK;
									curCodeDisp <= curCodeDisp - 1;

									if (0 == curCodeDisp)
										state <= S_CYCLEWAIT;
									else
										state <= S_ON;

								end

							S_ON:
								begin
									counter <= DELAY_BLINK;
									state <= S_OFF;
								end

							S_CYCLEWAIT: // Done blinking the code- capture the next code to blink here
								begin
									counter <= DELAY_CYCLE;
									state <= S_OFF;
									curCodeDisp <= s_code;
								end
						endcase

					end
			end
	end

endmodule


/**
* Copyright 2023 Francisco Marques & Zero-Day Labs, Lda
* SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1
*
* Author: F.Marques <fmarques_00@protonmail.com>
*/

module aplic_top
import aplic_pkg::*;
import imsic_pkg::*;
import imsic_protocol_pkg::*;
#(
   parameter aplic_cfg_t                        AplicCfg                = DefaultAplicCfg,
   parameter imsic_cfg_t                        ImsicCfg                = DefaultImsicCfg,
   parameter protocol_cfg_t                     ProtocolCfg             = DefaultImsicProtocolCfg,
   parameter type                               reg_req_t               = logic ,
   parameter type                               reg_rsp_t               = logic ,
   parameter type                               axi_req_t               = logic ,
   parameter type                               axi_resp_t              = logic
) (
   input  logic                                                      i_clk             ,
   input  logic                                                      ni_rst            ,
   input  logic [AplicCfg.NrSources-1:0]                             i_irq_sources     ,
   /** APLIC domain interface */
   input  reg_req_t                                                  i_req_cfg         ,
   output reg_rsp_t                                                  o_resp_cfg        ,
   `ifdef MSI_MODE
   `ifdef AIA_EMBEDDED
   /** IMSIC island CSR interface */
   input  csr_channel_to_imsic_t     [ImsicCfg.NrHarts-1:0]          i_imsic_csr,
   output csr_channel_from_imsic_t   [ImsicCfg.NrHarts-1:0]          o_imsic_csr,
   /** IMSIC island AXI interface*/
   input   axi_req_t                                                 i_imsic_req       ,
   output  axi_resp_t                                                o_imsic_resp
   `elsif AIA_DISTRIBUTED
   output  axi_req_t                                                 o_msi_req,
   input   axi_resp_t                                                i_msi_rsp
   `endif
   `elsif DIRECT_MODE
   output logic        [AplicCfg.NrHarts-1:0]   o_eintp_cpu   [AplicCfg.NrDomains-1:0]
   `endif
); /** End of APLIC top interface */

   /**
   * A 2-level synchronyzer to avoid metastability in the irq line
   */
   logic [AplicCfg.NrSources-1:0]    sync_irq_src;
   synchronizer_multi_level #(
      .DataW     ( AplicCfg.NrSources ),
      .NrLevels  ( 2                  )
   ) synchronizer_multi_level_i (
      .i_clk     ( i_clk              ),
      .ni_rst    ( ni_rst             ),
      .data_i    ( i_irq_sources      ),
      .data_o    ( sync_irq_src       )
   );

   /** APLIC Domain with IMSIC island */
   aplic_domain_top #(
      .AplicCfg         ( AplicCfg           ),
      .ImsicCfg         ( ImsicCfg           ),
      .ProtocolCfg      ( ProtocolCfg        ),
      .reg_req_t        ( reg_req_t          ),
      .reg_rsp_t        ( reg_rsp_t          ),
      .axi_req_t        ( axi_req_t          ),
      .axi_resp_t       ( axi_resp_t         )
   ) i_aplic_generic_domain_top (
      .i_clk            ( i_clk              ),
      .ni_rst           ( ni_rst             ),
      .i_req_cfg        ( i_req_cfg          ),
      .o_resp_cfg       ( o_resp_cfg         ),
      .i_irq_sources    ( sync_irq_src       ),
      `ifdef MSI_MODE
      `ifdef AIA_EMBEDDED
      .i_imsic_csr      ( i_imsic_csr        ),
      .o_imsic_csr      ( o_imsic_csr        ),
      .i_imsic_req      ( i_imsic_req        ),
      .o_imsic_resp     ( o_imsic_resp       )
      `elsif AIA_DISTRIBUTED
      .o_msi_req        ( o_msi_req          ),

      `endif
      `elsif DIRECT_MODE
      .o_eintp_cpu      ( o_eintp_cpu        )
      `endif
   );

endmodule

.i_msi_rsp        ( i_msi_rsp          )


// Include definitions
`include "definitions.v"
   module rtl_top (input  Hclk,
                   input  Hresetn,
                   input  [1:0] Htrans,
                   input        [2:0]Hsize,
                   input        Hreadyin,
                   input        [`WIDTH-1:0]Hwdata,
                   input        [`WIDTH-1:0]Haddr,
                   input                Hwrite,
                   input        [`WIDTH-1:0]Prdata,
                   output       [`WIDTH-1:0]Hrdata,
                   output       [1:0]Hresp,
                   output       Hreadyout,
                   output       [`SLAVES-1:0]Pselx,
                   output       Pwrite,
                   output       Penable,
                   output  [`WIDTH-1:0] Paddr,
                   output  [`WIDTH-1:0] Pwdata
                    ) ;

       wire     valid,Pwrite_wire,Penable_wire,Hreadyout_wire;
       wire     [`WIDTH-1 : 0]  Pwdata_wire, Paddr_wire, Prdata_wire,inc_address,Haddr_reg_d1,Haddr_reg_d2,Haddr_reg_d3;
       wire     [`SLAVES-1 : 0] Pselx_out, Pselx_wire;
       wire     [`WIDTH-1:0] config_data;

      ahb AHB_SLAVE(Hclk,
                   Hresetn,
                   Htrans,
                   Hsize,
                   Hreadyin,
                   Hwdata,
                   Haddr,
                   Hwrite,
                   Hreadyout_wire,
                   Penable_wire,
                   Hresp,
                   Hreadyout,
                   Pselx_out,
                   valid,
                   config_data,
                   inc_address,Haddr_reg_d1,Haddr_reg_d2,Haddr_reg_d3) ;

                        Pselx_out[1],
                        Pselx_out[2],
                        Pselx_out[3],
                        Haddr_reg_d1,Haddr_reg_d2,Haddr_reg_d3,inc_address,
                        Htrans,
                        Hsize,
                        Hwdata,
                        Prdata_wire,
                        config_data,
                        Penable_wire,
                        Pwrite_wire,
                        Pselx_wire,
                        Paddr_wire,
                        Hreadyout_wire,
                        Pwdata_wire,
                        Hrdata);

    apb APB_MASTER(    Paddr_wire,
                       Penable_wire,
                       Pwrite_wire,
                       Pwdata_wire,
                       Pselx_wire,
                       Prdata,
                       Paddr,
                       Pwrite,
                       Penable,
                       Pwdata,
                       Pselx,
                       Prdata_wire );

 endmodule

     apb_controller FSM(Hclk,
                        Hresetn,
                        valid,


/* 1-bit I/Q modulator
 *
 * ω1: broadcast carrier at input 'adc'
 * ω2: local oscillator from DDS
 *
 * Tuned, when ω1 = ω2.
 *
 * I = cos(ω1∙t + θ)∙cos(ω2)
 * Q = cos(ω1∙t + θ)∙(-sin(ω2))
 */

module iq_modulator
  (input  wire               clk,
   input  wire               adc,
   input  wire  signed [1:0] phase,
   output logic signed [1:0] I, Q);

   /* I =  cos(phase) * ADC
    * Q = -sin(phase) * ADC
    */
   always_ff @(posedge clk)
     case (phase)
       2'b00:
         begin
            I <=  to_signed(adc);
            Q <= -to_signed(adc);
         end

       2'b01:
         begin
            I <= -to_signed(adc);
            Q <= -to_signed(adc);
         end

       2'b10:

       2'b11:
         begin
            I <= to_signed(adc);
            Q <= to_signed(adc);
         end
     endcase

   function logic signed [1:0] to_signed(input x);
      return 2 * x - 1;
   endfunction
endmodule

         begin
            I <= -to_signed(adc);
            Q <=  to_signed(adc);


/**
 * Package: aes128Pkg
 *
 * A package for the 128-bit version of the Advanced Encryption Standard (AES)
 * design. A couple of types, constants, and functions are defined herein,
 * which are used throughout the whole design.
 *
 * General Information:
 * File         - aes128Pkg.sv
 * Title        - AES-128 package
 * Project      - VLSI Book AES-128 Example
 * Author       - Michael Muehlberghuber (mbgh@iis.ee.ethz.ch)
 * Company      - Integrated Systems Laboratory, ETH Zurich
 * Copyright    - Copyright (C) 2014 Integrated Systems Laboratory, ETH Zurich
 * File Created - 2014-10-16
 * Last Updated - 2014-10-16
 * Platform     - Simulation=QuestaSim; Synthesis=Synopsys
 * Standard     - SystemVerilog 1800-2009
 *
 * Revision Control System Information:
 * File ID     - $Id: aes128Pkg.sv 33 2014-10-22 07:26:02Z u59323933 $
 * Revision    - $Revision: 33 $
 * Local Date  - $Date: 2014-10-22 09:26:02 +0200 (Wed, 22 Oct 2014) $
 * Modified By - $Author: u59323933 $
 *
 * Major Revisions:
 * 2014-10-16 (v1.0) - Created (mbgh)
 */

package aes128Pkg;

	// --------------------------------------------------------------------------
 	// Type definitions
	// --------------------------------------------------------------------------
	/**
	 * Type: Byte
	 * A synonym for a logic[7:0].
	 */
	typedef logic [7:0]		Byte;

	/**
	 * Type: Word
	 * A word made up of four <Bytes>.
	 */
	typedef Byte					Word [0:3];

	/**
	 * Type: Matrix
	 * A matrix made up of four <Words>.
	 */
	typedef Word        	Matrix [0:3];

	/**
	 * Type: roundkeyArrayType
	 * An array for holding 11 round keys (each of them represented using a
	 * logic[127:0]).
	 */
	typedef logic [127:0] roundkeyArrayType [0:10];

	// --------------------------------------------------------------------------
	// Functions
	// --------------------------------------------------------------------------

	/**
	 * Function: to_word
	 *
	 * Converts a Word to a logic[31:0].
	 */
	function automatic Word to_word;
		input logic [31:0] inp;
		Word result;
		begin
			result[0] = inp[31:24];
			result[1] = inp[23:16];
			result[2] = inp[15:8];
			result[3] = inp[7:0];
			to_word = result;
		end
	endfunction : to_word

	/**
	 * Function: shift_rows
	 *
	 * Shifts the rows of a provided Matrix as defined for AES.
	 */
	function automatic Matrix shift_rows;
		input Matrix inp;
		Matrix result;
		begin
			// First row
			result[0][0] = inp[0][0];
			result[1][0] = inp[1][0];
			result[2][0] = inp[2][0];
			result[3][0] = inp[3][0];

			// Second row
			result[0][1] = inp[1][1];
			result[1][1] = inp[2][1];
			result[2][1] = inp[3][1];
			result[3][1] = inp[0][1];

			// Third row
			result[0][2] = inp[2][2];
			result[1][2] = inp[3][2];
			result[2][2] = inp[0][2];
			result[3][2] = inp[1][2];

			// Fourth row
			result[0][3] = inp[3][3];
			result[1][3] = inp[0][3];

			result[3][3] = inp[2][3];

			shift_rows = result;
		end
	endfunction : shift_rows

	/**
	 * Function: xor_matrix_logic
	 *
	 * Perform an XOR operation given a Matrix and a logic[127:0].
	 */
	function automatic Matrix xor_matrix_logic;
		input Matrix left;
		input logic[127:0] right;
  	Matrix result;
		begin
			// First Column
			result[0][0] = left[0][0] ^ right[127:120];
			result[0][1] = left[0][1] ^ right[119:112];
			result[0][2] = left[0][2] ^ right[111:104];
			result[0][3] = left[0][3] ^ right[103:96];
			// Second Column
			result[1][0] = left[1][0] ^ right[95:88];
			result[1][1] = left[1][1] ^ right[87:80];
			result[1][2] = left[1][2] ^ right[79:72];
			result[1][3] = left[1][3] ^ right[71:64];
			// Third Column
			result[2][0] = left[2][0] ^ right[63:56];
			result[2][1] = left[2][1] ^ right[55:48];
			result[2][2] = left[2][2] ^ right[47:40];
			result[2][3] = left[2][3] ^ right[39:32];
			// Fourth Column
			result[3][0] = left[3][0] ^ right[31:24];
			result[3][1] = left[3][1] ^ right[23:16];
			result[3][2] = left[3][2] ^ right[15:8];
			result[3][3] = left[3][3] ^ right[7:0];

			xor_matrix_logic = result;
		end
	endfunction : xor_matrix_logic

endpackage : aes128Pkg