以下描述了多种不同的 C2H 串流包。
常规包
常规 C2H 包既包含数据包又包含完成 (CMPT) 包。这两种包为一对一匹配。
常规 C2H 数据包可包含多个节拍。
-
s_axis_c2h_ctrl_qid
= C2H 描述符队列 ID。 -
s_axis_c2h_ctrl_len
= 包的长度。 -
s_axis_c2h_mty
= 在最后一个节拍中应设置空字节。 -
s_axis_c2h_ctrl_has_cmpt
=1'b1
。该数据包具有一个对应的 CMPT 包。
常规 C2H CMPT 包为一个节拍。
-
s_axis_c2h_cmpt_ctrl_qid
= 包的完成队列 ID。这可能与 C2H 描述符 QID 不同。 -
s_axis_c2h_cmpt_ctrl_cmpt_type
=HAS_PLD
。该完成包具有一个对应的数据包。 -
s_axis_c2h_cmpt_ctrl_wait_pld_pkt_id
= 此完成包必须等待具有此 ID 的数据包发送后,才能发送 CMPT 包。
当用户应用发送数据包时,必须计算每个包的包 ID 数量。第一个数据包的包 ID 为 1,此后每个数据包的包 ID 都会逐一递增。
对于常规 C2H 包,数据包和完成包一对一匹配。因此,s_axis_c2h_ctrl_has_cmpt
为 1'b1
的数据包的数量应该与 s_axis_c2h_cmpt_ctrl_cmpt_type
为 HAS_PLD
的 CMPT 包的数量相等。
QDMA Subsystem for PCIe 的完成输入 FIFO 深度较浅,仅为 2。为了提升性能,可为完成输入添加 FIFO,如下图所示。FIFO 的深度和宽度因用例而异。宽度取决于应用的最大 CMPT 大小,深度取决于性能需求。对于 64 字节 CMPT,为了达成最佳性能,建议使用深度 512。
当用户应用发送数据有效载荷时,它会对每个包进行计数。第一个包以 pkt_pld_id
1 开始。第二个包的 pkt_pld_id
为 2,以此类推。它是一个 16 位计数器,一旦计数达到 16'hffff,它就会复位为 0,重新开始计数。
用户应用会定义 CMPT 类型。
- 如果
s_axis_c2h_cmpt_ctrl_cmpt_type
为 HAS_PLD,则表示 CMPT 具有对应的数据有效载荷。用户应用必须将该包的pkt_pld_id
填入s_axis_c2h_cmpt_ctrl_wait_pld_pkt_id
字段中。DMA 仅在传出对应的数据有效载荷包后才会传出此 CMPT。 - 如果
s_axis_c2h_cmpt_ctrl_cmpt_type
为 NO_PLD_NO_WAIT,则表示 CMPT 没有任何数据有效载荷,因此无需等待有效载荷。然后 DMA 将传出此 CMPT。 - 如果
s_axis_c2h_cmpt_ctrl_cmpt_type
为 NO_PLD_BUT_WAIT,则表示 CMPT 没有对应的数据有效载荷包。CMPT 必须等待收到特定的数据有效载荷包后才会将其传出。因此,用户应用必须将该特定数据有效载荷的pld_pkt_id
填入s_axis_c2h_cmpt_ctrl_wait_pld_pkt_id
字段中。在传出具有该pld_pkt_id
的数据有效载荷之后,DMA 才会传出 CMPT。
即时数据包
用户应用可能具有如下类型的包:只写入完成环,而没有要传输到主机的对应数据包。此类包称为即时数据包。对于即时数据包,QDMA 不会发送数据有效载荷,但会写入 CMPT 队列。即时包不耗用描述符。
对于即时数据包,用户应用仅向 DMA 发送 CMPT 包,而不会发送数据包。
以下是即时完成包的设置。没有对应的数据包。
在某些应用中,即时完成包无需等待任何数据包。但在某些应用中,它可能仍需要等待数据有效载荷包。如果完成类型为 NO_PLD_NO_WAIT
,则无需等待任何数据包即可传出完成包。如果完成类型为 NO_PLD_BUT_WAIT
,则完成包必须指定需要等待的数据包 ID。
-
s_axis_c2h_cmpt_user_cmpt_type
=NO_PLD_NO_WAIT
或NO_PLD_BUT_WAIT
。 -
s_axis_c2h_cmpt_ctrl_wait_pld_pkt_id
= 不会递增包计数。
标记包
QDMA 的 C2H 串流引擎为用户应用提供了一种将标记与 C2H 包一起插入 QDMA 的方法。然后,此标记通过 C2H 引擎流水线传播,并在队列状态端口接口上输出。通过在 C2H 串流包中对标记位进行置位,即可插入标记。通过在队列状态端口上对 qsts_out_op[7:0] = 0x0
(CMPT 标记响应)位进行置位,QDMA 即可向用户应用指示标记响应。对于标记包,QDMA 不会传出有效载荷包,但仍会写入完成环。由于存在对应的标记请求,因此并不会生成所有标记响应。QDMA 有时会在遇到异常事件时生成标记响应。有关 QDMA 何时在内部生成标记响应的详细信息,请参阅以下部分。
允许用户应用将标记传入 QDMA,主要目的是为了确定将标记之前的所有流量全部清空的时机。在用户应用的关闭序列中,可使用此操作。尽管并非强制要求,但在将标记传入 QDMA 时,用户应用可以使用已置位的 user_trig
位来发送标记。这样,QDMA 就能够生成中断,真正确保将标记之前的所有流量全部清空。QDMA 完成引擎在收到来自用户应用的标记时会执行以下操作:
DMA 还可以选择在标记包期间不向完成环发送完成信息。在标记包期间可设置端口 s_axis_c2h_cmpt_ctrl_no_wrb_marker
。此选项将在生成该标记包时禁用针对完成环的任何写操作。如果针对标记包将此信号置位,则 DMA 不会进行数据传输或完成传输,但会使用 qsts_out_op[7:0]
上的标记响应进行响应。
- 将伴随标记的完成数据发送到 C2H 串流完成环。
- 将完成数据的低 24 位发送到队列状态数据端口
qsts_out_data[26:3]
。 - 如果已启用状态描述符,则生成状态描述符(如果在插入标记时
user_trig
已置位)。 - 如果已启用中断但尚未完成,则生成中断。
- 发送标记响应。如果由于正在启用中断,但尚未完成而未发送中断,则标记响应中的
retry marker_req
位将置位,以通知用户无法为该标记请求发送中断。如需了解有关这些字段的详细信息,请参阅队列状态端口接口描述。
标记包既包含数据包又包含 CMPT 包。这两种包一对一匹配。
以下是具有标记的数据包的设置:
- 1 拍数据
-
s_axis_c2h_ctrl_marker
=1'b1
-
s_axis_c2h_ctrl_len
= 数据宽度(例如,如果数据宽度是 512 位,那么该值为 64) -
s_axis_c2h_mty
= 0 -
s_axis_c2h_ctrl_has_cmpt
=1'b1
- 1 拍 CMPT 包
-
s_axis_c2h_cmpt_ctrl_marker
=1'b1
-
s_axis_c2h_cmpt_ctrl_cmpt_type
=HAS_PLD
-
s_axis_c2h_cmpt_ctrl_wait_pld_pkt_id
= 此完成包必须等到发送具有此 ID 的数据有效载荷包后,才会发送 CMPT 包。 -
s_axis_c2h_cmpt_ctrl_no_wrb_marker
=1'b0
。如果将其设置为1'b1
,那么就没有 CMPT 包。
即时数据包和标记包不耗用描述符;它们将写入 C2H 完成环。软件需要调整 C2H 完成环设置的大小,使其足以容纳未完成的即时包和标记包。
当 DMA 接收到标记请求而完成环已满时,将传出标记响应。但是,由于完成环已满,完成条目将被丢弃,队列将失效。
零长度包
数据包的长度可以为零。在输入时,用户需要发送 1 拍数据。零长度包会耗用描述符。QDMA 将传出 1DW 有效载荷数据。
以下是零长度包的设置:
- 1 拍数据
-
s_axis_c2h_ctrl_len
= 0 -
s_axis_c2h_mty
= 0
禁用完成包
用户应用可禁用特定包的完成。QDMA 可提供对有效载荷的直接存储器访问 (DMA),但不会写入 C2H 完成环。用户应用只向 DMA 发送数据包,而不会发送 CMPT 包。
以下是禁用完成包的设置:
-
s_axis_c2h_ctrl_has_cmpt
=1'b0