接口综合参考(Interface Synthesis Reference)

目录

    • 1 块级I/O协议
        • ap_ctrl_none
        • ap_ctrl_hs
        • ap_ctrl_chain
    • 2 端口级I/O协议
        • ap_none
        • ap_stable
        • ap_hs (ap_ack, ap_vld, and ap_ovld)
        • ap_ack
        • ap_vld
        • ap_ovld
        • ap_memory, bram
        • ap_fifo
        • ap_bus
        • axis
        • s_axilite
        • m_axi

本博客解释了每种Vivado HLS接口协议模式。

1 块级I/O协议

Vivado HLS使用接口类型ap_ctrl_none,ap_ctrl_hs和ap_ctrl_chain来指定是否使用块级握手信号实现RTL。块级握手信号指定以下内容:

  • 当设计的模块开始执行操作时
  • 当操作完成时
  • 当设计的模块空且准备好接受新的输入时

您可以给函数或者函数的返回值指定这些块级I/O协议。如果C代码不返回一个值,您同样可以给函数的返回指定一个块级I/O协议。如果C代码使用了一个函数返回,Vivado HLS会为返回值创建一个 ap_return 输出端口。

ap_ctrl_hs 块级I/O协议是默认使用的协议,下图展示了Vivado HLS在函数上实现ap_ctrl_hs时产生的RTL端口和行为。在这个例子中,函数利用return语法返回一个值,因而Vivado HLS在RTL设计创建了一个ap_return输出端口。如果C代码中不包含函数的return语法,这一个端口就不会生成。

接口综合参考(Interface Synthesis Reference)_第1张图片

ap_ctrl_chain 接口模式类似于ap_ctrl_hs,但是提供了附加的输入信号 ap_continue 来施加反压。Xilinx建议将Vivado HLS块链接在一起时使用ap_ctrl_chain块级I / O协议。

ap_ctrl_none

如果您指定使用 ap_ctrl_none 块级I/O协议,那么上图中的握手信号端口(ap_start,ap_idle,ap_ready 和 ap_done)就不会被创建。如果您没有在设计中指定块级I/O协议,那么您在使用C / RTL协同仿真来验证RTL设计时,必须遵守 接口综合要求 中所述的条件。

ap_ctrl_hs

下图展示了由ap_ctrl_hs I/O协议为非流水线设计而创建的块级握手(handshake)信号的行为。

接口综合参考(Interface Synthesis Reference)_第2张图片

复位完成后,将发生以下事件:

① 所设计的块等待 ap_start 置高电平以开始它的操作

② 输出 ap_idle 立刻置低电平以指示此时所设计的块不再空闲

ap_start 信号必须保持高电平直到 ap_ready 置高,一旦 ap_ready 置高:

  • 如果 ap_start 保持高电平,设计的块将会开始下一次事务
  • 如果 ap_start 置位低电平,设计将完成当前事务并暂停操作

④ 数据可以被输入端口读取(注意:输入端口可以使用独立于此块级I / O协议的端口级I / O协议)

⑤ 数据可以被写到输出端口(注意:输出端口可以使用独立于此块级I / O协议的端口级I / O协议)

⑥ 当设计的块完成操作时,输出 ap_done 置高(注意:如果有ap_return端口,则当ap_done为“高”时,此端口上的数据有效。 因此,ap_done信号还指示输出ap_return上的数据何时有效)

⑦ 当设计准备好接受新输入时,ap_ready 信号变为高电平。 以下是有关ap_ready信号的其他信息:

  • 在设计开始运行之前,ap_ready信号无效
  • 在非流水线设计中,ap_ready信号与ap_done同时声明
  • 在流水线设计中,在ap_start被采样为高电平之后,ap_ready信号可能在任何周期变为高电平,这取决于设计的流水线方式
  • 如果当ap_ready为高电平时ap_start信号为低电平,则设计将执行ap_done为高电平,然后停止操作
  • 如果当ap_ready为高电平时ap_start信号为高电平,则下一个事务处理子立即启动,并且设计继续运行

