data/full_repos/permissive/218463548/hardware/sim/nvme_lite/nvme_top_i.sv
None: at end of input
1: b'%Error: data/full_repos/permissive/218463548/hardware/sim/nvme_lite/nvme_top_i.sv:17: Cannot find include file: snap_config.sv\n`include "snap_config.sv" \n         ^~~~~~~~~~~~~~~~\n        ... Looked in:\n             data/full_repos/permissive/218463548/hardware/sim/nvme_lite,data/full_repos/permissive/218463548/snap_config.sv\n             data/full_repos/permissive/218463548/hardware/sim/nvme_lite,data/full_repos/permissive/218463548/snap_config.sv.v\n             data/full_repos/permissive/218463548/hardware/sim/nvme_lite,data/full_repos/permissive/218463548/snap_config.sv.sv\n             snap_config.sv\n             snap_config.sv.v\n             snap_config.sv.sv\n             obj_dir/snap_config.sv\n             obj_dir/snap_config.sv.v\n             obj_dir/snap_config.sv.sv\n%Error: data/full_repos/permissive/218463548/hardware/sim/nvme_lite/nvme_top_i.sv:18: Cannot find include file: nvme_defines.sv\n`include "nvme_defines.sv" \n         ^~~~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/218463548/hardware/sim/nvme_lite/nvme_top_i.sv:240: Define or directive not defined: \'`ACTION_W_NUM_REGS\'\n    localparam ACTION_W_BITS = $clog2(`ACTION_W_NUM_REGS);\n                                      ^~~~~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/218463548/hardware/sim/nvme_lite/nvme_top_i.sv:240: syntax error, unexpected \')\', expecting TYPE-IDENTIFIER\n    localparam ACTION_W_BITS = $clog2(`ACTION_W_NUM_REGS);\n                                                        ^\n%Error: data/full_repos/permissive/218463548/hardware/sim/nvme_lite/nvme_top_i.sv:241: Define or directive not defined: \'`ACTION_R_NUM_REGS\'\n    localparam ACTION_R_BITS = $clog2(`ACTION_R_NUM_REGS);\n                                      ^~~~~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/218463548/hardware/sim/nvme_lite/nvme_top_i.sv:241: syntax error, unexpected \')\', expecting TYPE-IDENTIFIER\n    localparam ACTION_R_BITS = $clog2(`ACTION_R_NUM_REGS);\n                                                        ^\n%Error: data/full_repos/permissive/218463548/hardware/sim/nvme_lite/nvme_top_i.sv:242: Define or directive not defined: \'`TOTAL_NUM_QUEUES\'\n    localparam SQ_INDEX_BITS = $clog2(`TOTAL_NUM_QUEUES);\n                                      ^~~~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/218463548/hardware/sim/nvme_lite/nvme_top_i.sv:242: syntax error, unexpected \')\', expecting TYPE-IDENTIFIER\n    localparam SQ_INDEX_BITS = $clog2(`TOTAL_NUM_QUEUES);\n                                                       ^\n%Error: data/full_repos/permissive/218463548/hardware/sim/nvme_lite/nvme_top_i.sv:244: Define or directive not defined: \'`ACTION_W_NUM_REGS\'\n    logic [31:0] action_w_regs[`ACTION_W_NUM_REGS];\n                               ^~~~~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/218463548/hardware/sim/nvme_lite/nvme_top_i.sv:245: Define or directive not defined: \'`ACTION_R_NUM_REGS\'\n    logic [31:0] action_r_regs[`ACTION_R_NUM_REGS];\n                               ^~~~~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/218463548/hardware/sim/nvme_lite/nvme_top_i.sv:254: Define or directive not defined: \'`ACTION_R_STATUS\'\n    assign action_r_regs[`ACTION_R_STATUS][16] = action_r_regs[`ACTION_R_TRACK_0][0];\n                         ^~~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/218463548/hardware/sim/nvme_lite/nvme_top_i.sv:254: syntax error, unexpected \']\', expecting TYPE-IDENTIFIER\n    assign action_r_regs[`ACTION_R_STATUS][16] = action_r_regs[`ACTION_R_TRACK_0][0];\n                                         ^\n%Error: data/full_repos/permissive/218463548/hardware/sim/nvme_lite/nvme_top_i.sv:254: Define or directive not defined: \'`ACTION_R_TRACK_0\'\n    assign action_r_regs[`ACTION_R_STATUS][16] = action_r_regs[`ACTION_R_TRACK_0][0];\n                                                               ^~~~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/218463548/hardware/sim/nvme_lite/nvme_top_i.sv:255: Define or directive not defined: \'`ACTION_R_STATUS\'\n    assign action_r_regs[`ACTION_R_STATUS][17] = action_r_regs[`ACTION_R_TRACK_0 + 1][0];\n                         ^~~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/218463548/hardware/sim/nvme_lite/nvme_top_i.sv:255: syntax error, unexpected \']\', expecting TYPE-IDENTIFIER\n    assign action_r_regs[`ACTION_R_STATUS][17] = action_r_regs[`ACTION_R_TRACK_0 + 1][0];\n                                         ^\n%Error: data/full_repos/permissive/218463548/hardware/sim/nvme_lite/nvme_top_i.sv:255: Define or directive not defined: \'`ACTION_R_TRACK_0\'\n    assign action_r_regs[`ACTION_R_STATUS][17] = action_r_regs[`ACTION_R_TRACK_0 + 1][0];\n                                                               ^~~~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/218463548/hardware/sim/nvme_lite/nvme_top_i.sv:256: Define or directive not defined: \'`ACTION_R_STATUS\'\n    assign action_r_regs[`ACTION_R_STATUS][18] = action_r_regs[`ACTION_R_TRACK_0 + 2][0];\n                         ^~~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/218463548/hardware/sim/nvme_lite/nvme_top_i.sv:256: syntax error, unexpected \']\', expecting TYPE-IDENTIFIER\n    assign action_r_regs[`ACTION_R_STATUS][18] = action_r_regs[`ACTION_R_TRACK_0 + 2][0];\n                                         ^\n%Error: data/full_repos/permissive/218463548/hardware/sim/nvme_lite/nvme_top_i.sv:256: Define or directive not defined: \'`ACTION_R_TRACK_0\'\n    assign action_r_regs[`ACTION_R_STATUS][18] = action_r_regs[`ACTION_R_TRACK_0 + 2][0];\n                                                               ^~~~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/218463548/hardware/sim/nvme_lite/nvme_top_i.sv:257: Define or directive not defined: \'`ACTION_R_STATUS\'\n    assign action_r_regs[`ACTION_R_STATUS][19] = action_r_regs[`ACTION_R_TRACK_0 + 3][0];\n                         ^~~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/218463548/hardware/sim/nvme_lite/nvme_top_i.sv:257: syntax error, unexpected \']\', expecting TYPE-IDENTIFIER\n    assign action_r_regs[`ACTION_R_STATUS][19] = action_r_regs[`ACTION_R_TRACK_0 + 3][0];\n                                         ^\n%Error: data/full_repos/permissive/218463548/hardware/sim/nvme_lite/nvme_top_i.sv:257: Define or directive not defined: \'`ACTION_R_TRACK_0\'\n    assign action_r_regs[`ACTION_R_STATUS][19] = action_r_regs[`ACTION_R_TRACK_0 + 3][0];\n                                                               ^~~~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/218463548/hardware/sim/nvme_lite/nvme_top_i.sv:258: Define or directive not defined: \'`ACTION_R_STATUS\'\n    assign action_r_regs[`ACTION_R_STATUS][20] = action_r_regs[`ACTION_R_TRACK_0 + 4][0];\n                         ^~~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/218463548/hardware/sim/nvme_lite/nvme_top_i.sv:258: syntax error, unexpected \']\', expecting TYPE-IDENTIFIER\n    assign action_r_regs[`ACTION_R_STATUS][20] = action_r_regs[`ACTION_R_TRACK_0 + 4][0];\n                                         ^\n%Error: data/full_repos/permissive/218463548/hardware/sim/nvme_lite/nvme_top_i.sv:258: Define or directive not defined: \'`ACTION_R_TRACK_0\'\n    assign action_r_regs[`ACTION_R_STATUS][20] = action_r_regs[`ACTION_R_TRACK_0 + 4][0];\n                                                               ^~~~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/218463548/hardware/sim/nvme_lite/nvme_top_i.sv:259: Define or directive not defined: \'`ACTION_R_STATUS\'\n    assign action_r_regs[`ACTION_R_STATUS][21] = action_r_regs[`ACTION_R_TRACK_0 + 5][0];\n                         ^~~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/218463548/hardware/sim/nvme_lite/nvme_top_i.sv:259: syntax error, unexpected \']\', expecting TYPE-IDENTIFIER\n    assign action_r_regs[`ACTION_R_STATUS][21] = action_r_regs[`ACTION_R_TRACK_0 + 5][0];\n                                         ^\n%Error: data/full_repos/permissive/218463548/hardware/sim/nvme_lite/nvme_top_i.sv:259: Define or directive not defined: \'`ACTION_R_TRACK_0\'\n    assign action_r_regs[`ACTION_R_STATUS][21] = action_r_regs[`ACTION_R_TRACK_0 + 5][0];\n                                                               ^~~~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/218463548/hardware/sim/nvme_lite/nvme_top_i.sv:260: Define or directive not defined: \'`ACTION_R_STATUS\'\n    assign action_r_regs[`ACTION_R_STATUS][22] = action_r_regs[`ACTION_R_TRACK_0 + 6][0];\n                         ^~~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/218463548/hardware/sim/nvme_lite/nvme_top_i.sv:260: syntax error, unexpected \']\', expecting TYPE-IDENTIFIER\n    assign action_r_regs[`ACTION_R_STATUS][22] = action_r_regs[`ACTION_R_TRACK_0 + 6][0];\n                                         ^\n%Error: data/full_repos/permissive/218463548/hardware/sim/nvme_lite/nvme_top_i.sv:260: Define or directive not defined: \'`ACTION_R_TRACK_0\'\n    assign action_r_regs[`ACTION_R_STATUS][22] = action_r_regs[`ACTION_R_TRACK_0 + 6][0];\n                                                               ^~~~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/218463548/hardware/sim/nvme_lite/nvme_top_i.sv:261: Define or directive not defined: \'`ACTION_R_STATUS\'\n    assign action_r_regs[`ACTION_R_STATUS][23] = action_r_regs[`ACTION_R_TRACK_0 + 7][0];\n                         ^~~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/218463548/hardware/sim/nvme_lite/nvme_top_i.sv:261: syntax error, unexpected \']\', expecting TYPE-IDENTIFIER\n    assign action_r_regs[`ACTION_R_STATUS][23] = action_r_regs[`ACTION_R_TRACK_0 + 7][0];\n                                         ^\n%Error: data/full_repos/permissive/218463548/hardware/sim/nvme_lite/nvme_top_i.sv:261: Define or directive not defined: \'`ACTION_R_TRACK_0\'\n    assign action_r_regs[`ACTION_R_STATUS][23] = action_r_regs[`ACTION_R_TRACK_0 + 7][0];\n                                                               ^~~~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/218463548/hardware/sim/nvme_lite/nvme_top_i.sv:262: Define or directive not defined: \'`ACTION_R_STATUS\'\n    assign action_r_regs[`ACTION_R_STATUS][24] = action_r_regs[`ACTION_R_TRACK_0 + 8][0];\n                         ^~~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/218463548/hardware/sim/nvme_lite/nvme_top_i.sv:262: syntax error, unexpected \']\', expecting TYPE-IDENTIFIER\n    assign action_r_regs[`ACTION_R_STATUS][24] = action_r_regs[`ACTION_R_TRACK_0 + 8][0];\n                                         ^\n%Error: data/full_repos/permissive/218463548/hardware/sim/nvme_lite/nvme_top_i.sv:262: Define or directive not defined: \'`ACTION_R_TRACK_0\'\n    assign action_r_regs[`ACTION_R_STATUS][24] = action_r_regs[`ACTION_R_TRACK_0 + 8][0];\n                                                               ^~~~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/218463548/hardware/sim/nvme_lite/nvme_top_i.sv:263: Define or directive not defined: \'`ACTION_R_STATUS\'\n    assign action_r_regs[`ACTION_R_STATUS][25] = action_r_regs[`ACTION_R_TRACK_0 + 9][0];\n                         ^~~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/218463548/hardware/sim/nvme_lite/nvme_top_i.sv:263: syntax error, unexpected \']\', expecting TYPE-IDENTIFIER\n    assign action_r_regs[`ACTION_R_STATUS][25] = action_r_regs[`ACTION_R_TRACK_0 + 9][0];\n                                         ^\n%Error: data/full_repos/permissive/218463548/hardware/sim/nvme_lite/nvme_top_i.sv:263: Define or directive not defined: \'`ACTION_R_TRACK_0\'\n    assign action_r_regs[`ACTION_R_STATUS][25] = action_r_regs[`ACTION_R_TRACK_0 + 9][0];\n                                                               ^~~~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/218463548/hardware/sim/nvme_lite/nvme_top_i.sv:264: Define or directive not defined: \'`ACTION_R_STATUS\'\n    assign action_r_regs[`ACTION_R_STATUS][26] = action_r_regs[`ACTION_R_TRACK_0 + 10][0];\n                         ^~~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/218463548/hardware/sim/nvme_lite/nvme_top_i.sv:264: syntax error, unexpected \']\', expecting TYPE-IDENTIFIER\n    assign action_r_regs[`ACTION_R_STATUS][26] = action_r_regs[`ACTION_R_TRACK_0 + 10][0];\n                                         ^\n%Error: data/full_repos/permissive/218463548/hardware/sim/nvme_lite/nvme_top_i.sv:264: Define or directive not defined: \'`ACTION_R_TRACK_0\'\n    assign action_r_regs[`ACTION_R_STATUS][26] = action_r_regs[`ACTION_R_TRACK_0 + 10][0];\n                                                               ^~~~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/218463548/hardware/sim/nvme_lite/nvme_top_i.sv:265: Define or directive not defined: \'`ACTION_R_STATUS\'\n    assign action_r_regs[`ACTION_R_STATUS][27] = action_r_regs[`ACTION_R_TRACK_0 + 11][0];\n                         ^~~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/218463548/hardware/sim/nvme_lite/nvme_top_i.sv:265: syntax error, unexpected \']\', expecting TYPE-IDENTIFIER\n    assign action_r_regs[`ACTION_R_STATUS][27] = action_r_regs[`ACTION_R_TRACK_0 + 11][0];\n                                         ^\n%Error: data/full_repos/permissive/218463548/hardware/sim/nvme_lite/nvme_top_i.sv:265: Define or directive not defined: \'`ACTION_R_TRACK_0\'\n    assign action_r_regs[`ACTION_R_STATUS][27] = action_r_regs[`ACTION_R_TRACK_0 + 11][0];\n                                                               ^~~~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/218463548/hardware/sim/nvme_lite/nvme_top_i.sv:266: Define or directive not defined: \'`ACTION_R_STATUS\'\n    assign action_r_regs[`ACTION_R_STATUS][28] = action_r_regs[`ACTION_R_TRACK_0 + 12][0];\n                         ^~~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/218463548/hardware/sim/nvme_lite/nvme_top_i.sv:266: syntax error, unexpected \']\', expecting TYPE-IDENTIFIER\n    assign action_r_regs[`ACTION_R_STATUS][28] = action_r_regs[`ACTION_R_TRACK_0 + 12][0];\n                                         ^\n%Error: data/full_repos/permissive/218463548/hardware/sim/nvme_lite/nvme_top_i.sv:266: Define or directive not defined: \'`ACTION_R_TRACK_0\'\n    assign action_r_regs[`ACTION_R_STATUS][28] = action_r_regs[`ACTION_R_TRACK_0 + 12][0];\n                                                               ^~~~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/218463548/hardware/sim/nvme_lite/nvme_top_i.sv:267: Define or directive not defined: \'`ACTION_R_STATUS\'\n    assign action_r_regs[`ACTION_R_STATUS][29] = action_r_regs[`ACTION_R_TRACK_0 + 13][0];\n                         ^~~~~~~~~~~~~~~~\n%Error: Exiting due to too many errors encountered; --error-limit=50\n'
module nvme_top (

    input  wire ACT_NVME_ACLK,
    input  wire ACT_NVME_ARESETN,
    input  wire [31:0]ACT_NVME_AXI_araddr,
    input  wire [1:0]ACT_NVME_AXI_arburst,
    input  wire [3:0]ACT_NVME_AXI_arcache,
    input  wire [7:0]ACT_NVME_AXI_arlen,
    input  wire [0:0]ACT_NVME_AXI_arlock,
    input  wire [2:0]ACT_NVME_AXI_arprot,
    input  wire [3:0]ACT_NVME_AXI_arqos,
    output wire ACT_NVME_AXI_arready,
    input  wire [3:0]ACT_NVME_AXI_arregion,
    input  wire [2:0]ACT_NVME_AXI_arsize,
    input  wire ACT_NVME_AXI_arvalid,
    input  wire [31:0]ACT_NVME_AXI_awaddr,
    input  wire [1:0]ACT_NVME_AXI_awburst,
    input  wire [3:0]ACT_NVME_AXI_awcache,
    input  wire [7:0]ACT_NVME_AXI_awlen,
    input  wire [0:0]ACT_NVME_AXI_awlock,
    input  wire [2:0]ACT_NVME_AXI_awprot,
    input  wire [3:0]ACT_NVME_AXI_awqos,
    output wire ACT_NVME_AXI_awready,
    input  wire [3:0]ACT_NVME_AXI_awregion,
    input  wire [2:0]ACT_NVME_AXI_awsize,
    input  wire ACT_NVME_AXI_awvalid,
    input  wire ACT_NVME_AXI_bready,
    output wire [1:0]ACT_NVME_AXI_bresp,
    output wire ACT_NVME_AXI_bvalid,
    output wire [31:0]ACT_NVME_AXI_rdata,
    output wire ACT_NVME_AXI_rlast,
    input  wire ACT_NVME_AXI_rready,
    output wire [1:0]ACT_NVME_AXI_rresp,
    output wire ACT_NVME_AXI_rvalid,
    input  wire [31:0]ACT_NVME_AXI_wdata,
    input  wire ACT_NVME_AXI_wlast,
    output wire ACT_NVME_AXI_wready,
    input  wire [3:0]ACT_NVME_AXI_wstrb,
    input  wire ACT_NVME_AXI_wvalid,


    output wire [`DDR_M_ADDRBWIDTH-1:0]DDR_M_AXI_araddr,
    output wire [1:0]DDR_M_AXI_arburst,
    output wire [3:0]DDR_M_AXI_arcache,
    output wire [3:0]DDR_M_AXI_arid,
    output wire [7:0]DDR_M_AXI_arlen,
    output wire [0:0]DDR_M_AXI_arlock,
    output wire [2:0]DDR_M_AXI_arprot,
    output wire [3:0]DDR_M_AXI_arqos,
    input  wire [0:0]DDR_M_AXI_arready,
    output wire [3:0]DDR_M_AXI_arregion,
    output wire [2:0]DDR_M_AXI_arsize,
    output wire [0:0]DDR_M_AXI_arvalid,
    output wire [`DDR_M_ADDRBWIDTH-1:0]DDR_M_AXI_awaddr,
    output wire [1:0]DDR_M_AXI_awburst,
    output wire [3:0]DDR_M_AXI_awcache,
    output wire [3:0]DDR_M_AXI_awid,
    output wire [7:0]DDR_M_AXI_awlen,
    output wire [0:0]DDR_M_AXI_awlock,
    output wire [2:0]DDR_M_AXI_awprot,
    output wire [3:0]DDR_M_AXI_awqos,
    input  wire [0:0]DDR_M_AXI_awready,
    output wire [3:0]DDR_M_AXI_awregion,
    output wire [2:0]DDR_M_AXI_awsize,
    output wire [0:0]DDR_M_AXI_awvalid,
    input  wire [3:0]DDR_M_AXI_bid,
    output wire [0:0]DDR_M_AXI_bready,
    input  wire [1:0]DDR_M_AXI_bresp,
    input  wire [0:0]DDR_M_AXI_bvalid,
    input  wire [127:0]DDR_M_AXI_rdata,
    input  wire [3:0]DDR_M_AXI_rid,
    input  wire [0:0]DDR_M_AXI_rlast,
    output wire [0:0]DDR_M_AXI_rready,
    input  wire [1:0]DDR_M_AXI_rresp,
    input  wire [15:0]DDR_M_AXI_ruser,
    input  wire [0:0]DDR_M_AXI_rvalid,
    output wire [127:0]DDR_M_AXI_wdata,
    output wire [0:0]DDR_M_AXI_wlast,
    input  wire [0:0]DDR_M_AXI_wready,
    output wire [15:0]DDR_M_AXI_wstrb,
    output wire [15:0]DDR_M_AXI_wuser,
    output wire [0:0]DDR_M_AXI_wvalid,


    input  wire NVME_S_ACLK,
    input  wire NVME_S_ARESETN,
    input  wire [31:0]NVME_S_AXI_araddr,
    input  wire [2:0]NVME_S_AXI_arprot,
    output wire [0:0]NVME_S_AXI_arready,
    input  wire [0:0]NVME_S_AXI_arvalid,
    input  wire [31:0]NVME_S_AXI_awaddr,
    input  wire [2:0]NVME_S_AXI_awprot,
    output wire [0:0]NVME_S_AXI_awready,
    input  wire [0:0]NVME_S_AXI_awvalid,
    input  wire [0:0]NVME_S_AXI_bready,
    output wire [1:0]NVME_S_AXI_bresp,
    output wire [0:0]NVME_S_AXI_bvalid,
    output wire [31:0]NVME_S_AXI_rdata,
    input  wire [0:0]NVME_S_AXI_rready,
    output wire [1:0]NVME_S_AXI_rresp,
    output wire [0:0]NVME_S_AXI_rvalid,
    input  wire [31:0]NVME_S_AXI_wdata,
    output wire [0:0]NVME_S_AXI_wready,
    input  wire [3:0]NVME_S_AXI_wstrb,
    input  wire [0:0]NVME_S_AXI_wvalid,


    output wire ddr_aclk,
    output wire ddr_aresetn,
    input  wire nvme_reset_n,
    input  wire [3:0]pcie_rc0_rxn,
    input  wire [3:0]pcie_rc0_rxp,
    output wire [3:0]pcie_rc0_txn,
    output wire [3:0]pcie_rc0_txp,
    input  wire [3:0]pcie_rc1_rxn,
    input  wire [3:0]pcie_rc1_rxp,
    output wire [3:0]pcie_rc1_txn,
    output wire [3:0]pcie_rc1_txp,
    input  wire refclk_nvme_ch0_n,
    input  wire refclk_nvme_ch0_p,
    input  wire refclk_nvme_ch1_n,
    input  wire refclk_nvme_ch1_p
    );

