diff --git a/src/cndm_proto/rtl/cndm_proto_core.sv b/src/cndm_proto/rtl/cndm_proto_core.sv index fd2b6d4..e1d4e33a 100644 --- a/src/cndm_proto/rtl/cndm_proto_core.sv +++ b/src/cndm_proto/rtl/cndm_proto_core.sv @@ -66,6 +66,7 @@ localparam RAM_SEL_W = dma_ram_wr.SEL_W; localparam PORT_OFFSET = 1; +// Interface array for control registers - common registers plus per-port registers taxi_axil_if #( .DATA_W(s_axil_wr.DATA_W), .ADDR_W(16), @@ -83,6 +84,7 @@ taxi_axil_if #( ) s_axil_ctrl[PORTS+PORT_OFFSET](); +// Interconnect to map common and per-port registers into linear address space taxi_axil_interconnect_1s #( .M_COUNT($size(s_axil_ctrl)), .ADDR_W(s_axil_wr.ADDR_W), @@ -108,6 +110,7 @@ port_intercon_inst ( .m_axil_rd(s_axil_ctrl) ); +// Common control registers logic s_axil_awready_reg = 1'b0; logic s_axil_wready_reg = 1'b0; logic s_axil_bvalid_reg = 1'b0; @@ -171,6 +174,7 @@ always_ff @(posedge clk) begin end end +// DMA interface multiplexing across ports, enabling ports to share the host DMA engine taxi_dma_desc_if #( .SRC_ADDR_W(dma_rd_desc_req.SRC_ADDR_W), .SRC_SEL_EN(dma_rd_desc_req.SRC_SEL_EN), @@ -254,6 +258,7 @@ dma_mux_inst ( for (genvar p = 0; p < PORTS; p = p + 1) begin : port + // Per-port datapath instance cndm_proto_port #( .PORTS(PORTS) ) diff --git a/src/cndm_proto/rtl/cndm_proto_cpl_wr.sv b/src/cndm_proto/rtl/cndm_proto_cpl_wr.sv index 8b9eca6..3eb4c2d 100644 --- a/src/cndm_proto/rtl/cndm_proto_cpl_wr.sv +++ b/src/cndm_proto/rtl/cndm_proto_cpl_wr.sv @@ -27,6 +27,9 @@ module cndm_proto_cpl_wr taxi_dma_desc_if.sts_snk dma_wr_desc_sts, taxi_dma_ram_if.rd_slv dma_ram_rd, + /* + * Control signals from port-level control registers + */ input wire logic txcq_en, input wire logic [3:0] txcq_size, input wire logic [63:0] txcq_base_addr, @@ -36,10 +39,18 @@ module cndm_proto_cpl_wr input wire logic [63:0] rxcq_base_addr, output wire logic [15:0] rxcq_prod, + /* + * Completion inputs from TX and RX datapaths + */ taxi_axis_if.snk axis_cpl[2], + + /* + * Interrupt request output + */ output wire logic irq ); +// Combined completion bus - carries both RX and TX completions, identified by tid taxi_axis_if #( .DATA_W(axis_cpl[0].DATA_W), .KEEP_EN(axis_cpl[0].KEEP_EN), @@ -54,6 +65,7 @@ taxi_axis_if #( .USER_W(axis_cpl[0].USER_W) ) cpl_comb(); +// Completion write control state machine localparam [2:0] STATE_IDLE = 0, STATE_RX_CPL = 1, @@ -76,6 +88,7 @@ assign irq = irq_reg; always_ff @(posedge clk) begin cpl_comb.tready <= 1'b0; + // Host DMA control descriptor to manage transferring completions to host memory dma_wr_desc_req.req_src_sel <= '0; dma_wr_desc_req.req_src_asid <= '0; dma_wr_desc_req.req_dst_sel <= '0; @@ -89,6 +102,7 @@ always_ff @(posedge clk) begin dma_wr_desc_req.req_user <= '0; dma_wr_desc_req.req_valid <= dma_wr_desc_req.req_valid && !dma_wr_desc_req.req_ready; + // reset pointers when disabled if (!txcq_en) begin txcq_prod_ptr_reg <= '0; end @@ -101,12 +115,19 @@ always_ff @(posedge clk) begin case (state_reg) STATE_IDLE: begin + // idle state - wait for completion + dma_wr_desc_req.req_src_addr <= '0; + // arbitrate between TX and RX completions if (cpl_comb.tid == 0) begin + // compute host address - base address plus producer pointer, modulo queue size dma_wr_desc_req.req_dst_addr <= txcq_base_addr + 64'(16'(txcq_prod_ptr_reg & ({16{1'b1}} >> (16 - txcq_size))) * 16); + // phase tag is the inverted version of the extended producer pointer + // each "pass" over the queue elements will invert the phase tag phase_tag_reg <= !txcq_prod_ptr_reg[txcq_size]; if (cpl_comb.tvalid && !cpl_comb.tready) begin + // increment pointer and start transfer operation, if the queue is enabled txcq_prod_ptr_reg <= txcq_prod_ptr_reg + 1; if (txcq_en) begin dma_wr_desc_req.req_valid <= 1'b1; @@ -116,9 +137,13 @@ always_ff @(posedge clk) begin end end end else begin + // compute host address - base address plus producer pointer, modulo queue size dma_wr_desc_req.req_dst_addr <= rxcq_base_addr + 64'(16'(rxcq_prod_ptr_reg & ({16{1'b1}} >> (16 - rxcq_size))) * 16); + // phase tag is the inverted version of the extended producer pointer + // each "pass" over the queue elements will invert the phase tag phase_tag_reg <= !rxcq_prod_ptr_reg[rxcq_size]; if (cpl_comb.tvalid && !cpl_comb.tready) begin + // increment pointer and start transfer operation, if the queue is enabled rxcq_prod_ptr_reg <= rxcq_prod_ptr_reg + 1; if (rxcq_en) begin dma_wr_desc_req.req_valid <= 1'b1; @@ -130,6 +155,7 @@ always_ff @(posedge clk) begin end end STATE_WRITE_DATA: begin + // write data state - wait for host DMA write to complete, issue IRQ to host if (dma_wr_desc_sts.sts_valid) begin cpl_comb.tready <= 1'b1; irq_reg <= 1'b1; @@ -149,6 +175,7 @@ always_ff @(posedge clk) begin end end +// mux for completions taxi_axis_arb_mux #( .S_COUNT(2), .UPDATE_TID(1), @@ -170,7 +197,7 @@ mux_inst ( .m_axis(cpl_comb) ); -// extract parameters +// "emulate" DMA RAM - pass completion data to host DMA engine along with phase tag bit localparam SEGS = dma_ram_rd.SEGS; localparam SEG_ADDR_W = dma_ram_rd.SEG_ADDR_W; localparam SEG_DATA_W = dma_ram_rd.SEG_DATA_W; diff --git a/src/cndm_proto/rtl/cndm_proto_desc_rd.sv b/src/cndm_proto/rtl/cndm_proto_desc_rd.sv index 33dab59..9d908e8 100644 --- a/src/cndm_proto/rtl/cndm_proto_desc_rd.sv +++ b/src/cndm_proto/rtl/cndm_proto_desc_rd.sv @@ -27,6 +27,9 @@ module cndm_proto_desc_rd taxi_dma_desc_if.sts_snk dma_rd_desc_sts, taxi_dma_ram_if.wr_slv dma_ram_wr, + /* + * Control signals from port-level control registers + */ input wire logic txq_en, input wire logic [3:0] txq_size, input wire logic [63:0] txq_base_addr, @@ -38,10 +41,14 @@ module cndm_proto_desc_rd input wire logic [15:0] rxq_prod, output wire logic [15:0] rxq_cons, + /* + * Descriptor request interface + */ input wire logic [1:0] desc_req, taxi_axis_if.src axis_desc[2] ); +// Control for internal streaming DMA engine localparam RAM_ADDR_W = 16; taxi_dma_desc_if #( @@ -61,6 +68,7 @@ taxi_dma_desc_if #( .USER_W(1) ) dma_desc(); +// Descriptor read control state machine localparam [2:0] STATE_IDLE = 0, STATE_READ_DESC = 1, @@ -78,8 +86,7 @@ assign txq_cons = txq_cons_ptr_reg; assign rxq_cons = rxq_cons_ptr_reg; always_ff @(posedge clk) begin - // axis_desc.tready <= 1'b0; - + // Host DMA control descriptor to manage transferring descriptors from host memory dma_rd_desc_req.req_src_sel <= '0; dma_rd_desc_req.req_src_asid <= '0; dma_rd_desc_req.req_dst_sel <= '0; @@ -93,6 +100,7 @@ always_ff @(posedge clk) begin dma_rd_desc_req.req_user <= '0; dma_rd_desc_req.req_valid <= dma_rd_desc_req.req_valid && !dma_rd_desc_req.req_ready; + // Streaming DMA control descriptor to manage reading descriptors dma_desc.req_src_sel <= '0; dma_desc.req_src_asid <= '0; dma_desc.req_dst_addr <= '0; @@ -106,8 +114,10 @@ always_ff @(posedge clk) begin dma_desc.req_user <= '0; dma_desc.req_valid <= dma_desc.req_valid && !dma_desc.req_ready; + // Latch descriptor request pulses desc_req_reg <= desc_req_reg | desc_req; + // reset pointers when queues are disabled if (!txq_en) begin txq_cons_ptr_reg <= '0; end @@ -118,29 +128,37 @@ always_ff @(posedge clk) begin case (state_reg) STATE_IDLE: begin + // idle state - wait for descriptor request + // favor RX over TX if (desc_req_reg[1]) begin + // compute host address - base address plus producer pointer, modulo queue size dma_rd_desc_req.req_src_addr <= rxq_base_addr + 64'(16'(rxq_cons_ptr_reg & ({16{1'b1}} >> (16 - rxq_size))) * 16); dma_desc.req_dest <= 1'b1; desc_req_reg[1] <= 1'b0; if (rxq_cons_ptr_reg == rxq_prod || !rxq_en) begin + // queue is empty or disabled, generate invalid descriptor dma_desc.req_user <= 1'b1; dma_desc.req_valid <= 1'b1; state_reg <= STATE_TX_DESC; end else begin + // increment pointer and start transfer operation dma_desc.req_user <= 1'b0; dma_rd_desc_req.req_valid <= 1'b1; rxq_cons_ptr_reg <= rxq_cons_ptr_reg + 1; state_reg <= STATE_READ_DESC; end end else if (desc_req_reg[0]) begin + // compute host address - base address plus producer pointer, modulo queue size dma_rd_desc_req.req_src_addr <= txq_base_addr + 64'(16'(txq_cons_ptr_reg & ({16{1'b1}} >> (16 - txq_size))) * 16); dma_desc.req_dest <= 1'b0; desc_req_reg[0] <= 1'b0; if (txq_cons_ptr_reg == txq_prod || !txq_en) begin + // queue is empty or disabled, generate invalid descriptor dma_desc.req_user <= 1'b1; dma_desc.req_valid <= 1'b1; state_reg <= STATE_TX_DESC; end else begin + // increment pointer and start transfer operation dma_desc.req_user <= 1'b0; dma_rd_desc_req.req_valid <= 1'b1; txq_cons_ptr_reg <= txq_cons_ptr_reg + 1; @@ -149,12 +167,14 @@ always_ff @(posedge clk) begin end end STATE_READ_DESC: begin + // read descriptor state - wait for host DMA read, start streaming DMA read if (dma_rd_desc_sts.sts_valid) begin dma_desc.req_valid <= 1'b1; state_reg <= STATE_TX_DESC; end end STATE_TX_DESC: begin + // transmit descriptor state - wait for streaming DMA read if (dma_desc.sts_valid) begin state_reg <= STATE_IDLE; end @@ -169,6 +189,7 @@ always_ff @(posedge clk) begin end end +// local RAM to store the descriptor temporarily taxi_dma_ram_if #( .SEGS(dma_ram_wr.SEGS), .SEG_ADDR_W(dma_ram_wr.SEG_ADDR_W), @@ -195,6 +216,7 @@ ram_inst ( .dma_ram_rd(dma_ram_rd) ); +// streaming DMA engine to read descriptor from local RAM taxi_axis_if #( .DATA_W(axis_desc[0].DATA_W), .KEEP_EN(axis_desc[0].KEEP_EN), @@ -235,6 +257,7 @@ dma_inst ( .enable(1'b1) ); +// demux module to route descriptor appropriately taxi_axis_demux #( .M_COUNT(2), .TDEST_ROUTE(1) diff --git a/src/cndm_proto/rtl/cndm_proto_pcie_us.sv b/src/cndm_proto/rtl/cndm_proto_pcie_us.sv index f082dd5..6fd5fea 100644 --- a/src/cndm_proto/rtl/cndm_proto_pcie_us.sv +++ b/src/cndm_proto/rtl/cndm_proto_pcie_us.sv @@ -95,6 +95,7 @@ module cndm_proto_pcie_us #( localparam CL_PORTS = $clog2(PORTS); +// PCIe BAR for device control localparam AXIL_DATA_W = 32; localparam AXIL_ADDR_W = BAR0_APERTURE; @@ -138,6 +139,7 @@ pcie_axil_master_inst ( .stat_err_uncor() ); +// Host PCIe DMA engine localparam AXIS_PCIE_DATA_W = m_axis_pcie_rq.DATA_W; localparam PCIE_ADDR_W = 64; @@ -383,6 +385,7 @@ dma_if_inst ( .stat_wr_tx_stall(stat_wr_tx_stall) ); +// MSI interrupts wire [PORTS-1:0] irq; wire [31:0] msi_irq = 32'(irq); diff --git a/src/cndm_proto/rtl/cndm_proto_port.sv b/src/cndm_proto/rtl/cndm_proto_port.sv index a4f0e19..384dbec 100644 --- a/src/cndm_proto/rtl/cndm_proto_port.sv +++ b/src/cndm_proto/rtl/cndm_proto_port.sv @@ -53,6 +53,7 @@ module cndm_proto_port #( taxi_axis_if.snk mac_axis_rx ); +// Port-level control registers localparam AXIL_ADDR_W = s_axil_wr.ADDR_W; localparam AXIL_DATA_W = s_axil_wr.DATA_W; @@ -207,6 +208,7 @@ always_ff @(posedge clk) begin end end +// DMA mux logic to share host DMA engine between descriptor read and transmit logic taxi_dma_desc_if #( .SRC_ADDR_W(dma_rd_desc_req.SRC_ADDR_W), .SRC_SEL_EN(dma_rd_desc_req.SRC_SEL_EN), @@ -264,6 +266,7 @@ rd_dma_mux_inst ( .client_ram_wr(dma_ram_wr_int) ); +// DMA mux logic to share host DMA engine between completion write and receive logic taxi_dma_desc_if #( .SRC_ADDR_W(dma_wr_desc_req.SRC_ADDR_W), .SRC_SEL_EN(dma_wr_desc_req.SRC_SEL_EN), @@ -322,6 +325,7 @@ wr_dma_mux_inst ( .client_ram_rd(dma_ram_rd_int) ); +// Descriptor read logic wire [1:0] desc_req; taxi_axis_if #( @@ -334,15 +338,6 @@ taxi_axis_if #( .USER_W(1) ) axis_desc[2](); -taxi_axis_if #( - .DATA_W(16*8), - .KEEP_EN(1), - .LAST_EN(1), - .ID_EN(1), // TODO - .DEST_EN(0), - .USER_EN(0) -) axis_cpl[2](); - cndm_proto_desc_rd desc_rd_inst ( .clk(clk), @@ -355,6 +350,9 @@ desc_rd_inst ( .dma_rd_desc_sts(dma_rd_desc_int[0]), .dma_ram_wr(dma_ram_wr_int[0]), + /* + * Control signals from port-level control registers + */ .txq_en(txq_en_reg), .txq_size(txq_size_reg), .txq_base_addr(txq_base_addr_reg), @@ -366,10 +364,23 @@ desc_rd_inst ( .rxq_prod(rxq_prod_reg), .rxq_cons(rxq_cons), + /* + * Descriptor request interface + */ .desc_req(desc_req), .axis_desc(axis_desc) ); +// Completion write logic +taxi_axis_if #( + .DATA_W(16*8), + .KEEP_EN(1), + .LAST_EN(1), + .ID_EN(1), // TODO + .DEST_EN(0), + .USER_EN(0) +) axis_cpl[2](); + cndm_proto_cpl_wr cpl_wr_inst ( .clk(clk), @@ -382,6 +393,9 @@ cpl_wr_inst ( .dma_wr_desc_sts(dma_wr_desc_int[0]), .dma_ram_rd(dma_ram_rd_int[0]), + /* + * Control signals from port-level control registers + */ .txcq_en(txcq_en_reg), .txcq_size(txcq_size_reg), .txcq_base_addr(txcq_base_addr_reg), @@ -391,10 +405,18 @@ cpl_wr_inst ( .rxcq_base_addr(rxcq_base_addr_reg), .rxcq_prod(rxcq_prod), + /* + * Completion inputs from TX and RX datapaths + */ .axis_cpl(axis_cpl), + + /* + * Interrupt request output + */ .irq(irq) ); +// Transmit datapath and async FIFO taxi_axis_if #( .DATA_W(mac_axis_tx.DATA_W), .USER_EN(1), @@ -461,12 +483,24 @@ tx_inst ( .dma_rd_desc_sts(dma_rd_desc_int[1]), .dma_ram_wr(dma_ram_wr_int[1]), + /* + * Descriptor request + */ .desc_req(desc_req[0]), .axis_desc(axis_desc[0]), + + /* + * Transmit data output + */ .tx_data(mac_tx_int), + + /* + * Completion output + */ .axis_cpl(axis_cpl[0]) ); +// Receive datapath and async FIFO taxi_axis_if #( .DATA_W(mac_axis_rx.DATA_W), .USER_EN(1), @@ -533,9 +567,20 @@ rx_inst ( .dma_wr_desc_sts(dma_wr_desc_int[1]), .dma_ram_rd(dma_ram_rd_int[1]), + /* + * Receive data input + */ .rx_data(mac_rx_int), + + /* + * Descriptor request + */ .desc_req(desc_req[1]), .axis_desc(axis_desc[1]), + + /* + * Completion output + */ .axis_cpl(axis_cpl[1]) ); diff --git a/src/cndm_proto/rtl/cndm_proto_rx.sv b/src/cndm_proto/rtl/cndm_proto_rx.sv index eef6f6f..ff9a6fa 100644 --- a/src/cndm_proto/rtl/cndm_proto_rx.sv +++ b/src/cndm_proto/rtl/cndm_proto_rx.sv @@ -27,12 +27,24 @@ module cndm_proto_rx taxi_dma_desc_if.sts_snk dma_wr_desc_sts, taxi_dma_ram_if.rd_slv dma_ram_rd, + /* + * Receive data input + */ taxi_axis_if.snk rx_data, + + /* + * Descriptor request + */ output wire logic desc_req, taxi_axis_if.snk axis_desc, + + /* + * Completion output + */ taxi_axis_if.src axis_cpl ); +// Control for internal streaming DMA engine localparam RAM_ADDR_W = 16; taxi_dma_desc_if #( @@ -51,6 +63,7 @@ taxi_dma_desc_if #( .USER_W(1) ) dma_desc(); +// Receive datapath control state machine localparam [2:0] STATE_IDLE = 0, STATE_RX_DATA = 1, @@ -68,6 +81,7 @@ always_ff @(posedge clk) begin axis_desc.tready <= 1'b0; + // Host DMA control descriptor to manage transferring packet data to host memory dma_wr_desc_req.req_src_sel <= '0; dma_wr_desc_req.req_src_asid <= '0; dma_wr_desc_req.req_dst_sel <= '0; @@ -80,6 +94,7 @@ always_ff @(posedge clk) begin dma_wr_desc_req.req_user <= '0; dma_wr_desc_req.req_valid <= dma_wr_desc_req.req_valid && !dma_wr_desc_req.req_ready; + // Streaming DMA control descriptor to transfer packet data dma_desc.req_src_addr <= '0; dma_desc.req_src_sel <= '0; dma_desc.req_src_asid <= '0; @@ -104,10 +119,12 @@ always_ff @(posedge clk) begin case (state_reg) STATE_IDLE: begin + // idle state - start streaming DMA engine to receive packet dma_desc.req_valid <= 1'b1; state_reg <= STATE_RX_DATA; end STATE_RX_DATA: begin + // RX data state - wait for streaming DMA, store packet length and start descriptor read operation dma_wr_desc_req.req_len <= 20'(dma_desc.sts_len); axis_cpl.tdata[47:32] <= 16'(dma_desc.sts_len); if (dma_desc.sts_valid) begin @@ -116,12 +133,15 @@ always_ff @(posedge clk) begin end end STATE_READ_DESC: begin + // read descriptor state - wait for descriptor, start host DMA write axis_desc.tready <= 1'b1; + // host address from descriptor dma_wr_desc_req.req_src_addr <= '0; dma_wr_desc_req.req_dst_addr <= axis_desc.tdata[127:64]; if (axis_desc.tvalid && axis_desc.tready) begin + // limit transfer length to descriptor size if (dma_wr_desc_req.req_len > 20'(axis_desc.tdata[47:32])) begin dma_wr_desc_req.req_len <= 20'(axis_desc.tdata[47:32]); end @@ -136,6 +156,7 @@ always_ff @(posedge clk) begin end end STATE_WRITE_DATA: begin + // write data state - wait for host DMA write to complete, generate completion if (dma_wr_desc_sts.sts_valid) begin axis_cpl.tvalid <= 1'b1; state_reg <= STATE_IDLE; @@ -151,6 +172,7 @@ always_ff @(posedge clk) begin end end +// local RAM to store the packet data temporarily taxi_dma_ram_if #( .SEGS(dma_ram_rd.SEGS), .SEG_ADDR_W(dma_ram_rd.SEG_ADDR_W), @@ -177,6 +199,7 @@ ram_inst ( .dma_ram_rd(dma_ram_rd) ); +// streaming DMA engine to write packet data to local RAM taxi_dma_client_axis_sink dma_inst ( .clk(clk), diff --git a/src/cndm_proto/rtl/cndm_proto_tx.sv b/src/cndm_proto/rtl/cndm_proto_tx.sv index 6ffd2ad..c526a59 100644 --- a/src/cndm_proto/rtl/cndm_proto_tx.sv +++ b/src/cndm_proto/rtl/cndm_proto_tx.sv @@ -27,12 +27,24 @@ module cndm_proto_tx taxi_dma_desc_if.sts_snk dma_rd_desc_sts, taxi_dma_ram_if.wr_slv dma_ram_wr, + /* + * Descriptor request + */ output wire logic desc_req, taxi_axis_if.snk axis_desc, + + /* + * Transmit data output + */ taxi_axis_if.src tx_data, + + /* + * Completion output + */ taxi_axis_if.src axis_cpl ); +// Control for internal streaming DMA engine localparam RAM_ADDR_W = 16; taxi_dma_desc_if #( @@ -51,6 +63,7 @@ taxi_dma_desc_if #( .USER_W(1) ) dma_desc(); +// Transmit datapath control state machine localparam [2:0] STATE_IDLE = 0, STATE_READ_DESC = 1, @@ -68,6 +81,7 @@ always_ff @(posedge clk) begin axis_desc.tready <= 1'b0; + // Host DMA control descriptor to manage transferring packet data from host memory dma_rd_desc_req.req_src_sel <= '0; dma_rd_desc_req.req_src_asid <= '0; dma_rd_desc_req.req_dst_sel <= '0; @@ -80,6 +94,7 @@ always_ff @(posedge clk) begin dma_rd_desc_req.req_user <= '0; dma_rd_desc_req.req_valid <= dma_rd_desc_req.req_valid && !dma_rd_desc_req.req_ready; + // Streaming DMA control descriptor to transfer packet data dma_desc.req_src_sel <= '0; dma_desc.req_src_asid <= '0; dma_desc.req_dst_addr <= '0; @@ -102,10 +117,12 @@ always_ff @(posedge clk) begin case (state_reg) STATE_IDLE: begin + // idle state - start descriptor read operation desc_req_reg <= 1'b1; state_reg <= STATE_READ_DESC; end STATE_READ_DESC: begin + // read descriptor state - wait for descriptor, start host DMA read axis_desc.tready <= 1'b1; dma_rd_desc_req.req_src_addr <= axis_desc.tdata[127:64]; @@ -126,12 +143,14 @@ always_ff @(posedge clk) begin end end STATE_READ_DATA: begin + // read data state - wait for host DMA read, start streaming DMA read if (dma_rd_desc_sts.sts_valid) begin dma_desc.req_valid <= 1'b1; state_reg <= STATE_TX_DATA; end end STATE_TX_DATA: begin + // transmit data state - wait for streaming DMA read if (dma_desc.sts_valid) begin axis_cpl.tvalid <= 1'b1; state_reg <= STATE_IDLE; @@ -147,6 +166,7 @@ always_ff @(posedge clk) begin end end +// local RAM to store the packet data temporarily taxi_dma_ram_if #( .SEGS(dma_ram_wr.SEGS), .SEG_ADDR_W(dma_ram_wr.SEG_ADDR_W), @@ -173,6 +193,7 @@ ram_inst ( .dma_ram_rd(dma_ram_rd) ); +// streaming DMA engine to read packet data from local RAM taxi_dma_client_axis_source dma_inst ( .clk(clk),