ap_idle 信号指示设计何时处于空闲状态且未运行。 以下是有关ap_idle信号的其他信息:

  • 如果当ap_ready为高电平时ap_start信号为低电平,则设计停止操作,并且在ap_done之后一个周期ap_idle信号变为高电平
  • 如果当ap_ready为高电平时ap_start信号为高电平,则设计继续运行,并且ap_idle信号保持低电平

ap_ctrl_chain

ap_ctrl_chain 块级I/O协议类似于 ap_ctrl_hs 协议,但提供了一个名为 ap_continue 的附加输入端口。高电平有效的ap_continue信号指示消耗输出数据的下游块已准备好进行新的数据输入。如果下游块无法使用新的数据输入,则ap_continue信号为低电平,这将阻止上游块生成附加数据。

下游块的 ap_ready 端口可以直接驱动 ap_continue 端口。 以下是有关ap_continue端口的其他信息:

  • 如果当ap_done为高电平时ap_continue信号为高电平,则设计继续运行。其他块级I/O信号的行为与ap_ctrl_hs块级I/O协议中描述的行为相同
  • 如果当ap_done为高电平时ap_continue信号为低电平,则设计停止操作,ap_done信号保持高电平,并且如果存在ap_return端口,则数据在ap_return端口上保持有效。

在下面的图中,因为当ap_done为高时,ap_continue为高,所以第一个事务完成,并且第二个事务立即启动。 但是,设计将在第二个事务结束时停止,直到将ap_continue声明为高为止。

接口综合参考(Interface Synthesis Reference)_第3张图片

2 端口级I/O协议

ap_none

ap_none端口级I/O协议是最简单的接口类型,并且没有其他信号与其关联。输入数据信号和输出数据信号都没有关联的用于指示何时读取或写入数据的控制端口。 RTL设计中唯一的端口是源代码中指定的端口。

ap_none接口不需要其他硬件开销,尽管如此,ap_none接口需要满足以下条件:

  • 生产者块执行以下两个操作之一
    • 在正确的时间向输入端口提供数据
    • 保留事务期间的数据,直到设计的块的操作完成
  • 使用者块在正确的时间读取输出端口

注意:ap_none接口不能与数组参数一起使用。

ap_stable

与ap_none一样,ap_stable端口级I/O协议不会在设计中添加任何接口控制端口。 ap_stable类型通常用于可更改但在正常操作期间保持稳定的数据,例如提供配置数据的端口。 ap_stable类型将以下内容通知给Vivado HLS:

  • 应用于端口的数据在正常操作期间保持稳定,但不是可以优化的恒定值
  • 此端口的扇出不需要注册

注意:ap_stable类型只能应用于输入端口。 当应用于inout端口时,仅端口的输入被认为是稳定的。

ap_hs (ap_ack, ap_vld, and ap_ovld)

ap_hs端口级I/O协议在开发过程中提供了最大的灵活性,允许自下而上和自上而下的设计流程。 双向握手可以安全地执行所有块内通信,且可以正确操作不需要手动干预或假设。 ap_hs端口级I/O协议提供以下信号:

  • 数据端口
  • 指示何时消耗数据的确知信号
  • 指示何时读取数据的有效信号

下面的图显示了ap_hs接口在输入和输出端口上的行为,在此示例中,输入端口命名为 in,输出端口命名为 out。

注意:控制信号的名称是基于原始端口名称确定的。 例如,用于输入数据的有效端口名为in_vld。
接口综合参考(Interface Synthesis Reference)_第4张图片
对于输入,发生以下事件:

  • 开始信号ap_start置高后,块开始正常操作
  • 如果设计已准备好输入数据,但输入有效信号in_valid为低,则设计将暂停并等待输入有效信号in_vld置高以指示存在新的输入值(注意:上图显示了此行为。 在此示例中,在第4个时钟周期设计已准备好读取输入的数据,并在读取数据之前停顿等待输入有效)
  • 当输入有效信号in_vld置位高电平时,确知信号in_ack就置位高电平,表明已读取数据

