`resetall
`timescale 1ns / 1ps
`default_nettype none

module top #
(
    parameter NUM_RX = 2
)
(   
    input  wire 		sys_clk_p,
    input  wire 		sys_clk_n,
    // output wire [2:0]   leds,
    // input  wire         uart_rxd,
    // output wire         uart_txd,
    // output wire         fan_pwm,

    output wire [7:0]   pcie_mgt_txp,
    output wire [7:0]   pcie_mgt_txn,
    input  wire [7:0]   pcie_mgt_rxp,
    input  wire [7:0]   pcie_mgt_rxn,
    input  wire         pcie_rst_n,
    input  wire 		pcie_ref_clk_p,
    input  wire 		pcie_ref_clk_n    


);

parameter DATE_CODE = 32'h0000_0000;
parameter TIME_CODE = 32'h0000_0000;

wire axi_pcie_resetn;
wire axi_pcie_clk;
wire axil_resetn;
wire axil_clk;
wire usr_irq_req;
wire [5:0] pcie_cfg_ltssm_state;
wire pcie_user_lnk_up;
wire [31:0] gpo;
wire [31:0] gpi;
assign usr_irq_req = 1'b0;


axi4l_intf # (
    .AXI_ADDR_WIDTH(32), 
    .AXI_DATA_WIDTH(32)
) 
util_reg_if (
    .clk(axi_pcie_clk),
    .resetn(axi_pcie_resetn)
);

axi4l_intf # (
    .AXI_ADDR_WIDTH(32), 
    .AXI_DATA_WIDTH(32)
) 
descriptors_if (
    .clk(axi_pcie_clk),
    .resetn(axi_pcie_resetn)
);

axi4l_intf # (
    .AXI_ADDR_WIDTH(32), 
    .AXI_DATA_WIDTH(32)
) 
timing_if (
    .clk(axi_pcie_clk),
    .resetn(axi_pcie_resetn)
);

axi4l_intf # (
    .AXI_ADDR_WIDTH(32), 
    .AXI_DATA_WIDTH(32)
) 
data_gen_if (
    .clk(axi_pcie_clk),
    .resetn(axi_pcie_resetn)
);

// If you increase NUM_DMA you will also need to create additional AXI interfaces into the BD
parameter NUM_DMA = 4;

axi4l_intf # (
    .AXI_ADDR_WIDTH(32), 
    .AXI_DATA_WIDTH(32)
    ) 
pcie_dma_ctrl_axi[NUM_DMA](
    .clk(axi_pcie_clk),
    .resetn(axi_pcie_resetn)
    );     
    
axi4_intf # (
    .AXI_ADDR_WIDTH(40), 
    .AXI_DATA_WIDTH(256)
    ) 
pcie_dma_maxi[NUM_DMA](
    .clk(axi_pcie_clk),
    .resetn(axi_pcie_resetn)
    );   

axi4s_intf # (
    .AXI_DATA_WIDTH(128)
    ) 
pcie_dma_axis[NUM_DMA](
    .clk(axi_pcie_clk),
    .resetn(axi_pcie_resetn)
    );  

design_1 design_1_i
(
    .sys_clk_clk_n(sys_clk_n),
    .sys_clk_clk_p(sys_clk_p),
    // .UART_0_rxd(uart_rxd),
    // .UART_0_txd(uart_txd),
    .pcie_mgt_0_rxn(pcie_mgt_rxn),
    .pcie_mgt_0_rxp(pcie_mgt_rxp),
    .pcie_mgt_0_txn(pcie_mgt_txn),
    .pcie_mgt_0_txp(pcie_mgt_txp),    
    .pcie_refclk_clk_n(pcie_ref_clk_n),
    .pcie_refclk_clk_p(pcie_ref_clk_p),    
    .pcie_rstn(pcie_rst_n),
    .pcie_cfg_ltssm_state(pcie_cfg_ltssm_state),
    .pcie_user_lnk_up(pcie_user_lnk_up),
    .usr_irq_req(usr_irq_req),

    .axi_pcie_aresetn(axi_pcie_resetn),
    .axi_pcie_clk(axi_pcie_clk),
    .axil_resetn(axil_resetn),
    .axil_clk(axil_clk),

    .axil_util_araddr(util_reg_if.araddr),
    .axil_util_arprot(util_reg_if.arprot),
    .axil_util_arready(util_reg_if.arready),
    .axil_util_arvalid(util_reg_if.arvalid),
    .axil_util_awaddr(util_reg_if.awaddr),
    .axil_util_awprot(util_reg_if.awprot),
    .axil_util_awready(util_reg_if.awready),
    .axil_util_awvalid(util_reg_if.awvalid),
    .axil_util_bready(util_reg_if.bready),
    .axil_util_bresp(util_reg_if.bresp),
    .axil_util_bvalid(util_reg_if.bvalid),
    .axil_util_rdata(util_reg_if.rdata),
    .axil_util_rready(util_reg_if.rready),
    .axil_util_rresp(util_reg_if.rresp),
    .axil_util_rvalid(util_reg_if.rvalid),
    .axil_util_wdata(util_reg_if.wdata),
    .axil_util_wready(util_reg_if.wready),
    .axil_util_wstrb(util_reg_if.wstrb),
    .axil_util_wvalid(util_reg_if.wvalid),    

    .axil_timing_araddr(timing_if.araddr),
    .axil_timing_arprot(timing_if.arprot),
    .axil_timing_arready(timing_if.arready),
    .axil_timing_arvalid(timing_if.arvalid),
    .axil_timing_awaddr(timing_if.awaddr),
    .axil_timing_awprot(timing_if.awprot),
    .axil_timing_awready(timing_if.awready),
    .axil_timing_awvalid(timing_if.awvalid),
    .axil_timing_bready(timing_if.bready),
    .axil_timing_bresp(timing_if.bresp),
    .axil_timing_bvalid(timing_if.bvalid),
    .axil_timing_rdata(timing_if.rdata),
    .axil_timing_rready(timing_if.rready),
    .axil_timing_rresp(timing_if.rresp),
    .axil_timing_rvalid(timing_if.rvalid),
    .axil_timing_wdata(timing_if.wdata),
    .axil_timing_wready(timing_if.wready),
    .axil_timing_wstrb(timing_if.wstrb),
    .axil_timing_wvalid(timing_if.wvalid),     

    .axil_data_gen_araddr(data_gen_if.araddr),
    .axil_data_gen_arprot(data_gen_if.arprot),
    .axil_data_gen_arready(data_gen_if.arready),
    .axil_data_gen_arvalid(data_gen_if.arvalid),
    .axil_data_gen_awaddr(data_gen_if.awaddr),
    .axil_data_gen_awprot(data_gen_if.awprot),
    .axil_data_gen_awready(data_gen_if.awready),
    .axil_data_gen_awvalid(data_gen_if.awvalid),
    .axil_data_gen_bready(data_gen_if.bready),
    .axil_data_gen_bresp(data_gen_if.bresp),
    .axil_data_gen_bvalid(data_gen_if.bvalid),
    .axil_data_gen_rdata(data_gen_if.rdata),
    .axil_data_gen_rready(data_gen_if.rready),
    .axil_data_gen_rresp(data_gen_if.rresp),
    .axil_data_gen_rvalid(data_gen_if.rvalid),
    .axil_data_gen_wdata(data_gen_if.wdata),
    .axil_data_gen_wready(data_gen_if.wready),
    .axil_data_gen_wstrb(data_gen_if.wstrb),
    .axil_data_gen_wvalid(data_gen_if.wvalid),         

    .axil_descriptors_araddr(descriptors_if.araddr),
    .axil_descriptors_arprot(descriptors_if.arprot),
    .axil_descriptors_arready(descriptors_if.arready),
    .axil_descriptors_arvalid(descriptors_if.arvalid),
    .axil_descriptors_awaddr(descriptors_if.awaddr),
    .axil_descriptors_awprot(descriptors_if.awprot),
    .axil_descriptors_awready(descriptors_if.awready),
    .axil_descriptors_awvalid(descriptors_if.awvalid),
    .axil_descriptors_bready(descriptors_if.bready),
    .axil_descriptors_bresp(descriptors_if.bresp),
    .axil_descriptors_bvalid(descriptors_if.bvalid),
    .axil_descriptors_rdata(descriptors_if.rdata),
    .axil_descriptors_rready(descriptors_if.rready),
    .axil_descriptors_rresp(descriptors_if.rresp),
    .axil_descriptors_rvalid(descriptors_if.rvalid),
    .axil_descriptors_wdata(descriptors_if.wdata),
    .axil_descriptors_wready(descriptors_if.wready),
    .axil_descriptors_wstrb(descriptors_if.wstrb),
    .axil_descriptors_wvalid(descriptors_if.wvalid),

    .axil_dma_ctrl0_araddr(pcie_dma_ctrl_axi[0].araddr),
    .axil_dma_ctrl0_arprot(pcie_dma_ctrl_axi[0].arprot),
    .axil_dma_ctrl0_arready(pcie_dma_ctrl_axi[0].arready),
    .axil_dma_ctrl0_arvalid(pcie_dma_ctrl_axi[0].arvalid),
    .axil_dma_ctrl0_awaddr(pcie_dma_ctrl_axi[0].awaddr),
    .axil_dma_ctrl0_awprot(pcie_dma_ctrl_axi[0].awprot),
    .axil_dma_ctrl0_awready(pcie_dma_ctrl_axi[0].awready),
    .axil_dma_ctrl0_awvalid(pcie_dma_ctrl_axi[0].awvalid),
    .axil_dma_ctrl0_bready(pcie_dma_ctrl_axi[0].bready),
    .axil_dma_ctrl0_bresp(pcie_dma_ctrl_axi[0].bresp),
    .axil_dma_ctrl0_bvalid(pcie_dma_ctrl_axi[0].bvalid),
    .axil_dma_ctrl0_rdata(pcie_dma_ctrl_axi[0].rdata),
    .axil_dma_ctrl0_rready(pcie_dma_ctrl_axi[0].rready),
    .axil_dma_ctrl0_rresp(pcie_dma_ctrl_axi[0].rresp),
    .axil_dma_ctrl0_rvalid(pcie_dma_ctrl_axi[0].rvalid),
    .axil_dma_ctrl0_wdata(pcie_dma_ctrl_axi[0].wdata),
    .axil_dma_ctrl0_wready(pcie_dma_ctrl_axi[0].wready),
    .axil_dma_ctrl0_wstrb(pcie_dma_ctrl_axi[0].wstrb),
    .axil_dma_ctrl0_wvalid(pcie_dma_ctrl_axi[0].wvalid),
    
    .axil_dma_ctrl1_araddr(pcie_dma_ctrl_axi[1].araddr),
    .axil_dma_ctrl1_arprot(pcie_dma_ctrl_axi[1].arprot),
    .axil_dma_ctrl1_arready(pcie_dma_ctrl_axi[1].arready),
    .axil_dma_ctrl1_arvalid(pcie_dma_ctrl_axi[1].arvalid),
    .axil_dma_ctrl1_awaddr(pcie_dma_ctrl_axi[1].awaddr),
    .axil_dma_ctrl1_awprot(pcie_dma_ctrl_axi[1].awprot),
    .axil_dma_ctrl1_awready(pcie_dma_ctrl_axi[1].awready),
    .axil_dma_ctrl1_awvalid(pcie_dma_ctrl_axi[1].awvalid),
    .axil_dma_ctrl1_bready(pcie_dma_ctrl_axi[1].bready),
    .axil_dma_ctrl1_bresp(pcie_dma_ctrl_axi[1].bresp),
    .axil_dma_ctrl1_bvalid(pcie_dma_ctrl_axi[1].bvalid),
    .axil_dma_ctrl1_rdata(pcie_dma_ctrl_axi[1].rdata),
    .axil_dma_ctrl1_rready(pcie_dma_ctrl_axi[1].rready),
    .axil_dma_ctrl1_rresp(pcie_dma_ctrl_axi[1].rresp),
    .axil_dma_ctrl1_rvalid(pcie_dma_ctrl_axi[1].rvalid),
    .axil_dma_ctrl1_wdata(pcie_dma_ctrl_axi[1].wdata),
    .axil_dma_ctrl1_wready(pcie_dma_ctrl_axi[1].wready),
    .axil_dma_ctrl1_wstrb(pcie_dma_ctrl_axi[1].wstrb),
    .axil_dma_ctrl1_wvalid(pcie_dma_ctrl_axi[1].wvalid),

    .axil_dma_ctrl2_araddr(pcie_dma_ctrl_axi[2].araddr),
    .axil_dma_ctrl2_arprot(pcie_dma_ctrl_axi[2].arprot),
    .axil_dma_ctrl2_arready(pcie_dma_ctrl_axi[2].arready),
    .axil_dma_ctrl2_arvalid(pcie_dma_ctrl_axi[2].arvalid),
    .axil_dma_ctrl2_awaddr(pcie_dma_ctrl_axi[2].awaddr),
    .axil_dma_ctrl2_awprot(pcie_dma_ctrl_axi[2].awprot),
    .axil_dma_ctrl2_awready(pcie_dma_ctrl_axi[2].awready),
    .axil_dma_ctrl2_awvalid(pcie_dma_ctrl_axi[2].awvalid),
    .axil_dma_ctrl2_bready(pcie_dma_ctrl_axi[2].bready),
    .axil_dma_ctrl2_bresp(pcie_dma_ctrl_axi[2].bresp),
    .axil_dma_ctrl2_bvalid(pcie_dma_ctrl_axi[2].bvalid),
    .axil_dma_ctrl2_rdata(pcie_dma_ctrl_axi[2].rdata),
    .axil_dma_ctrl2_rready(pcie_dma_ctrl_axi[2].rready),
    .axil_dma_ctrl2_rresp(pcie_dma_ctrl_axi[2].rresp),
    .axil_dma_ctrl2_rvalid(pcie_dma_ctrl_axi[2].rvalid),
    .axil_dma_ctrl2_wdata(pcie_dma_ctrl_axi[2].wdata),
    .axil_dma_ctrl2_wready(pcie_dma_ctrl_axi[2].wready),
    .axil_dma_ctrl2_wstrb(pcie_dma_ctrl_axi[2].wstrb),
    .axil_dma_ctrl2_wvalid(pcie_dma_ctrl_axi[2].wvalid),
    
    .axil_dma_ctrl3_araddr(pcie_dma_ctrl_axi[3].araddr),
    .axil_dma_ctrl3_arprot(pcie_dma_ctrl_axi[3].arprot),
    .axil_dma_ctrl3_arready(pcie_dma_ctrl_axi[3].arready),
    .axil_dma_ctrl3_arvalid(pcie_dma_ctrl_axi[3].arvalid),
    .axil_dma_ctrl3_awaddr(pcie_dma_ctrl_axi[3].awaddr),
    .axil_dma_ctrl3_awprot(pcie_dma_ctrl_axi[3].awprot),
    .axil_dma_ctrl3_awready(pcie_dma_ctrl_axi[3].awready),
    .axil_dma_ctrl3_awvalid(pcie_dma_ctrl_axi[3].awvalid),
    .axil_dma_ctrl3_bready(pcie_dma_ctrl_axi[3].bready),
    .axil_dma_ctrl3_bresp(pcie_dma_ctrl_axi[3].bresp),
    .axil_dma_ctrl3_bvalid(pcie_dma_ctrl_axi[3].bvalid),
    .axil_dma_ctrl3_rdata(pcie_dma_ctrl_axi[3].rdata),
    .axil_dma_ctrl3_rready(pcie_dma_ctrl_axi[3].rready),
    .axil_dma_ctrl3_rresp(pcie_dma_ctrl_axi[3].rresp),
    .axil_dma_ctrl3_rvalid(pcie_dma_ctrl_axi[3].rvalid),
    .axil_dma_ctrl3_wdata(pcie_dma_ctrl_axi[3].wdata),
    .axil_dma_ctrl3_wready(pcie_dma_ctrl_axi[3].wready),
    .axil_dma_ctrl3_wstrb(pcie_dma_ctrl_axi[3].wstrb),
    .axil_dma_ctrl3_wvalid(pcie_dma_ctrl_axi[3].wvalid),    

    .pcie_m_axi0_awaddr (pcie_dma_maxi[0].awaddr),
    .pcie_m_axi0_awburst(pcie_dma_maxi[0].awburst),
    .pcie_m_axi0_awcache(pcie_dma_maxi[0].awcache),
    .pcie_m_axi0_awlen  (pcie_dma_maxi[0].awlen),
    .pcie_m_axi0_awlock (pcie_dma_maxi[0].awlock),
    .pcie_m_axi0_awprot (pcie_dma_maxi[0].awprot),
    .pcie_m_axi0_awqos  (pcie_dma_maxi[0].awqos),
    .pcie_m_axi0_awready(pcie_dma_maxi[0].awready),
    .pcie_m_axi0_awregion(4'b0000),
    .pcie_m_axi0_awsize (pcie_dma_maxi[0].awsize),
    .pcie_m_axi0_awvalid(pcie_dma_maxi[0].awvalid),
    .pcie_m_axi0_bready (pcie_dma_maxi[0].bready),
    .pcie_m_axi0_bresp  (pcie_dma_maxi[0].bresp),
    .pcie_m_axi0_bvalid (pcie_dma_maxi[0].bvalid),
    .pcie_m_axi0_wdata  (pcie_dma_maxi[0].wdata),
    .pcie_m_axi0_wlast  (pcie_dma_maxi[0].wlast),
    .pcie_m_axi0_wready (pcie_dma_maxi[0].wready),
    .pcie_m_axi0_wstrb  (pcie_dma_maxi[0].wstrb),
    .pcie_m_axi0_wvalid (pcie_dma_maxi[0].wvalid),

    .pcie_m_axi1_awaddr (pcie_dma_maxi[1].awaddr),
    .pcie_m_axi1_awburst(pcie_dma_maxi[1].awburst),
    .pcie_m_axi1_awcache(pcie_dma_maxi[1].awcache),
    .pcie_m_axi1_awlen  (pcie_dma_maxi[1].awlen),
    .pcie_m_axi1_awlock (pcie_dma_maxi[1].awlock),
    .pcie_m_axi1_awprot (pcie_dma_maxi[1].awprot),
    .pcie_m_axi1_awqos  (pcie_dma_maxi[1].awqos),
    .pcie_m_axi1_awready(pcie_dma_maxi[1].awready),
    .pcie_m_axi1_awregion(4'b0000),
    .pcie_m_axi1_awsize (pcie_dma_maxi[1].awsize),
    .pcie_m_axi1_awvalid(pcie_dma_maxi[1].awvalid),
    .pcie_m_axi1_bready (pcie_dma_maxi[1].bready),
    .pcie_m_axi1_bresp  (pcie_dma_maxi[1].bresp),
    .pcie_m_axi1_bvalid (pcie_dma_maxi[1].bvalid),
    .pcie_m_axi1_wdata  (pcie_dma_maxi[1].wdata),
    .pcie_m_axi1_wlast  (pcie_dma_maxi[1].wlast),
    .pcie_m_axi1_wready (pcie_dma_maxi[1].wready),
    .pcie_m_axi1_wstrb  (pcie_dma_maxi[1].wstrb),
    .pcie_m_axi1_wvalid (pcie_dma_maxi[1].wvalid),

    .pcie_m_axi2_awaddr (pcie_dma_maxi[2].awaddr),
    .pcie_m_axi2_awburst(pcie_dma_maxi[2].awburst),
    .pcie_m_axi2_awcache(pcie_dma_maxi[2].awcache),
    .pcie_m_axi2_awlen  (pcie_dma_maxi[2].awlen),
    .pcie_m_axi2_awlock (pcie_dma_maxi[2].awlock),
    .pcie_m_axi2_awprot (pcie_dma_maxi[2].awprot),
    .pcie_m_axi2_awqos  (pcie_dma_maxi[2].awqos),
    .pcie_m_axi2_awready(pcie_dma_maxi[2].awready),
    .pcie_m_axi2_awregion(4'b0000),
    .pcie_m_axi2_awsize (pcie_dma_maxi[2].awsize),
    .pcie_m_axi2_awvalid(pcie_dma_maxi[2].awvalid),
    .pcie_m_axi2_bready (pcie_dma_maxi[2].bready),
    .pcie_m_axi2_bresp  (pcie_dma_maxi[2].bresp),
    .pcie_m_axi2_bvalid (pcie_dma_maxi[2].bvalid),
    .pcie_m_axi2_wdata  (pcie_dma_maxi[2].wdata),
    .pcie_m_axi2_wlast  (pcie_dma_maxi[2].wlast),
    .pcie_m_axi2_wready (pcie_dma_maxi[2].wready),
    .pcie_m_axi2_wstrb  (pcie_dma_maxi[2].wstrb),
    .pcie_m_axi2_wvalid (pcie_dma_maxi[2].wvalid),
    
    .pcie_m_axi3_awaddr (pcie_dma_maxi[3].awaddr),
    .pcie_m_axi3_awburst(pcie_dma_maxi[3].awburst),
    .pcie_m_axi3_awcache(pcie_dma_maxi[3].awcache),
    .pcie_m_axi3_awlen  (pcie_dma_maxi[3].awlen),
    .pcie_m_axi3_awlock (pcie_dma_maxi[3].awlock),
    .pcie_m_axi3_awprot (pcie_dma_maxi[3].awprot),
    .pcie_m_axi3_awqos  (pcie_dma_maxi[3].awqos),
    .pcie_m_axi3_awready(pcie_dma_maxi[3].awready),
    .pcie_m_axi3_awregion(4'b0000),
    .pcie_m_axi3_awsize (pcie_dma_maxi[3].awsize),
    .pcie_m_axi3_awvalid(pcie_dma_maxi[3].awvalid),
    .pcie_m_axi3_bready (pcie_dma_maxi[3].bready),
    .pcie_m_axi3_bresp  (pcie_dma_maxi[3].bresp),
    .pcie_m_axi3_bvalid (pcie_dma_maxi[3].bvalid),
    .pcie_m_axi3_wdata  (pcie_dma_maxi[3].wdata),
    .pcie_m_axi3_wlast  (pcie_dma_maxi[3].wlast),
    .pcie_m_axi3_wready (pcie_dma_maxi[3].wready),
    .pcie_m_axi3_wstrb  (pcie_dma_maxi[3].wstrb),
    .pcie_m_axi3_wvalid (pcie_dma_maxi[3].wvalid)        

);

assign gpi = 0;

util_reg util_reg_i
(
    .ctrl_if(util_reg_if),
    
    .gpo(gpo),
    .gpi(gpi),
    .fan_pwm(),
    .datecode(DATE_CODE),
    .timecode(TIME_CODE)         
);  

// assign leds[0] = gpo[0];



wire [7:0]   timing_pulses;
wire pps;
wire start_of_cpi;
wire start_of_pulse;

timing_engine timing_engine_i
(
    .clk(axi_pcie_clk),    
    .pps(pps),
    
    .ctrl_if(timing_if),
    
    .start_of_cpi(start_of_cpi),
    .start_of_pulse(start_of_pulse),
    .timing_pulses(timing_pulses)
);  

data_gen 
# (
    .NUM_CH(NUM_DMA)
) data_gen_i (
    .ctrl_if(data_gen_if),
    .trigger(start_of_pulse),
    .data_out(pcie_dma_axis)
);       

// The CPU Side driver reads this list to determine how many devices to make
// Must expand this list to add more DMA channels
axi_descriptor  
# (
    .DESCRIPTOR_WIDTH(128), 
    .DESCRIPTOR_LENGTH(NUM_DMA+1)
) axi_descriptor_i 
(
    .axi(descriptors_if),
    .descriptor_list('{{64'b0, 32'h00000000, 32'h10000},  // AXI Registers
                       {64'b0, 32'h00100000, 32'h20000},  // DMA 0
                       {64'b0, 32'h00110000, 32'h20000},  // DMA 1
                       {64'b0, 32'h00120000, 32'h20000},  // DMA 2
                       {64'b0, 32'h00130000, 32'h20000}   // DMA 3
                    })
);
    

genvar dma_index;
generate
    for (dma_index=0; dma_index < NUM_DMA; dma_index++) begin   
        dma_engine_256 dma_engine_256_i (
            .ctrl_if(pcie_dma_ctrl_axi[dma_index]),
            .axis(pcie_dma_axis[dma_index]), // Stream Data In
            .axim(pcie_dma_maxi[dma_index]) // MM Data Out - Goes to Host Proc via PCIe
        );   
    end
endgenerate


endmodule

`resetall