`define CONFIG_DDR_READWRITE_TEST   0


    reg ACT_arready;
    reg [31:0] ACT_araddr;
    reg [31:0] ACT_rdata;
    reg [0:0] ACT_awready;
    reg [31:0] ACT_awaddr;
    reg [31:0] ACT_wdata;
    reg [0:0] ACT_wready;
    reg [0:0] ACT_bvalid;
    reg [1:0] ACT_bresp;
    reg [0:0] ACT_rvalid;
    reg [0:0] ACT_rlast;
    reg [1:0] ACT_rresp;


    reg DDR_aclk;
    reg DDR_aresetn;
    reg [3:0] DDR_arid;
    reg [7:0] DDR_awlen;
    reg [2:0] DDR_awsize;
    reg [1:0] DDR_awburst;
    reg [`DDR_M_ADDRBWIDTH-1:0] DDR_awaddr;
    reg [0:0] DDR_arvalid;
    reg [0:0] DDR_awvalid;
    reg [127:0] DDR_wdata;
    reg [15:0] DDR_wstrb;
    reg [0:0] DDR_wvalid;
    reg [3:0] DDR_awid;
    reg [7:0] DDR_arlen;
    reg [2:0] DDR_arsize;
    reg [`DDR_M_ADDRBWIDTH-1:0] DDR_araddr;
    reg [0:0] DDR_rready;
    reg [0:0] DDR_arlock;
    reg [0:0] DDR_wlast;
    reg [0:0] DDR_bready;
    reg [0:0] DDR_arburst;
    reg [0:0] DDR_awlock;
    reg [2:0] DDR_awprot;
    reg [2:0] DDR_arprot;
    reg [3:0] DDR_awqos;
    reg [3:0] DDR_arqos;
    reg [3:0] DDR_awcache;
    reg [3:0] DDR_arcache;
    reg [15:0] DDR_wuser;
    reg [3:0] DDR_awregion;
    reg [3:0] DDR_arregion;


    assign ACT_NVME_AXI_arready = ACT_arready;
    assign ACT_NVME_AXI_rdata = ACT_rdata;
    assign ACT_NVME_AXI_awready = ACT_awready;
    assign ACT_NVME_AXI_wready = ACT_wready;
    assign ACT_NVME_AXI_bvalid = ACT_bvalid;
    assign ACT_NVME_AXI_bresp = ACT_bresp;
    assign ACT_NVME_AXI_rvalid = ACT_rvalid;
    assign ACT_NVME_AXI_rresp = ACT_rresp;
    assign ACT_NVME_AXI_rlast = ACT_rlast;


    assign ddr_aclk = DDR_aclk;
    assign ddr_aresetn = DDR_aresetn;
    assign DDR_M_AXI_awid = DDR_awid;
    assign DDR_M_AXI_arid = DDR_arid;
    assign DDR_M_AXI_awlen = DDR_awlen;
    assign DDR_M_AXI_awsize = DDR_awsize;
    assign DDR_M_AXI_awburst = DDR_awburst;
    assign DDR_M_AXI_awaddr = DDR_awaddr[`DDR_M_ADDRBWIDTH-1:0];
    assign DDR_M_AXI_awvalid = DDR_awvalid;
    assign DDR_M_AXI_wdata = DDR_wdata;
    assign DDR_M_AXI_wstrb = DDR_wstrb;
    assign DDR_M_AXI_wvalid = DDR_wvalid;
    assign DDR_M_AXI_wlast = DDR_wlast;
    assign DDR_M_AXI_arvalid = DDR_arvalid;
    assign DDR_M_AXI_arlen = DDR_arlen;
    assign DDR_M_AXI_arsize = DDR_arsize;
    assign DDR_M_AXI_araddr = DDR_araddr[`DDR_M_ADDRBWIDTH-1:0];
    assign DDR_M_AXI_rready = DDR_rready;
    assign DDR_M_AXI_bready = DDR_bready;
    assign DDR_M_AXI_arburst = DDR_arburst;
    assign DDR_M_AXI_awlock = DDR_awlock;
    assign DDR_M_AXI_arlock = DDR_arlock;
    assign DDR_M_AXI_awprot = DDR_awprot;
    assign DDR_M_AXI_arprot = DDR_arprot;
    assign DDR_M_AXI_awqos = DDR_awqos;
    assign DDR_M_AXI_arqos = DDR_arqos;
    assign DDR_M_AXI_awcache = DDR_awcache;
    assign DDR_M_AXI_arcache = DDR_arcache;
    assign DDR_M_AXI_wuser = DDR_wuser;
    assign DDR_M_AXI_awregion = DDR_awregion;
    assign DDR_M_AXI_arregion = DDR_arregion;


    localparam ACTION_W_BITS = $clog2(`ACTION_W_NUM_REGS);
    localparam ACTION_R_BITS = $clog2(`ACTION_R_NUM_REGS);
    localparam SQ_INDEX_BITS = $clog2(`TOTAL_NUM_QUEUES);

    logic [31:0] action_w_regs[`ACTION_W_NUM_REGS];
    logic [31:0] action_r_regs[`ACTION_R_NUM_REGS];

    logic [ACTION_R_BITS - 1: 0] action_r_index;
    assign action_r_index = ACT_araddr[ACTION_R_BITS + 1: 2];

    logic [ACTION_W_BITS - 1: 0] action_w_index;
    assign action_w_index = ACT_awaddr[ACTION_W_BITS + 1: 2];


    assign action_r_regs[`ACTION_R_STATUS][16] = action_r_regs[`ACTION_R_TRACK_0][0];
    assign action_r_regs[`ACTION_R_STATUS][17] = action_r_regs[`ACTION_R_TRACK_0 + 1][0];
    assign action_r_regs[`ACTION_R_STATUS][18] = action_r_regs[`ACTION_R_TRACK_0 + 2][0];
    assign action_r_regs[`ACTION_R_STATUS][19] = action_r_regs[`ACTION_R_TRACK_0 + 3][0];
    assign action_r_regs[`ACTION_R_STATUS][20] = action_r_regs[`ACTION_R_TRACK_0 + 4][0];
    assign action_r_regs[`ACTION_R_STATUS][21] = action_r_regs[`ACTION_R_TRACK_0 + 5][0];
    assign action_r_regs[`ACTION_R_STATUS][22] = action_r_regs[`ACTION_R_TRACK_0 + 6][0];
    assign action_r_regs[`ACTION_R_STATUS][23] = action_r_regs[`ACTION_R_TRACK_0 + 7][0];
    assign action_r_regs[`ACTION_R_STATUS][24] = action_r_regs[`ACTION_R_TRACK_0 + 8][0];
    assign action_r_regs[`ACTION_R_STATUS][25] = action_r_regs[`ACTION_R_TRACK_0 + 9][0];
    assign action_r_regs[`ACTION_R_STATUS][26] = action_r_regs[`ACTION_R_TRACK_0 + 10][0];
    assign action_r_regs[`ACTION_R_STATUS][27] = action_r_regs[`ACTION_R_TRACK_0 + 11][0];
    assign action_r_regs[`ACTION_R_STATUS][28] = action_r_regs[`ACTION_R_TRACK_0 + 12][0];
    assign action_r_regs[`ACTION_R_STATUS][29] = action_r_regs[`ACTION_R_TRACK_0 + 13][0];
    assign action_r_regs[`ACTION_R_STATUS][30] = action_r_regs[`ACTION_R_TRACK_0 + 14][0];
    assign action_r_regs[`ACTION_R_STATUS][31] = action_r_regs[`ACTION_R_TRACK_15][0];

    localparam DDR_AWLEN = 4;
    localparam DDR_ARLEN = 4;

    localparam ACTION_ID_MAX = 16;
    localparam ACTION_ID_BITS = $clog2(ACTION_ID_MAX);


    enum { NVME_IDLE, NVME_WRITING, NVME_READING, NVME_COMPLETED } activity_state;


    enum { VERIFY_OK, VERIFY_ERROR } verify_state;

    initial begin

        axi_ddr_reset();





        if (`CONFIG_DDR_READWRITE_TEST) begin
            axi_ddr_test();
        end
    end


    enum { READ_IDLE, READ_DECODE, READ_BUFFER, READ_ACTION_REGS } read_state;

    always @(posedge ACT_NVME_ACLK, negedge ACT_NVME_ARESETN)
    begin
        if (!ACT_NVME_ARESETN) begin
            ACT_arready <= 1'b0;
            ACT_araddr <= 'hx;
            ACT_rdata <= 'hx;
            ACT_rresp <= 2'hx;
            ACT_rlast <= 1'b0;
            ACT_rvalid <= 1'b0;
            action_r_regs[`ACTION_R_STATUS] = 32'h0000fff0;
            for (int i = `ACTION_R_TRACK_0; i < `ACTION_R_SQ_LEVEL; i++) begin
                action_r_regs[i][31:16] <= 16'h0000;
                action_r_regs[i][15:8] <= i;
                action_r_regs[i][7:0] <= 8'h0;
            end
            for (int i = `ACTION_R_SQ_LEVEL; i < `ACTION_R_NUM_REGS; i++) begin
                action_r_regs[i] <= 32'haabbcc00 + i;
            end
            read_state <= READ_IDLE;
       end else begin
            case (read_state)
            READ_IDLE: begin
                ACT_rvalid <= 1'b0;
                ACT_arready <= 1'b1;
                if (ACT_arready && ACT_NVME_AXI_arvalid) begin
                    ACT_araddr <= ACT_NVME_AXI_araddr;
                    ACT_arready <= 1'b0;
                    read_state <= READ_DECODE;
                end
            end
            READ_DECODE: begin
                ACT_rresp <= 2'h0;
                ACT_rdata <= action_r_regs[action_r_index];
                ACT_rvalid <= 1'b1;
                ACT_rlast <= 1'b1;


                if ((ACT_NVME_AXI_araddr >= `ACTION_R_TRACK_0) &&
                    (ACT_NVME_AXI_araddr <= `ACTION_R_TRACK_15) &&
                    (activity_state == NVME_COMPLETED)) begin
                    action_r_regs[action_r_index][31:30] <= 2'b11;
                    action_r_regs[action_r_index][0] <= 0;
                end
                read_state <= READ_BUFFER;
            end
            READ_BUFFER: begin
                if (ACT_rvalid && ACT_NVME_AXI_rready) begin

                    ACT_rvalid <= 1'b0;
                    ACT_rlast <= 1'b0;
                    read_state <= READ_IDLE;
                end
            end
            default: begin
            end
            endcase
        end
    end


    enum { WRITE_IDLE, WRITE_DECODE, WRITE_BUFFER, WRITE_BURST } write_state;
    logic start_nvme_operation;

    always @(posedge ACT_NVME_ACLK, negedge ACT_NVME_ARESETN)
    begin
        if (!ACT_NVME_ARESETN) begin
            ACT_awready <= 1'b0;
            ACT_bvalid <= 1'b0;
            ACT_bresp <= 2'hx;
            ACT_awaddr <= 'hx;
            ACT_wdata <= 'hx;
            ACT_wready <= 1'b0;
            for (int i = 0; i < `ACTION_W_NUM_REGS; i++) begin
                action_w_regs[i] <= 'd0;
            end
            write_state <= WRITE_IDLE;

        end else begin
            case (write_state)
            WRITE_IDLE: begin
                ACT_awready <= 1'b1;
                ACT_wready <= 1'b0;
                start_nvme_operation <= 0;

                if (ACT_NVME_AXI_awvalid == 1 && ACT_NVME_AXI_awready == 1) begin
                    ACT_awaddr <= ACT_NVME_AXI_awaddr;
                    ACT_awready <= 1'b0;
                    ACT_wready <= 1'b1;

                    write_state <= WRITE_DECODE;
                end
            end
            WRITE_DECODE: begin
                if (ACT_NVME_AXI_wvalid == 1 && ACT_wready == 1) begin


                    ACT_wdata <= ACT_NVME_AXI_wdata;
                    action_w_regs[ACT_awaddr[ACTION_W_BITS + 1: 2]] <= ACT_NVME_AXI_wdata;

                    if (ACT_NVME_AXI_awburst == 2'b01) begin
                        ACT_awaddr <= ACT_awaddr + 4;
                        write_state <= WRITE_BURST;
                    end else begin
                        write_state <= WRITE_BUFFER;
                    end
                end
            end

            WRITE_BUFFER: begin
                if ((ACT_NVME_AXI_wvalid == 1'b1) && (ACT_wready == 1'b1) && (ACT_bvalid == 1'b0)) begin
                    if (ACT_awaddr[ACTION_W_BITS + 1: 2] == `ACTION_W_COMMAND) begin
                        void' (nvme_operation());
                    end
                end

                ACT_bresp <= 2'h0;
                ACT_bvalid <= 1'b1;

                if (ACT_bvalid && ACT_NVME_AXI_bready) begin
                    ACT_bvalid <= 1'b0;
                    write_state <= WRITE_IDLE;
                end
            end

            WRITE_BURST: begin
                ACT_wready <= 1'b1;

                if ((ACT_NVME_AXI_wvalid == 1'b1) && (ACT_wready == 1'b1) && (ACT_bvalid == 1'b0)) begin
                        if (ACT_awaddr[ACTION_W_BITS + 1: 2] == `ACTION_W_COMMAND) begin
                            start_nvme_operation <= 1;
                        end

                        action_w_regs[ACT_awaddr[ACTION_W_BITS + 1: 2]] <= ACT_NVME_AXI_wdata;
                        ACT_wdata <= ACT_NVME_AXI_wdata;
                        ACT_awaddr <= ACT_awaddr + 4;
                end

                if (ACT_NVME_AXI_wvalid == 1'b1 && ACT_wready == 1'b1 && ACT_NVME_AXI_wlast == 1'b1) begin
                    ACT_bresp <= 2'b00;
                    ACT_bvalid <= 1'b1;
                end
                if (ACT_bvalid && ACT_NVME_AXI_bready) begin
                    if (start_nvme_operation) begin
                        void '(nvme_operation());
                        start_nvme_operation <= 0;
                    end
                    ACT_bvalid <= 1'b0;
                    write_state <= WRITE_IDLE;
                end
            end
            endcase
        end
    end

    function nvme_operation();
        logic [63:0] ddr_addr;
        logic [63:0] lba_addr;
        logic [31:0] lba_num;
        logic [63:0] axi_addr;
        logic [`CMD_TYPE_BITS-1:0] cmd_type;
        logic [`CMD_ACTION_ID_BITS-1:0] cmd_action_id;


        assign cmd_type = action_w_regs[`ACTION_W_COMMAND][`CMD_TYPE_BITS-1:0];
        assign cmd_action_id = action_w_regs[`ACTION_W_COMMAND][11:8];
        assign ddr_addr = { action_w_regs[`ACTION_W_DPTR_HIGH], action_w_regs[`ACTION_W_DPTR_LOW] };
        assign lba_addr = { action_w_regs[`ACTION_W_LBA_HIGH], action_w_regs[`ACTION_W_LBA_LOW] };
        assign lba_num = action_w_regs[`ACTION_W_LBA_NUM] + 1;

        $display("nvme_operation: ddr=%h lba=%h num=%h cmd_type=%h cmd_action_id=%h",
                ddr_addr, lba_addr, lba_num, cmd_type, cmd_action_id);

        if (cmd_type == `CMD_READ) begin
            fork
                nvme_cmd_read(ddr_addr, lba_addr, lba_num, cmd_action_id);
            join_none
        end
        if (cmd_type == `CMD_WRITE) begin
            fork
                nvme_cmd_write(ddr_addr, lba_addr, lba_num, cmd_action_id);
            join_none
        end
        return 0;
    endfunction

    task nvme_cmd_read(input logic [63:0] ddr_addr,
                       input logic [63:0] lba_addr,
                       input logic [31:0] lba_num,
                       input logic [`CMD_ACTION_ID_BITS-1:0] cmd_action_id);

        logic [63:0] axi_addr;
        logic [15:0] i, j;
        logic [127:0] axi_data[512/16];


        activity_state = NVME_READING;
        if (action_r_regs[`ACTION_R_TRACK_0 + cmd_action_id][0] == 1) begin
            action_r_regs[`ACTION_R_TRACK_0 + cmd_action_id][1] = 1;
        end
        action_r_regs[`ACTION_R_TRACK_0 + cmd_action_id][31:30] = 2'b00;
        action_r_regs[`ACTION_R_TRACK_0 + cmd_action_id][0] = 0;
        verify_state = VERIFY_OK;
        #1;


        $display("nvme_read: ddr=%h lba=%h num=%h", ddr_addr, lba_addr, lba_num);
        i = 0;
        for (axi_addr = ddr_addr; axi_addr < ddr_addr + lba_num * 512; axi_addr += 16 * DDR_AWLEN) begin

            if (i == 0) begin


`ifdef SIM_XSIM
                static logic [7:0] fname[128];
`else
                static string fname;
`endif
                $sformat(fname, "SNAP_LBA_%h.bin", lba_addr);
                $readmemh(fname, axi_data);


                lba_addr += 1;
            end


            axi_ddr_write(axi_addr, { axi_data[i], axi_data[i+1], axi_data[i+2],axi_data[i+3] });
            $display("  write: axi_addr=%h axi_data=%h%h%h%h", axi_addr,
                    axi_data[i], axi_data[i+1], axi_data[i+2], axi_data[i+3]);
            i = (i + DDR_AWLEN) % (512/16);

        end

        action_r_regs[`ACTION_R_TRACK_0 + cmd_action_id][31:30] = 2'b10;
        action_r_regs[`ACTION_R_TRACK_0 + cmd_action_id][0] = 1;
        activity_state = NVME_COMPLETED;
        #1;

    endtask

    task nvme_cmd_write(input logic [63:0] ddr_addr,
                        input logic [63:0] lba_addr,
                        input logic [31:0] lba_num,
                        input logic [`CMD_ACTION_ID_BITS-1:0] cmd_action_id);
        logic [63:0] axi_addr;
        logic [15:0] i, j;
        logic [127:0] axi_rdata[DDR_ARLEN];
        logic [127:0] axi_data[512/16];

        activity_state = NVME_WRITING;
        if (action_r_regs[`ACTION_R_TRACK_0 + cmd_action_id][0] == 1) begin
            action_r_regs[`ACTION_R_TRACK_0 + cmd_action_id][1] = 1;
        end
        action_r_regs[`ACTION_R_TRACK_0 + cmd_action_id][31:30] = 2'b00;
        action_r_regs[`ACTION_R_TRACK_0 + cmd_action_id][0] = 0;
        verify_state = VERIFY_OK;
        #1;


        i = 0;
        $display("nvme_write: ddr=%h lba=%h num=%h", ddr_addr, lba_addr, lba_num);
        for (axi_addr = ddr_addr; axi_addr < ddr_addr + lba_num * 512; axi_addr += 16 * DDR_ARLEN) begin
            axi_ddr_read(axi_addr, axi_rdata);

            for (j = 0; j < DDR_ARLEN; j++) begin
                axi_data[i + j] = axi_rdata[j];
            end
            $display("  read: axi_addr=%h axi_data=%h%h%h%h", axi_addr,
                    axi_data[i], axi_data[i+1], axi_data[i+2], axi_data[i+3]);
            i = (i + DDR_ARLEN) % (512/16);


            if (i == 0) begin
                static string fname;
                $sformat(fname, "SNAP_LBA_%h.bin", lba_addr);
	        $display("Writing %s\n", fname);
                $writememh(fname, axi_data);
                lba_addr += 1;
            end

        end
        action_r_regs[`ACTION_R_TRACK_0 + cmd_action_id][31:30] = 2'b01;
        action_r_regs[`ACTION_R_TRACK_0 + cmd_action_id][0] = 1;
        activity_state = NVME_COMPLETED;
        #1;
    endtask


    always begin : AXI_DDR_CLOCK
        #1 DDR_aclk = 0;
        #1 DDR_aclk = 1;
    end

    enum { DDR_WIDLE, DDR_WRESET, DDR_WADDR, DDR_WDATA, DDR_WACK, DDR_WERROR } ddr_write_state;
    enum { DDR_RIDLE, DDR_RRESET, DDR_RADDR, DDR_RDATA, DDR_RERROR } ddr_read_state;

    task axi_ddr_reset();
        DDR_aclk = 0;
        DDR_aresetn = 0;
        ddr_write_state = DDR_WRESET;
        ddr_read_state = DDR_RRESET;
        #5;
        DDR_aresetn = 1;
        #1;
    endtask




    task axi_ddr_test();
        int i;
        logic [`DDR_M_ADDRBWIDTH-1:0] axi_addr;
        logic [127:0] axi_data[DDR_AWLEN];
        logic [127:0] cmp_data[DDR_AWLEN];




        for (axi_addr = 0; axi_addr < 4 * 1024; axi_addr += 16 * DDR_AWLEN) begin
            for (i = 0; i < DDR_AWLEN; i++) begin
                axi_data[i] = 128'h0011223344556677_8899aa00000000 + axi_addr + i;
                $display("write: axi_addr=%h axi_data=%h", axi_addr + 16 * i, axi_data[i]);
            end
            axi_ddr_write(axi_addr, axi_data);
        end


        for (axi_addr = 0; axi_addr < 4 * 1024; axi_addr += 16 * DDR_AWLEN) begin
            for (i = 0; i < DDR_AWLEN; i++) begin
                cmp_data[i] = 128'h0011223344556677_8899aa00000000 + axi_addr + i;
            end
            axi_ddr_read(axi_addr, axi_data);
            if (axi_data != cmp_data) begin
                ddr_read_state = DDR_RERROR;
            end
            $display("read: axi_addr=%h cmp_data=%h%h%h%h axi_data=%h%h%h%h", axi_addr,
                    cmp_data[i], cmp_data[i+1], cmp_data[i+2], cmp_data[i+3],
                    axi_data[i], axi_data[i+1], axi_data[i+2], axi_data[i+3]);
        end
    endtask


    logic [`DDR_M_ADDRBWIDTH-1:0] ddr_write_addr;
    logic [7:0] ddr_widx;
    logic [127:0] ddr_write_data[DDR_AWLEN];


    logic [`DDR_M_ADDRBWIDTH-1:0] ddr_read_addr;
    logic [7:0] ddr_ridx;
    logic [127:0] ddr_read_data[DDR_ARLEN];

    task axi_ddr_write(input logic [`DDR_M_ADDRBWIDTH-1:0] addr, input logic [127:0] data[DDR_AWLEN]);
        while (ddr_write_state != DDR_WIDLE) begin
            #1;
        end
        ddr_write_addr = addr;
        ddr_write_data = data;
        ddr_write_state = DDR_WADDR;
        #1;

        while (ddr_write_state != DDR_WIDLE) begin
            #1;
        end
    endtask

    function axi_ddr_wreset();
        DDR_awid <= 0;
        DDR_awlen <= 0;
        DDR_awsize <= 0;
        DDR_wstrb <= 0;
        DDR_awburst <= 0;
        DDR_awvalid <= 0;
        DDR_wstrb <= 0;
        DDR_wlast <= 0;
        DDR_wvalid <= 0;
        DDR_bready <= 0;
        DDR_awlock <= 0;
        DDR_awprot <= 0;
        DDR_awqos <= 0;
        DDR_awcache <= 0;
        DDR_wuser <= 0;
        DDR_awregion <= 0;
        ddr_widx <= 0;
        ddr_write_state <= DDR_WIDLE;
        return 0;
    endfunction


    always @(posedge DDR_aclk, negedge ddr_aresetn) begin
        if (!ddr_aresetn) begin
            void' (axi_ddr_wreset());

        end else begin
            case (ddr_write_state)
            DDR_WADDR: begin
                DDR_awburst <= 2'b01;
                ddr_widx <= 0;
                DDR_awlen <= DDR_AWLEN - 1;
                DDR_awcache <= 4'b0011;
                DDR_awprot <= 4'b0000;
                DDR_awsize <= 3'b100;
                DDR_wstrb <= 16'hffff;
                DDR_bready <= 1'b0;
                DDR_wvalid <= 1'b0;
                DDR_awaddr <= ddr_write_addr;
                DDR_awvalid <= 1'b1;

                if (DDR_M_AXI_awready && DDR_M_AXI_awvalid) begin
                    DDR_wdata <= ddr_write_data[ddr_widx];
                    ddr_widx <= ddr_widx + 1;
                    DDR_wvalid <= 1'b1;
                    DDR_awvalid <= 1'b0;
                    if (ddr_widx == DDR_AWLEN - 1) begin
                        DDR_wlast <= 1'b1;
                    end
                    ddr_write_state <= DDR_WDATA;
                end
            end
            DDR_WDATA: begin

                if (!DDR_wlast && DDR_M_AXI_wvalid && DDR_M_AXI_wready) begin
                    DDR_wdata <= ddr_write_data[ddr_widx];
                    ddr_widx <= ddr_widx + 1;
                    DDR_wvalid <= 1'b1;
                    if (ddr_widx == DDR_AWLEN - 1) begin
                        DDR_wlast <= 1'b1;
                    end
                end

                if (DDR_wlast && DDR_M_AXI_wvalid && DDR_M_AXI_wready) begin
                    DDR_wvalid <= 1'b0;
                    DDR_wlast <= 1'b0;
                    DDR_bready <= 1'b1;
                    ddr_write_state <= DDR_WACK;
                end
            end
            DDR_WACK: begin
                if (DDR_M_AXI_bready && DDR_M_AXI_bvalid) begin
                    DDR_bready <= 1'b0;
                    ddr_write_state <= DDR_WIDLE;
                end
            end
            default begin
            end
            endcase
        end
     end

     task axi_ddr_read(input logic [`DDR_M_ADDRBWIDTH-1:0] addr, output logic [127:0] data[DDR_ARLEN]);
        while (ddr_read_state != DDR_RIDLE) begin
            #1;
        end
        ddr_read_addr = addr;
        ddr_read_state = DDR_RADDR;
        #1;

        while (ddr_read_state != DDR_RIDLE) begin
            #1;
        end
        data = ddr_read_data;
        #1;
    endtask

    function axi_ddr_rreset();
        DDR_arid <= 0;
        DDR_arlock <= 0;
        DDR_arlen <= 0;
        DDR_arsize <= 0;
        DDR_arburst <= 0;
        DDR_arcache <= 0;
        DDR_arvalid <= 0;
        DDR_rready <= 0;
        DDR_rready <= 0;
        DDR_arqos <= 0;
        DDR_arregion <= 0;
        ddr_ridx <= 0;
        ddr_read_state <= DDR_RIDLE;
        return 0;
    endfunction


    always @(posedge DDR_aclk, negedge ddr_aresetn) begin
        if (!ddr_aresetn) begin
            void' (axi_ddr_rreset());

        end else begin
            case (ddr_read_state)
            DDR_RADDR: begin
                DDR_arburst <= 2'b01;
                DDR_arlen <= DDR_ARLEN - 1;
                ddr_ridx <= 0;
                DDR_arcache <= 4'b0011;
                DDR_arprot <= 4'b0000;
                DDR_arsize <= 3'b100;
                DDR_araddr <= ddr_read_addr;
                DDR_arvalid <= 1'b1;

                if (DDR_M_AXI_arready && DDR_arvalid) begin
                    DDR_arvalid <= 1'b0;
                    DDR_rready <= 1'b1;
                    ddr_read_state <= DDR_RDATA;
                end
            end
            DDR_RDATA: begin
                if (DDR_M_AXI_rvalid && DDR_rready) begin
                    ddr_read_data[ddr_ridx] <= DDR_M_AXI_rdata;
                    ddr_ridx <= ddr_ridx + 1;
                    if (DDR_M_AXI_rlast == 1'b1) begin
                        DDR_rready <= 1'b0;
                        ddr_read_state <= DDR_RIDLE;
                    end
                end
            end
            default begin
            end
            endcase
        end
    end

endmodule
module nvme_top (

    input  wire ACT_NVME_ACLK,
    input  wire ACT_NVME_ARESETN,
    input  wire [31:0]ACT_NVME_AXI_araddr,
    input  wire [1:0]ACT_NVME_AXI_arburst,
    input  wire [3:0]ACT_NVME_AXI_arcache,
    input  wire [7:0]ACT_NVME_AXI_arlen,
    input  wire [0:0]ACT_NVME_AXI_arlock,
    input  wire [2:0]ACT_NVME_AXI_arprot,
    input  wire [3:0]ACT_NVME_AXI_arqos,
    output wire ACT_NVME_AXI_arready,
    input  wire [3:0]ACT_NVME_AXI_arregion,
    input  wire [2:0]ACT_NVME_AXI_arsize,
    input  wire ACT_NVME_AXI_arvalid,
    input  wire [31:0]ACT_NVME_AXI_awaddr,
    input  wire [1:0]ACT_NVME_AXI_awburst,
    input  wire [3:0]ACT_NVME_AXI_awcache,
    input  wire [7:0]ACT_NVME_AXI_awlen,
    input  wire [0:0]ACT_NVME_AXI_awlock,
    input  wire [2:0]ACT_NVME_AXI_awprot,
    input  wire [3:0]ACT_NVME_AXI_awqos,
    output wire ACT_NVME_AXI_awready,
    input  wire [3:0]ACT_NVME_AXI_awregion,
    input  wire [2:0]ACT_NVME_AXI_awsize,
    input  wire ACT_NVME_AXI_awvalid,
    input  wire ACT_NVME_AXI_bready,
    output wire [1:0]ACT_NVME_AXI_bresp,
    output wire ACT_NVME_AXI_bvalid,
    output wire [31:0]ACT_NVME_AXI_rdata,
    output wire ACT_NVME_AXI_rlast,
    input  wire ACT_NVME_AXI_rready,
    output wire [1:0]ACT_NVME_AXI_rresp,
    output wire ACT_NVME_AXI_rvalid,
    input  wire [31:0]ACT_NVME_AXI_wdata,
    input  wire ACT_NVME_AXI_wlast,
    output wire ACT_NVME_AXI_wready,
    input  wire [3:0]ACT_NVME_AXI_wstrb,
    input  wire ACT_NVME_AXI_wvalid,


    output wire [`DDR_M_ADDRBWIDTH-1:0]DDR_M_AXI_araddr,
    output wire [1:0]DDR_M_AXI_arburst,
    output wire [3:0]DDR_M_AXI_arcache,
    output wire [3:0]DDR_M_AXI_arid,
    output wire [7:0]DDR_M_AXI_arlen,
    output wire [0:0]DDR_M_AXI_arlock,
    output wire [2:0]DDR_M_AXI_arprot,
    output wire [3:0]DDR_M_AXI_arqos,
    input  wire [0:0]DDR_M_AXI_arready,
    output wire [3:0]DDR_M_AXI_arregion,
    output wire [2:0]DDR_M_AXI_arsize,
    output wire [0:0]DDR_M_AXI_arvalid,
    output wire [`DDR_M_ADDRBWIDTH-1:0]DDR_M_AXI_awaddr,
    output wire [1:0]DDR_M_AXI_awburst,
    output wire [3:0]DDR_M_AXI_awcache,
    output wire [3:0]DDR_M_AXI_awid,
    output wire [7:0]DDR_M_AXI_awlen,
    output wire [0:0]DDR_M_AXI_awlock,
    output wire [2:0]DDR_M_AXI_awprot,
    output wire [3:0]DDR_M_AXI_awqos,
    input  wire [0:0]DDR_M_AXI_awready,
    output wire [3:0]DDR_M_AXI_awregion,
    output wire [2:0]DDR_M_AXI_awsize,
    output wire [0:0]DDR_M_AXI_awvalid,
    input  wire [3:0]DDR_M_AXI_bid,
    output wire [0:0]DDR_M_AXI_bready,
    input  wire [1:0]DDR_M_AXI_bresp,
    input  wire [0:0]DDR_M_AXI_bvalid,
    input  wire [127:0]DDR_M_AXI_rdata,
    input  wire [3:0]DDR_M_AXI_rid,
    input  wire [0:0]DDR_M_AXI_rlast,
    output wire [0:0]DDR_M_AXI_rready,
    input  wire [1:0]DDR_M_AXI_rresp,
    input  wire [15:0]DDR_M_AXI_ruser,
    input  wire [0:0]DDR_M_AXI_rvalid,
    output wire [127:0]DDR_M_AXI_wdata,
    output wire [0:0]DDR_M_AXI_wlast,
    input  wire [0:0]DDR_M_AXI_wready,
    output wire [15:0]DDR_M_AXI_wstrb,
    output wire [15:0]DDR_M_AXI_wuser,
    output wire [0:0]DDR_M_AXI_wvalid,


    input  wire NVME_S_ACLK,
    input  wire NVME_S_ARESETN,
    input  wire [31:0]NVME_S_AXI_araddr,
    input  wire [2:0]NVME_S_AXI_arprot,
    output wire [0:0]NVME_S_AXI_arready,
    input  wire [0:0]NVME_S_AXI_arvalid,
    input  wire [31:0]NVME_S_AXI_awaddr,
    input  wire [2:0]NVME_S_AXI_awprot,
    output wire [0:0]NVME_S_AXI_awready,
    input  wire [0:0]NVME_S_AXI_awvalid,
    input  wire [0:0]NVME_S_AXI_bready,
    output wire [1:0]NVME_S_AXI_bresp,
    output wire [0:0]NVME_S_AXI_bvalid,
    output wire [31:0]NVME_S_AXI_rdata,
    input  wire [0:0]NVME_S_AXI_rready,
    output wire [1:0]NVME_S_AXI_rresp,
    output wire [0:0]NVME_S_AXI_rvalid,
    input  wire [31:0]NVME_S_AXI_wdata,
    output wire [0:0]NVME_S_AXI_wready,
    input  wire [3:0]NVME_S_AXI_wstrb,
    input  wire [0:0]NVME_S_AXI_wvalid,


    output wire ddr_aclk,
    output wire ddr_aresetn,
    input  wire nvme_reset_n,
    input  wire [3:0]pcie_rc0_rxn,
    input  wire [3:0]pcie_rc0_rxp,
    output wire [3:0]pcie_rc0_txn,
    output wire [3:0]pcie_rc0_txp,
    input  wire [3:0]pcie_rc1_rxn,
    input  wire [3:0]pcie_rc1_rxp,
    output wire [3:0]pcie_rc1_txn,
    output wire [3:0]pcie_rc1_txp,
    input  wire refclk_nvme_ch0_n,
    input  wire refclk_nvme_ch0_p,
    input  wire refclk_nvme_ch1_n,
    input  wire refclk_nvme_ch1_p
    );


`define CONFIG_DDR_READWRITE_TEST   0


    reg ACT_arready;
    reg [31:0] ACT_araddr;
    reg [31:0] ACT_rdata;
    reg [0:0] ACT_awready;
    reg [31:0] ACT_awaddr;
    reg [31:0] ACT_wdata;
    reg [0:0] ACT_wready;
    reg [0:0] ACT_bvalid;
    reg [1:0] ACT_bresp;
    reg [0:0] ACT_rvalid;
    reg [0:0] ACT_rlast;
    reg [1:0] ACT_rresp;


    reg DDR_aclk;
    reg DDR_aresetn;
    reg [3:0] DDR_arid;
    reg [7:0] DDR_awlen;
    reg [2:0] DDR_awsize;
    reg [1:0] DDR_awburst;
    reg [`DDR_M_ADDRBWIDTH-1:0] DDR_awaddr;
    reg [0:0] DDR_arvalid;
    reg [0:0] DDR_awvalid;
    reg [127:0] DDR_wdata;
    reg [15:0] DDR_wstrb;
    reg [0:0] DDR_wvalid;
    reg [3:0] DDR_awid;
    reg [7:0] DDR_arlen;
    reg [2:0] DDR_arsize;
    reg [`DDR_M_ADDRBWIDTH-1:0] DDR_araddr;
    reg [0:0] DDR_rready;
    reg [0:0] DDR_arlock;
    reg [0:0] DDR_wlast;
    reg [0:0] DDR_bready;
    reg [0:0] DDR_arburst;
    reg [0:0] DDR_awlock;
    reg [2:0] DDR_awprot;
    reg [2:0] DDR_arprot;
    reg [3:0] DDR_awqos;
    reg [3:0] DDR_arqos;
    reg [3:0] DDR_awcache;
    reg [3:0] DDR_arcache;
    reg [15:0] DDR_wuser;
    reg [3:0] DDR_awregion;
    reg [3:0] DDR_arregion;


    assign ACT_NVME_AXI_arready = ACT_arready;
    assign ACT_NVME_AXI_rdata = ACT_rdata;
    assign ACT_NVME_AXI_awready = ACT_awready;
    assign ACT_NVME_AXI_wready = ACT_wready;
    assign ACT_NVME_AXI_bvalid = ACT_bvalid;
    assign ACT_NVME_AXI_bresp = ACT_bresp;
    assign ACT_NVME_AXI_rvalid = ACT_rvalid;
    assign ACT_NVME_AXI_rresp = ACT_rresp;
    assign ACT_NVME_AXI_rlast = ACT_rlast;


    assign ddr_aclk = DDR_aclk;
    assign ddr_aresetn = DDR_aresetn;
    assign DDR_M_AXI_awid = DDR_awid;
    assign DDR_M_AXI_arid = DDR_arid;
    assign DDR_M_AXI_awlen = DDR_awlen;
    assign DDR_M_AXI_awsize = DDR_awsize;
    assign DDR_M_AXI_awburst = DDR_awburst;
    assign DDR_M_AXI_awaddr = DDR_awaddr[`DDR_M_ADDRBWIDTH-1:0];
    assign DDR_M_AXI_awvalid = DDR_awvalid;
    assign DDR_M_AXI_wdata = DDR_wdata;
    assign DDR_M_AXI_wstrb = DDR_wstrb;
    assign DDR_M_AXI_wvalid = DDR_wvalid;
    assign DDR_M_AXI_wlast = DDR_wlast;
    assign DDR_M_AXI_arvalid = DDR_arvalid;
    assign DDR_M_AXI_arlen = DDR_arlen;
    assign DDR_M_AXI_arsize = DDR_arsize;
    assign DDR_M_AXI_araddr = DDR_araddr[`DDR_M_ADDRBWIDTH-1:0];
    assign DDR_M_AXI_rready = DDR_rready;
    assign DDR_M_AXI_bready = DDR_bready;
    assign DDR_M_AXI_arburst = DDR_arburst;
    assign DDR_M_AXI_awlock = DDR_awlock;
    assign DDR_M_AXI_arlock = DDR_arlock;
    assign DDR_M_AXI_awprot = DDR_awprot;
    assign DDR_M_AXI_arprot = DDR_arprot;
    assign DDR_M_AXI_awqos = DDR_awqos;
    assign DDR_M_AXI_arqos = DDR_arqos;
    assign DDR_M_AXI_awcache = DDR_awcache;
    assign DDR_M_AXI_arcache = DDR_arcache;
    assign DDR_M_AXI_wuser = DDR_wuser;
    assign DDR_M_AXI_awregion = DDR_awregion;
    assign DDR_M_AXI_arregion = DDR_arregion;


    localparam ACTION_W_BITS = $clog2(`ACTION_W_NUM_REGS);
    localparam ACTION_R_BITS = $clog2(`ACTION_R_NUM_REGS);
    localparam SQ_INDEX_BITS = $clog2(`TOTAL_NUM_QUEUES);

    logic [31:0] action_w_regs[`ACTION_W_NUM_REGS];
    logic [31:0] action_r_regs[`ACTION_R_NUM_REGS];

    logic [ACTION_R_BITS - 1: 0] action_r_index;
    assign action_r_index = ACT_araddr[ACTION_R_BITS + 1: 2];

    logic [ACTION_W_BITS - 1: 0] action_w_index;
    assign action_w_index = ACT_awaddr[ACTION_W_BITS + 1: 2];


    assign action_r_regs[`ACTION_R_STATUS][16] = action_r_regs[`ACTION_R_TRACK_0][0];
    assign action_r_regs[`ACTION_R_STATUS][17] = action_r_regs[`ACTION_R_TRACK_0 + 1][0];
    assign action_r_regs[`ACTION_R_STATUS][18] = action_r_regs[`ACTION_R_TRACK_0 + 2][0];
    assign action_r_regs[`ACTION_R_STATUS][19] = action_r_regs[`ACTION_R_TRACK_0 + 3][0];
    assign action_r_regs[`ACTION_R_STATUS][20] = action_r_regs[`ACTION_R_TRACK_0 + 4][0];
    assign action_r_regs[`ACTION_R_STATUS][21] = action_r_regs[`ACTION_R_TRACK_0 + 5][0];
    assign action_r_regs[`ACTION_R_STATUS][22] = action_r_regs[`ACTION_R_TRACK_0 + 6][0];
    assign action_r_regs[`ACTION_R_STATUS][23] = action_r_regs[`ACTION_R_TRACK_0 + 7][0];
    assign action_r_regs[`ACTION_R_STATUS][24] = action_r_regs[`ACTION_R_TRACK_0 + 8][0];
    assign action_r_regs[`ACTION_R_STATUS][25] = action_r_regs[`ACTION_R_TRACK_0 + 9][0];
    assign action_r_regs[`ACTION_R_STATUS][26] = action_r_regs[`ACTION_R_TRACK_0 + 10][0];
    assign action_r_regs[`ACTION_R_STATUS][27] = action_r_regs[`ACTION_R_TRACK_0 + 11][0];
    assign action_r_regs[`ACTION_R_STATUS][28] = action_r_regs[`ACTION_R_TRACK_0 + 12][0];
    assign action_r_regs[`ACTION_R_STATUS][29] = action_r_regs[`ACTION_R_TRACK_0 + 13][0];
    assign action_r_regs[`ACTION_R_STATUS][30] = action_r_regs[`ACTION_R_TRACK_0 + 14][0];
    assign action_r_regs[`ACTION_R_STATUS][31] = action_r_regs[`ACTION_R_TRACK_15][0];

    localparam DDR_AWLEN = 4;
    localparam DDR_ARLEN = 4;

    localparam ACTION_ID_MAX = 16;
    localparam ACTION_ID_BITS = $clog2(ACTION_ID_MAX);


    enum { NVME_IDLE, NVME_WRITING, NVME_READING, NVME_COMPLETED } activity_state;


    enum { VERIFY_OK, VERIFY_ERROR } verify_state;

    initial begin

        axi_ddr_reset();





        if (`CONFIG_DDR_READWRITE_TEST) begin
            axi_ddr_test();
        end
    end


    enum { READ_IDLE, READ_DECODE, READ_BUFFER, READ_ACTION_REGS } read_state;

    always @(posedge ACT_NVME_ACLK, negedge ACT_NVME_ARESETN)
    begin
        if (!ACT_NVME_ARESETN) begin
            ACT_arready <= 1'b0;
            ACT_araddr <= 'hx;
            ACT_rdata <= 'hx;
            ACT_rresp <= 2'hx;
            ACT_rlast <= 1'b0;
            ACT_rvalid <= 1'b0;
            action_r_regs[`ACTION_R_STATUS] = 32'h0000fff0;
            for (int i = `ACTION_R_TRACK_0; i < `ACTION_R_SQ_LEVEL; i++) begin
                action_r_regs[i][31:16] <= 16'h0000;
                action_r_regs[i][15:8] <= i;
                action_r_regs[i][7:0] <= 8'h0;
            end
            for (int i = `ACTION_R_SQ_LEVEL; i < `ACTION_R_NUM_REGS; i++) begin
                action_r_regs[i] <= 32'haabbcc00 + i;
            end
            read_state <= READ_IDLE;
       end else begin
            case (read_state)
            READ_IDLE: begin
                ACT_rvalid <= 1'b0;
                ACT_arready <= 1'b1;
                if (ACT_arready && ACT_NVME_AXI_arvalid) begin
                    ACT_araddr <= ACT_NVME_AXI_araddr;
                    ACT_arready <= 1'b0;
                    read_state <= READ_DECODE;
                end
            end
            READ_DECODE: begin
                ACT_rresp <= 2'h0;
                ACT_rdata <= action_r_regs[action_r_index];
                ACT_rvalid <= 1'b1;
                ACT_rlast <= 1'b1;


                if ((ACT_NVME_AXI_araddr >= `ACTION_R_TRACK_0) &&
                    (ACT_NVME_AXI_araddr <= `ACTION_R_TRACK_15) &&
                    (activity_state == NVME_COMPLETED)) begin
                    action_r_regs[action_r_index][31:30] <= 2'b11;
                    action_r_regs[action_r_index][0] <= 0;
                end
                read_state <= READ_BUFFER;
            end
            READ_BUFFER: begin
                if (ACT_rvalid && ACT_NVME_AXI_rready) begin

                    ACT_rvalid <= 1'b0;
                    ACT_rlast <= 1'b0;
                    read_state <= READ_IDLE;
                end
            end
            default: begin
            end
            endcase
        end
    end


    enum { WRITE_IDLE, WRITE_DECODE, WRITE_BUFFER, WRITE_BURST } write_state;
    logic start_nvme_operation;

    always @(posedge ACT_NVME_ACLK, negedge ACT_NVME_ARESETN)
    begin
        if (!ACT_NVME_ARESETN) begin
            ACT_awready <= 1'b0;
            ACT_bvalid <= 1'b0;
            ACT_bresp <= 2'hx;
            ACT_awaddr <= 'hx;
            ACT_wdata <= 'hx;
            ACT_wready <= 1'b0;
            for (int i = 0; i < `ACTION_W_NUM_REGS; i++) begin
                action_w_regs[i] <= 'd0;
            end
            write_state <= WRITE_IDLE;

        end else begin
            case (write_state)
            WRITE_IDLE: begin
                ACT_awready <= 1'b1;
                ACT_wready <= 1'b0;
                start_nvme_operation <= 0;

                if (ACT_NVME_AXI_awvalid == 1 && ACT_NVME_AXI_awready == 1) begin
                    ACT_awaddr <= ACT_NVME_AXI_awaddr;
                    ACT_awready <= 1'b0;
                    ACT_wready <= 1'b1;

                    write_state <= WRITE_DECODE;
                end
            end
            WRITE_DECODE: begin
                if (ACT_NVME_AXI_wvalid == 1 && ACT_wready == 1) begin


                    ACT_wdata <= ACT_NVME_AXI_wdata;
                    action_w_regs[ACT_awaddr[ACTION_W_BITS + 1: 2]] <= ACT_NVME_AXI_wdata;

                    if (ACT_NVME_AXI_awburst == 2'b01) begin
                        ACT_awaddr <= ACT_awaddr + 4;
                        write_state <= WRITE_BURST;
                    end else begin
                        write_state <= WRITE_BUFFER;
                    end
                end
            end

            WRITE_BUFFER: begin
                if ((ACT_NVME_AXI_wvalid == 1'b1) && (ACT_wready == 1'b1) && (ACT_bvalid == 1'b0)) begin
                    if (ACT_awaddr[ACTION_W_BITS + 1: 2] == `ACTION_W_COMMAND) begin
                        void' (nvme_operation());
                    end
                end

                ACT_bresp <= 2'h0;
                ACT_bvalid <= 1'b1;

                if (ACT_bvalid && ACT_NVME_AXI_bready) begin
                    ACT_bvalid <= 1'b0;
                    write_state <= WRITE_IDLE;
                end
            end

            WRITE_BURST: begin
                ACT_wready <= 1'b1;

                if ((ACT_NVME_AXI_wvalid == 1'b1) && (ACT_wready == 1'b1) && (ACT_bvalid == 1'b0)) begin
                        if (ACT_awaddr[ACTION_W_BITS + 1: 2] == `ACTION_W_COMMAND) begin
                            start_nvme_operation <= 1;
                        end

                        action_w_regs[ACT_awaddr[ACTION_W_BITS + 1: 2]] <= ACT_NVME_AXI_wdata;
                        ACT_wdata <= ACT_NVME_AXI_wdata;
                        ACT_awaddr <= ACT_awaddr + 4;
                end

                if (ACT_NVME_AXI_wvalid == 1'b1 && ACT_wready == 1'b1 && ACT_NVME_AXI_wlast == 1'b1) begin
                    ACT_bresp <= 2'b00;
                    ACT_bvalid <= 1'b1;
                end
                if (ACT_bvalid && ACT_NVME_AXI_bready) begin
                    if (start_nvme_operation) begin
                        void '(nvme_operation());
                        start_nvme_operation <= 0;
                    end
                    ACT_bvalid <= 1'b0;
                    write_state <= WRITE_IDLE;
                end
            end
            endcase
        end
    end

    function nvme_operation();
        logic [63:0] ddr_addr;
        logic [63:0] lba_addr;
        logic [31:0] lba_num;
        logic [63:0] axi_addr;
        logic [`CMD_TYPE_BITS-1:0] cmd_type;
        logic [`CMD_ACTION_ID_BITS-1:0] cmd_action_id;


        assign cmd_type = action_w_regs[`ACTION_W_COMMAND][`CMD_TYPE_BITS-1:0];
        assign cmd_action_id = action_w_regs[`ACTION_W_COMMAND][11:8];
        assign ddr_addr = { action_w_regs[`ACTION_W_DPTR_HIGH], action_w_regs[`ACTION_W_DPTR_LOW] };
        assign lba_addr = { action_w_regs[`ACTION_W_LBA_HIGH], action_w_regs[`ACTION_W_LBA_LOW] };
        assign lba_num = action_w_regs[`ACTION_W_LBA_NUM] + 1;

        $display("nvme_operation: ddr=%h lba=%h num=%h cmd_type=%h cmd_action_id=%h",
                ddr_addr, lba_addr, lba_num, cmd_type, cmd_action_id);

        if (cmd_type == `CMD_READ) begin
            fork
                nvme_cmd_read(ddr_addr, lba_addr, lba_num, cmd_action_id);
            join_none
        end
        if (cmd_type == `CMD_WRITE) begin
            fork
                nvme_cmd_write(ddr_addr, lba_addr, lba_num, cmd_action_id);
            join_none
        end
        return 0;
    endfunction

    task nvme_cmd_read(input logic [63:0] ddr_addr,
                       input logic [63:0] lba_addr,
                       input logic [31:0] lba_num,
                       input logic [`CMD_ACTION_ID_BITS-1:0] cmd_action_id);

        logic [63:0] axi_addr;
        logic [15:0] i, j;
        logic [127:0] axi_data[512/16];


        activity_state = NVME_READING;
        if (action_r_regs[`ACTION_R_TRACK_0 + cmd_action_id][0] == 1) begin
            action_r_regs[`ACTION_R_TRACK_0 + cmd_action_id][1] = 1;
        end
        action_r_regs[`ACTION_R_TRACK_0 + cmd_action_id][31:30] = 2'b00;
        action_r_regs[`ACTION_R_TRACK_0 + cmd_action_id][0] = 0;
        verify_state = VERIFY_OK;
        #1;


        $display("nvme_read: ddr=%h lba=%h num=%h", ddr_addr, lba_addr, lba_num);
        i = 0;
        for (axi_addr = ddr_addr; axi_addr < ddr_addr + lba_num * 512; axi_addr += 16 * DDR_AWLEN) begin

            if (i == 0) begin


`ifdef SIM_XSIM
                static logic [7:0] fname[128];
`else
                static string fname;
`endif
                $sformat(fname, "SNAP_LBA_%h.bin", lba_addr);
                $readmemh(fname, axi_data);


                lba_addr += 1;
            end


            axi_ddr_write(axi_addr, { axi_data[i], axi_data[i+1], axi_data[i+2],axi_data[i+3] });
            $display("  write: axi_addr=%h axi_data=%h%h%h%h", axi_addr,
                    axi_data[i], axi_data[i+1], axi_data[i+2], axi_data[i+3]);
            i = (i + DDR_AWLEN) % (512/16);

        end

        action_r_regs[`ACTION_R_TRACK_0 + cmd_action_id][31:30] = 2'b10;
        action_r_regs[`ACTION_R_TRACK_0 + cmd_action_id][0] = 1;
        activity_state = NVME_COMPLETED;
        #1;

    endtask

    task nvme_cmd_write(input logic [63:0] ddr_addr,
                        input logic [63:0] lba_addr,
                        input logic [31:0] lba_num,
                        input logic [`CMD_ACTION_ID_BITS-1:0] cmd_action_id);
        logic [63:0] axi_addr;
        logic [15:0] i, j;
        logic [127:0] axi_rdata[DDR_ARLEN];
        logic [127:0] axi_data[512/16];

        activity_state = NVME_WRITING;
        if (action_r_regs[`ACTION_R_TRACK_0 + cmd_action_id][0] == 1) begin
            action_r_regs[`ACTION_R_TRACK_0 + cmd_action_id][1] = 1;
        end
        action_r_regs[`ACTION_R_TRACK_0 + cmd_action_id][31:30] = 2'b00;
        action_r_regs[`ACTION_R_TRACK_0 + cmd_action_id][0] = 0;
        verify_state = VERIFY_OK;
        #1;


        i = 0;
        $display("nvme_write: ddr=%h lba=%h num=%h", ddr_addr, lba_addr, lba_num);
        for (axi_addr = ddr_addr; axi_addr < ddr_addr + lba_num * 512; axi_addr += 16 * DDR_ARLEN) begin
            axi_ddr_read(axi_addr, axi_rdata);

            for (j = 0; j < DDR_ARLEN; j++) begin
                axi_data[i + j] = axi_rdata[j];
            end
            $display("  read: axi_addr=%h axi_data=%h%h%h%h", axi_addr,
                    axi_data[i], axi_data[i+1], axi_data[i+2], axi_data[i+3]);
            i = (i + DDR_ARLEN) % (512/16);


            if (i == 0) begin
                static string fname;
                $sformat(fname, "SNAP_LBA_%h.bin", lba_addr);
	        $display("Writing %s\n", fname);
                $writememh(fname, axi_data);
                lba_addr += 1;
            end

        end
        action_r_regs[`ACTION_R_TRACK_0 + cmd_action_id][31:30] = 2'b01;
        action_r_regs[`ACTION_R_TRACK_0 + cmd_action_id][0] = 1;
        activity_state = NVME_COMPLETED;
        #1;
    endtask


    always begin : AXI_DDR_CLOCK
        #1 DDR_aclk = 0;
        #1 DDR_aclk = 1;
    end

    enum { DDR_WIDLE, DDR_WRESET, DDR_WADDR, DDR_WDATA, DDR_WACK, DDR_WERROR } ddr_write_state;
    enum { DDR_RIDLE, DDR_RRESET, DDR_RADDR, DDR_RDATA, DDR_RERROR } ddr_read_state;

    task axi_ddr_reset();
        DDR_aclk = 0;
        DDR_aresetn = 0;
        ddr_write_state = DDR_WRESET;
        ddr_read_state = DDR_RRESET;
        #5;
        DDR_aresetn = 1;
        #1;
    endtask




    task axi_ddr_test();
        int i;
        logic [`DDR_M_ADDRBWIDTH-1:0] axi_addr;
        logic [127:0] axi_data[DDR_AWLEN];
        logic [127:0] cmp_data[DDR_AWLEN];




        for (axi_addr = 0; axi_addr < 4 * 1024; axi_addr += 16 * DDR_AWLEN) begin
            for (i = 0; i < DDR_AWLEN; i++) begin
                axi_data[i] = 128'h0011223344556677_8899aa00000000 + axi_addr + i;
                $display("write: axi_addr=%h axi_data=%h", axi_addr + 16 * i, axi_data[i]);
            end
            axi_ddr_write(axi_addr, axi_data);
        end


        for (axi_addr = 0; axi_addr < 4 * 1024; axi_addr += 16 * DDR_AWLEN) begin
            for (i = 0; i < DDR_AWLEN; i++) begin
                cmp_data[i] = 128'h0011223344556677_8899aa00000000 + axi_addr + i;
            end
            axi_ddr_read(axi_addr, axi_data);
            if (axi_data != cmp_data) begin
                ddr_read_state = DDR_RERROR;
            end
            $display("read: axi_addr=%h cmp_data=%h%h%h%h axi_data=%h%h%h%h", axi_addr,
                    cmp_data[i], cmp_data[i+1], cmp_data[i+2], cmp_data[i+3],
                    axi_data[i], axi_data[i+1], axi_data[i+2], axi_data[i+3]);
        end
    endtask


    logic [`DDR_M_ADDRBWIDTH-1:0] ddr_write_addr;
    logic [7:0] ddr_widx;
    logic [127:0] ddr_write_data[DDR_AWLEN];


    logic [`DDR_M_ADDRBWIDTH-1:0] ddr_read_addr;
    logic [7:0] ddr_ridx;
    logic [127:0] ddr_read_data[DDR_ARLEN];

    task axi_ddr_write(input logic [`DDR_M_ADDRBWIDTH-1:0] addr, input logic [127:0] data[DDR_AWLEN]);
        while (ddr_write_state != DDR_WIDLE) begin
            #1;
        end
        ddr_write_addr = addr;
        ddr_write_data = data;
        ddr_write_state = DDR_WADDR;
        #1;

        while (ddr_write_state != DDR_WIDLE) begin
            #1;
        end
    endtask

    function axi_ddr_wreset();
        DDR_awid <= 0;
        DDR_awlen <= 0;
        DDR_awsize <= 0;
        DDR_wstrb <= 0;
        DDR_awburst <= 0;
        DDR_awvalid <= 0;
        DDR_wstrb <= 0;
        DDR_wlast <= 0;
        DDR_wvalid <= 0;
        DDR_bready <= 0;
        DDR_awlock <= 0;
        DDR_awprot <= 0;
        DDR_awqos <= 0;
        DDR_awcache <= 0;
        DDR_wuser <= 0;
        DDR_awregion <= 0;
        ddr_widx <= 0;
        ddr_write_state <= DDR_WIDLE;
        return 0;
    endfunction


    always @(posedge DDR_aclk, negedge ddr_aresetn) begin
        if (!ddr_aresetn) begin
            void' (axi_ddr_wreset());

        end else begin
            case (ddr_write_state)
            DDR_WADDR: begin
                DDR_awburst <= 2'b01;
                ddr_widx <= 0;
                DDR_awlen <= DDR_AWLEN - 1;
                DDR_awcache <= 4'b0011;
                DDR_awprot <= 4'b0000;
                DDR_awsize <= 3'b100;
                DDR_wstrb <= 16'hffff;
                DDR_bready <= 1'b0;
                DDR_wvalid <= 1'b0;
                DDR_awaddr <= ddr_write_addr;
                DDR_awvalid <= 1'b1;

                if (DDR_M_AXI_awready && DDR_M_AXI_awvalid) begin
                    DDR_wdata <= ddr_write_data[ddr_widx];
                    ddr_widx <= ddr_widx + 1;
                    DDR_wvalid <= 1'b1;
                    DDR_awvalid <= 1'b0;
                    if (ddr_widx == DDR_AWLEN - 1) begin
                        DDR_wlast <= 1'b1;
                    end
                    ddr_write_state <= DDR_WDATA;
                end
            end
            DDR_WDATA: begin

                if (!DDR_wlast && DDR_M_AXI_wvalid && DDR_M_AXI_wready) begin
                    DDR_wdata <= ddr_write_data[ddr_widx];
                    ddr_widx <= ddr_widx + 1;
                    DDR_wvalid <= 1'b1;
                    if (ddr_widx == DDR_AWLEN - 1) begin
                        DDR_wlast <= 1'b1;
                    end
                end

                if (DDR_wlast && DDR_M_AXI_wvalid && DDR_M_AXI_wready) begin
                    DDR_wvalid <= 1'b0;
                    DDR_wlast <= 1'b0;
                    DDR_bready <= 1'b1;
                    ddr_write_state <= DDR_WACK;
                end
            end
            DDR_WACK: begin
                if (DDR_M_AXI_bready && DDR_M_AXI_bvalid) begin
                    DDR_bready <= 1'b0;
                    ddr_write_state <= DDR_WIDLE;
                end
            end
            default begin
            end
            endcase
        end
     end

     task axi_ddr_read(input logic [`DDR_M_ADDRBWIDTH-1:0] addr, output logic [127:0] data[DDR_ARLEN]);
        while (ddr_read_state != DDR_RIDLE) begin
            #1;
        end
        ddr_read_addr = addr;
        ddr_read_state = DDR_RADDR;
        #1;

        while (ddr_read_state != DDR_RIDLE) begin
            #1;
        end
        data = ddr_read_data;
        #1;
    endtask

    function axi_ddr_rreset();
        DDR_arid <= 0;
        DDR_arlock <= 0;
        DDR_arlen <= 0;
        DDR_arsize <= 0;
        DDR_arburst <= 0;
        DDR_arcache <= 0;
        DDR_arvalid <= 0;
        DDR_rready <= 0;
        DDR_rready <= 0;
        DDR_arqos <= 0;
        DDR_arregion <= 0;
        ddr_ridx <= 0;
        ddr_read_state <= DDR_RIDLE;
        return 0;
    endfunction


    always @(posedge DDR_aclk, negedge ddr_aresetn) begin
        if (!ddr_aresetn) begin
            void' (axi_ddr_rreset());

        end else begin
            case (ddr_read_state)
            DDR_RADDR: begin
                DDR_arburst <= 2'b01;
                DDR_arlen <= DDR_ARLEN - 1;
                ddr_ridx <= 0;
                DDR_arcache <= 4'b0011;
                DDR_arprot <= 4'b0000;
                DDR_arsize <= 3'b100;
                DDR_araddr <= ddr_read_addr;
                DDR_arvalid <= 1'b1;

                if (DDR_M_AXI_arready && DDR_arvalid) begin
                    DDR_arvalid <= 1'b0;
                    DDR_rready <= 1'b1;
                    ddr_read_state <= DDR_RDATA;
                end
            end
            DDR_RDATA: begin
                if (DDR_M_AXI_rvalid && DDR_rready) begin
                    ddr_read_data[ddr_ridx] <= DDR_M_AXI_rdata;
                    ddr_ridx <= ddr_ridx + 1;
                    if (DDR_M_AXI_rlast == 1'b1) begin
                        DDR_rready <= 1'b0;
                        ddr_read_state <= DDR_RIDLE;
                    end
                end
            end
            default begin
            end
            endcase
        end
    end

endmodule