对于输出,发生以下事件:

  • 开始信号ap_start置高后,块开始正常操作
  • 写入输出端口时,将同时声明其关联的输出有效信号,以指示端口上存在有效数据
  • 如果相关的输入确知信号in_ack为低电平,则设计将停顿并等待输入确知信号in_ack置高
  • 输入确知信号in_ack置高后,将在下一个时钟沿输出有效out_vld将置为无效

ap_ack

ap_ack端口级I/O协议是ap_hs接口类型的子集,它提供以下信号:

  • 数据端口
  • 确知信号指示何时消耗数据
    • 对于输入的参数,设计将生成一个输出确知端口,该确知信号将在输入被读取的周期中为高电平有效
    • 对于输出的参数,Vivado HLS会实现为一个输入确知端口,以确认输出被读取

注意:在执行写操作后,设计将暂停并等待直到输入确认为高电平为止,这表明输出已由使用者块读取。 但是,没有关联的输出端口指示何时可以使用数据。不能使用C / RTL协同仿真来验证在输出端口上使用ap_ack的设计!

ap_vld

ap_vld是ap_hs接口类型的子集。 ap_vld端口级I/O协议提供以下信号:

  • 数据端口
  • 指示何时读取数据的有效信号
    • 对于输入参数,设计将在valid信号有效后立即读取数据端口。 即使设计尚未准备好读取新数据,设计也会对数据端口进行采样并在内部保留所需的数据
    • 对于输出参数,Vivado HLS实现为一个输出有效端口,以指示输出端口上的数据何时有效。

ap_ovld

ap_ovld是ap_hs接口类型的子集。 ap_ovld端口级I/O协议提供以下信号:

  • 数据端口
  • 指示何时读取数据的有效信号
    • 对于输入参数和inout参数的输入,设计默认为ap_none
    • 对于输出参数和inout参数的输出,设计实现类型为ap_vld

ap_memory, bram

ap_memory和bram接口端口级I/O协议用于实现数组参数。 当需要随机访问内存地址位置时,这种类型的端口级I/O协议可以与存储元件(例如RAM和ROM)通信。

注意:如果只需要对存储元素的顺序访问,请改用ap_fifo接口。 ap_fifo接口可减少硬件开销,因为不执行地址生成。

ap_memory和bram接口端口级别的I/O协议是相同的。 唯一的不同是Vivado IP集成器显示块的方式:

  • ap_memory接口显示为离散端口
  • bram接口显示为单个分组端口,在IP集成器中,可以使用单个连接来创建到所有端口的连接

使用ap_memory接口时,请使用RESOURCE指令指定数组目标。 如果没有为阵列指定目标,则Vivado HLS会自动决定是使用单端口还是双端口RAM接口。(TIP提示:在运行综合之前,请确保使用RESOURCE指令将数组参数定位到正确的内存类型。 使用更正后的内存进行重新合成可能会导致时间表和RTL不同)

下图显示了一个名为d的数组,该数组指定为单端口Block RAM, 端口名称基于C函数中的参数名称。 例如,如果C参数名为d,则片使能命名为d_ce;基于BRAM的output / q端口,输入数据会命名为d_q0。

接口综合参考(Interface Synthesis Reference)_第5张图片
复位完成后,将发生以下事件:

  • 开始信号ap_start置高后,块开始正常操作
  • 在置位输出信号d_ce的同时,通过在输出地址端口上给地址来执行读取(注意:对于默认的Block RAM,设计期望输入数据d_q0在下一个时钟周期可用。 您可以使用RESOURCE指令来指示RAM具有更长的读取延迟)
  • 写操作通过置位输出端口信号d_ce和d_we来执行,同时给出地址和输出数据d_d0

ap_fifo

若一个输出端口被写入,当设计需要访问存储元件并且访问总是以顺序的方式进行时,即不需要随机访问时,与其相关联的输出有效信号接口是最节省硬件的方法。 ap_fifo端口级I/O协议支持以下内容:

  • 允许端口连接到FIFO
  • 实现完整的双向空满通讯
  • 适用于数组,指针和按引用传递参数类型

注意:可以使用ap_fifo接口的函数通常使用指针,并且可以多次访问相同的变量。 若要了解使用这种编码样式时volatile限定符的重要性,请参考:《Mult-Access Pointer Interfaces: Streaming Data》。

在下面的示例中,in1是一个指针,该指针访问当前地址,然后访问当前地址的上两个地址,最后访问下一个地址。

void foo(int* in1, ...) {
	int data1, data2, data3;
	...
	data1= *in1;
	data2= *(in1+2);
	data3= *(in1-1);
	...
}

如果将in1指定为ap_fifo接口,则Vivado HLS会检查访问的方式,确定访问不是按顺序进行的,然后发出错误信息并暂停。 要从 非顺序地址位置 读取数据,需要使用 ap_memorybram 接口。

您不能在读写(既要读又要写)的参数上指定ap_fifo接口。 您只能在输入或输出参数上指定ap_fifo接口。输入参数为in且输出参数为out且都指定为ap_fifo的设计的行为如下图所示。

接口综合参考(Interface Synthesis Reference)_第6张图片

对于输入,发生以下事件:

  • 开始信号ap_start置高后,块开始正常操作
  • 如果输入端口已准备好读取但FIFO空,即输入端口in_empty_n置位低电平,则设计将停顿并等待数据可用
  • 当FIFO包含输入端口in_empty_n高指示的数据时,输出确知信号in_read会被置为高,以指示在此周期中已读取数据

对于输出,发生以下事件:

  • 开始信号ap_start置高后,块开始正常操作
  • 如果输出端口已准备好写入,但FIFO已满,即out_full_n置位低电平,则将数据放置在输出端口上,但设计将停顿并等待FIFO中的空间可用
  • 当FIFO中有可用空间时,即out_full_n置位高电平,输出确知信号out_write会被置位以指示输出数据有效
  • 如果使用 -rewind 选项对顶层函数或顶层循环进行了流水线处理,则Vivado HLS将创建带有后缀 _lwr 的附加输出端口。 当最后一次写入FIFO接口完成时,_lwr 端口变为高电平有效。

ap_bus

ap_bus 接口可以与总线桥进行通信。 由于ap_bus接口未遵循特定的总线标准,因此可以将此接口和与系统总线进行通信的总线桥一起使用,其中总线桥必须能够缓存所有突发写入。

注意:可以使用ap_bus接口的函数使用指针,并且可能多次访问同一变量。 若要了解使用这种编码样式时volatile限定符的重要性,请参考:《Mult-Access Pointer Interfaces: Streaming Data》。

您可以通过以下方式使用ap_bus接口:

  • 标准模式:此模式执行单独的读取和写入操作,并指定每个操作的地址
  • 突发模式:如果在C源代码中使用了C函数 memcpy ,则此模式将执行数据传输。 在突发模式下,该接口指示基址和传输大小, 然后以连续的周期传输数据样本

注意:通过memcpy函数访问的数组不能划分为寄存器。

以下示例显示了将 ap_bus 接口应用于参数 d 时标准模式下的读写操作的行为。

void foo (int *d) {
	static int acc = 0;
	int i;
	for (i=0;i<4;i++) {
		acc += d[i+1];
		d[i] = acc;
	}
}

以下示例显示了使用C函数memcpy和突发模式时的行为。

void bus (int *d) {
	int buf1[4], buf2[4];
	int i;
	memcpy(buf1,d,4*sizeof(int));
	for (i=0;i<4;i++) {
		buf2[i] = buf1[3-i];
	}
	memcpy(d,buf2,4*sizeof(int));
}

① 标准模式下的ap_bus读取操作行为如下图所示。
接口综合参考(Interface Synthesis Reference)_第7张图片

复位完成后,将发生以下事件:

  • 开始信号ap_start置高后,块开始正常操作
  • 如果必须执行读取但总线桥FIFO中没有数据(即d_rsp_empty_n为低电平),则会发生以下情况:
    • 输出端口d_req_write被置高电平,输入端口d_req_din保持低电平,以指示要进行一个读取操作
    • 输出地址d_address
    • 设计停顿并等待数据可用
  • 当数据变得可用于读取输出信号时,d_rsp_read立刻置位并在下一个时钟沿读取数据
  • 如果必须执行读取并且总线桥FIFO中有可用数据(由d_rsp_empty_n高指示),则会发生以下情况:
    • 输出端口d_req_write被置为有效,而端口d_req_din被置为无效以指示读取操作
    • 输出地址
    • 输出信号d_rsp_read在下一个时钟周期有效,然后设计的块在下一个时钟沿读取数据

② 标准模式下的ap_bus写数据操作行为如下图所示。

接口综合参考(Interface Synthesis Reference)_第8张图片
复位完成后,将发生以下事件:

  • 开始信号ap_start置高后,块开始正常操作
  • 如果必须执行写操作,但总线桥FIFO中没有空间(即d_req_full_n为低电平),则会发生以下情况:
    • 输出地址和数据
    • 设计停顿并等待空间可用
  • 当空间变得可用于写入时,将发生以下情况:
    • 输出端口d_req_write和d_req_din被置位以指示写操作
    • 输出信号d_req_din立刻被置位以指示该数据在下一个时钟沿有效
  • 如果必须执行写操作并且总线桥FIFO中有可用空间(即d_req_full_n为高电平),则会发生以下情况:
    • 输出端口d_req_write和d_req_din被置位以指示写操作
    • 输出地址和数据
    • 输出信号d_req_din被置位以指示数据在下一个时钟沿有效

③ 突发模式下的ap_bus读取数据操作行为如下图所示。

接口综合参考(Interface Synthesis Reference)_第9张图片
复位完成后,将发生以下事件:

  • 开始信号ap_start置高后,块开始正常操作
  • 如果必须执行读取但总线桥FIFO中没有数据(d_rsp_empty_n为低电平),则会发生以下情况:
    • 输出端口d_req_write被置高电平,输入端口d_req_din保持低电平,以指示要进行一个读取操作
    • 输出传输基地址和传输大小
    • 设计停顿并等待数据可用
  • 当数据可用于读取时,输出信号d_rsp_read立刻置位并在接下来的N个时钟沿读取数据,其中N是关于传输大小的输出端口的值
  • 如果总线桥FIFO的值空了,数据传输将立即停止并等待直到数据可用为止

④ 突发模式下的ap_bus写入数据操作行为如下图所示。

接口综合参考(Interface Synthesis Reference)_第10张图片
复位完成后,将发生以下事件:

  • 开始信号ap_start置高后,块开始正常操作
  • 如果必须执行写操作,但总线桥FIFO中没有空间(即d_req_full_n为低电平),则会发生以下情况:
    • 输出基地址、传输大小和数据
    • 设计停顿并等待空间可用
  • 当空间变得可用于写入时,将发生以下情况:
    • 输出端口d_req_write和d_req_din被置位以指示写操作
    • 输出信号d_req_din立刻被置位以指示该数据在下一个时钟沿有效
    • 如果FIFO已满,则输出信号d_req_din立即置为无效,并在有可用空间时将其置为有效
    • 传输完N个数据值后,传输停止,其中N是关于传输大小的输出端口的值
  • 如果必须执行写操作并且总线桥FIFO中有可用空间(即d_rsp_full_n为高电平),则传输开始,直到FIFO已满时设计才停止操作

axis

axis模式指定了AXI4-Stream I/O协议。 有关AXI4-Stream接口的完整描述,包括时序和端口,请参见《 Vivado Design Suite: AXI Reference Guide》(UG1037)。 有关使用此I/O协议的完整功能的信息,请参考《Using AXI4 Interfaces》。

s_axilite

s_axilite模式指定AXI4-Lite slave I/O协议。有关AXI4-Lite slave接口的完整描述,包括时序和端口,请参见《 Vivado Design Suite: AXI Reference Guide》(UG1037)。有关使用此I/O协议的完整功能的信息,请参考《Using AXI4 Interfaces》。

m_axi

m_axi模式指定AXI4 master I/O协议。有关AXI4 master接口的完整描述,包括时序和端口,请参见《 Vivado Design Suite: AXI Reference Guide》(UG1037)。有关使用此I/O协议的完整功能的信息,请参考《Using AXI4 Interfaces》。

你可能感兴趣的:(ZYNQ-FPGA)