fpga系列 HDL:XILINX Vivado Vitis HLS 笔记 函数接口综合 ap_ctrl_none,ap_ctrl_hs,ap_ctrl_chain 和s_axilite

块级接口综合类型

  • Vitis HLS(High-Level Synthesis)中,块级接口类型用于指定模块的控制信号和通信方式,从而影响硬件实现时的控制逻辑、时序以及数据传输方式。Vitis HLS 使用以下接口类型 ap_ctrl_none,ap_ctrl_hs,ap_ctrl_chain 和s_axilite来指定 RTL IP 是否使用模块级握手信号实现。

在这里插入图片描述

  • 注:默认情况下,block-level interface protocol 被添加到 design中。且块级接口的端口格式为ap_ctrl_hs

在这里插入图片描述

块级:可以在函数或函数返回上指定块级 I/O 协议

  • 如果 C/C++ 代码未返回值,您仍然可以在函数返回时指定块级 I/O 协议。如果 C/C++ 代码使用函数返回,则 Vitis HLS 会为返回值创建一个输出端口 ap_return。
    在这里插入图片描述

ap_ctrl_none(No Control)

  • ap_ctrl_none 是一种不带握手信号的控制方式,通常用于不需要显式同步控制信号的设计场景。模块之间的数据流通常是基于时序控制的,在这种模式下,控制信号的依赖关系相对较少或不存在。

  • 适用场景:无需复杂控制信号,设计中可能只是简单的模块调用。

  • 工作原理:不涉及复杂的握手或数据同步信号,控制信号可能是基于时钟的触发,或者是一次性数据传输。

代码效果

// LED控制函数
void hlsv1(ap_uint<1> &led) {
#pragma HLS INTERFACE ap_ctrl_none port=return

}

⇓ \Downarrow

`timescale 1 ns / 1 ps 

(* CORE_GENERATION_INFO="hlsv1_hlsv1,hls_ip_2020_2,{HLS_INPUT_TYPE=cxx,HLS_INPUT_FLOAT=0,HLS_INPUT_FIXED=0,HLS_INPUT_PART=xc7z010-clg400-1,HLS_INPUT_CLOCK=10.000000,HLS_INPUT_ARCH=others,HLS_SYN_CLOCK=0.000000,HLS_SYN_LAT=0,HLS_SYN_TPT=none,HLS_SYN_MEM=0,HLS_SYN_DSP=0,HLS_SYN_FF=0,HLS_SYN_LUT=0,HLS_VERSION=2020_2}" *)

module hlsv1 (
        led
);


input  [511:0] led;

endmodule //hlsv1

ap_ctrl_hs (Handshaking Control)

  • ap_ctrl_hs 模式是基于握手信号的控制方式,通常用于数据流的处理。在这种模式下,模块会通过握手信号来实现数据的同步传输。它是最常见的流式数据处理方式,特别适用于流水线设计和数据流控制。

  • 握手信号

    • 控制块何时可以开始处理数据 (ap_start)
    • 指示模块是空闲,非处理数据阶段 (ap_idle)
    • 指示准备好接受新输入 (ap_ready)
    • 模块已完成操作 (ap_done)在这里插入图片描述
  • 使用场景:适用于需要数据同步或流水线控制的设计。图像处理、音频信号处理等流式数据处理任务。例如,一个模块的输出端如果准备好给下游模块传输数据时,它会通过 valid 信号通知下游模块;下游模块通过 ready 信号确认可以接受数据。

代码效果

// LED控制函数
void hlsv1(ap_uint<1> &led) {
#pragma HLS INTERFACE ap_ctrl_hs port=return

}

⇓ \Downarrow

`timescale 1 ns / 1 ps 

(* CORE_GENERATION_INFO="hlsv1_hlsv1,hls_ip_2020_2,{HLS_INPUT_TYPE=cxx,HLS_INPUT_FLOAT=0,HLS_INPUT_FIXED=0,HLS_INPUT_PART=xc7z010-clg400-1,HLS_INPUT_CLOCK=10.000000,HLS_INPUT_ARCH=others,HLS_SYN_CLOCK=0.000000,HLS_SYN_LAT=0,HLS_SYN_TPT=none,HLS_SYN_MEM=0,HLS_SYN_DSP=0,HLS_SYN_FF=0,HLS_SYN_LUT=0,HLS_VERSION=2020_2}" *)

module hlsv1 (
        ap_start,
        ap_done,
        ap_idle,
        ap_ready,
        led
);


input   ap_start;
output   ap_done;
output   ap_idle;
output   ap_ready;
input  [511:0] led;

assign ap_done = ap_start;

assign ap_idle = 1'b1;

assign ap_ready = ap_start;

endmodule //hlsv1

ap_ctrl_chain

  • ap_ctrl_chain 模式(流水线内核)允许多个模块形成一个链式结构,每个模块的控制信号通过链式传递。这意味着每个模块的执行控制由前一个模块的信号控制,模块间的同步是通过级联握手实现的。

  • 使用场景:适用于多个模块按顺序依次执行,且每个模块的执行依赖于前一个模块的状态。这种模式通常用于复杂的流水线设计中,各模块的数据依赖性较强时使用。

代码效果

// LED控制函数
void hlsv1(ap_uint<1> &led) {
#pragma HLS INTERFACE ap_ctrl_chain port=return


}

⇓ \Downarrow

`timescale 1 ns / 1 ps 

(* CORE_GENERATION_INFO="hlsv1_hlsv1,hls_ip_2020_2,{HLS_INPUT_TYPE=cxx,HLS_INPUT_FLOAT=0,HLS_INPUT_FIXED=0,HLS_INPUT_PART=xc7z010-clg400-1,HLS_INPUT_CLOCK=10.000000,HLS_INPUT_ARCH=others,HLS_SYN_CLOCK=0.000000,HLS_SYN_LAT=0,HLS_SYN_TPT=none,HLS_SYN_MEM=0,HLS_SYN_DSP=0,HLS_SYN_FF=2,HLS_SYN_LUT=11,HLS_VERSION=2020_2}" *)

module hlsv1 (
        ap_clk,
        ap_rst,
        ap_start,
        ap_done,
        ap_continue,
        ap_idle,
        ap_ready,
        led
);

parameter    ap_ST_fsm_state1 = 1'd1;

input   ap_clk;
input   ap_rst;
input   ap_start;
output   ap_done;
input   ap_continue;
output   ap_idle;
output   ap_ready;
input  [511:0] led;

reg ap_done;
reg ap_idle;
reg ap_ready;

reg    ap_done_reg;
(* fsm_encoding = "none" *) reg   [0:0] ap_CS_fsm;
wire    ap_CS_fsm_state1;
reg    ap_block_state1;
reg   [0:0] ap_NS_fsm;
wire    ap_ce_reg;

// power-on initialization
initial begin
#0 ap_done_reg = 1'b0;
#0 ap_CS_fsm = 1'd1;
end

always @ (posedge ap_clk) begin
    if (ap_rst == 1'b1) begin
        ap_CS_fsm <= ap_ST_fsm_state1;
    end else begin
        ap_CS_fsm <= ap_NS_fsm;
    end
end

always @ (posedge ap_clk) begin
    if (ap_rst == 1'b1) begin
        ap_done_reg <= 1'b0;
    end else begin
        if ((ap_continue == 1'b1)) begin
            ap_done_reg <= 1'b0;
        end else if ((~((ap_start == 1'b0) | (ap_done_reg == 1'b1)) & (1'b1 == ap_CS_fsm_state1))) begin
            ap_done_reg <= 1'b1;
        end
    end
end

always @ (*) begin
    if ((~((ap_start == 1'b0) | (ap_done_reg == 1'b1)) & (1'b1 == ap_CS_fsm_state1))) begin
        ap_done = 1'b1;
    end else begin
        ap_done = ap_done_reg;
    end
end

always @ (*) begin
    if (((ap_start == 1'b0) & (1'b1 == ap_CS_fsm_state1))) begin
        ap_idle = 1'b1;
    end else begin
        ap_idle = 1'b0;
    end
end

always @ (*) begin
    if ((~((ap_start == 1'b0) | (ap_done_reg == 1'b1)) & (1'b1 == ap_CS_fsm_state1))) begin
        ap_ready = 1'b1;
    end else begin
        ap_ready = 1'b0;
    end
end

always @ (*) begin
    case (ap_CS_fsm)
        ap_ST_fsm_state1 : begin
            ap_NS_fsm = ap_ST_fsm_state1;
        end
        default : begin
            ap_NS_fsm = 'bx;
        end
    endcase
end

assign ap_CS_fsm_state1 = ap_CS_fsm[32'd0];

always @ (*) begin
    ap_block_state1 = ((ap_start == 1'b0) | (ap_done_reg == 1'b1));
end

endmodule //hlsv1

s_axilite

  • s_axilite 是一种专门用于与 AXI Lite 接口交互的控制信号模式。AXI Lite 是一种较为简单的通信协议,常用于低带宽、高效的控制与状态寄存器读写。

  • 使用场景s_axilite 表示该函数/模块将通过 AXI Lite 总线进行通信,适用于与控制寄存器交互的设计,例如读取和写入配置寄存器、状态寄存器等。通常用于系统的控制接口,与外部处理器或主控系统通信。

典型用法:

#pragma HLS INTERFACE s_axilite port=control

这条指令将模块的 control 端口映射为 AXI Lite 接口,通常用于控制寄存器或简单的指令交互。

例子:

void example_function(int *control) {
    // 这个函数的控制信号将通过 AXI Lite 接口传输
    *control = 10;
}

代码效果

void hlsv1(ap_uint<1> &led) {
#pragma HLS INTERFACE s_axilite port=return


}

⇓ \Downarrow

`timescale 1 ns / 1 ps 

(* CORE_GENERATION_INFO="hlsv1_hlsv1,hls_ip_2020_2,{HLS_INPUT_TYPE=cxx,HLS_INPUT_FLOAT=0,HLS_INPUT_FIXED=0,HLS_INPUT_PART=xc7z010-clg400-1,HLS_INPUT_CLOCK=10.000000,HLS_INPUT_ARCH=others,HLS_SYN_CLOCK=0.000000,HLS_SYN_LAT=0,HLS_SYN_TPT=none,HLS_SYN_MEM=0,HLS_SYN_DSP=0,HLS_SYN_FF=36,HLS_SYN_LUT=40,HLS_VERSION=2020_2}" *)

module hlsv1 (
        led,
        s_axi_control_AWVALID,
        s_axi_control_AWREADY,
        s_axi_control_AWADDR,
        s_axi_control_WVALID,
        s_axi_control_WREADY,
        s_axi_control_WDATA,
        s_axi_control_WSTRB,
        s_axi_control_ARVALID,
        s_axi_control_ARREADY,
        s_axi_control_ARADDR,
        s_axi_control_RVALID,
        s_axi_control_RREADY,
        s_axi_control_RDATA,
        s_axi_control_RRESP,
        s_axi_control_BVALID,
        s_axi_control_BREADY,
        s_axi_control_BRESP,
        ap_clk,
        ap_rst_n,
        interrupt
);

parameter    C_S_AXI_CONTROL_DATA_WIDTH = 32;
parameter    C_S_AXI_CONTROL_ADDR_WIDTH = 4;
parameter    C_S_AXI_DATA_WIDTH = 32;

parameter C_S_AXI_CONTROL_WSTRB_WIDTH = (32 / 8);
parameter C_S_AXI_WSTRB_WIDTH = (32 / 8);

input  [511:0] led;
input   s_axi_control_AWVALID;
output   s_axi_control_AWREADY;
input  [C_S_AXI_CONTROL_ADDR_WIDTH - 1:0] s_axi_control_AWADDR;
input   s_axi_control_WVALID;
output   s_axi_control_WREADY;
input  [C_S_AXI_CONTROL_DATA_WIDTH - 1:0] s_axi_control_WDATA;
input  [C_S_AXI_CONTROL_WSTRB_WIDTH - 1:0] s_axi_control_WSTRB;
input   s_axi_control_ARVALID;
output   s_axi_control_ARREADY;
input  [C_S_AXI_CONTROL_ADDR_WIDTH - 1:0] s_axi_control_ARADDR;
output   s_axi_control_RVALID;
input   s_axi_control_RREADY;
output  [C_S_AXI_CONTROL_DATA_WIDTH - 1:0] s_axi_control_RDATA;
output  [1:0] s_axi_control_RRESP;
output   s_axi_control_BVALID;
input   s_axi_control_BREADY;
output  [1:0] s_axi_control_BRESP;
input   ap_clk;
input   ap_rst_n;
output   interrupt;

wire    ap_start;
wire    ap_done;
wire    ap_idle;
wire    ap_ready;
 reg    ap_rst_n_inv;

hlsv1_control_s_axi #(
    .C_S_AXI_ADDR_WIDTH( C_S_AXI_CONTROL_ADDR_WIDTH ),
    .C_S_AXI_DATA_WIDTH( C_S_AXI_CONTROL_DATA_WIDTH ))
control_s_axi_U(
    .AWVALID(s_axi_control_AWVALID),
    .AWREADY(s_axi_control_AWREADY),
    .AWADDR(s_axi_control_AWADDR),
    .WVALID(s_axi_control_WVALID),
    .WREADY(s_axi_control_WREADY),
    .WDATA(s_axi_control_WDATA),
    .WSTRB(s_axi_control_WSTRB),
    .ARVALID(s_axi_control_ARVALID),
    .ARREADY(s_axi_control_ARREADY),
    .ARADDR(s_axi_control_ARADDR),
    .RVALID(s_axi_control_RVALID),
    .RREADY(s_axi_control_RREADY),
    .RDATA(s_axi_control_RDATA),
    .RRESP(s_axi_control_RRESP),
    .BVALID(s_axi_control_BVALID),
    .BREADY(s_axi_control_BREADY),
    .BRESP(s_axi_control_BRESP),
    .ACLK(ap_clk),
    .ARESET(ap_rst_n_inv),
    .ACLK_EN(1'b1),
    .ap_start(ap_start),
    .interrupt(interrupt),
    .ap_ready(ap_ready),
    .ap_done(ap_done),
    .ap_idle(ap_idle)
);

assign ap_done = ap_start;

assign ap_idle = 1'b1;

assign ap_ready = ap_start;

always @ (*) begin
    ap_rst_n_inv = ~ap_rst_n;
end

endmodule //hlsv1
  • 此外还有一个 hlsv1_control_s_axi 模块
    在这里插入图片描述

CG

<think>好的,我现在要解决用户关于HLSap_ctrl_hs的作用及使用方法的问题。首先,我需要回顾一下自己对这个概念的理解,确保准确无误。根据用户提供的引用资料,ap_ctrl_hsVivado HLSVitis HLS中的一种接口协议,用于模块级的控制握手。它包含四个信号:ap_start、ap_ready、ap_idle、ap_done。这些信号的作用是协调模块的开始、准备状态、空闲状态完成状态。 接下来,我需要确认这些信息的正确性。根据引用[2][3],ap_ctrl_hs确实包含这四个信号。引用[4]提到ap_ctrl_chain相比ap_ctrl_hs多了一个ap_continue信号,这说明ap_ctrl_hs是基础的控制协议,而ap_ctrl_chain用于更复杂的控制流程。此外,引用[5]指出ap_ctrl_hs是阻塞IO控制握手协议,这意味着模块可能需要等待这些信号的状态变化才能继续执行。 用户的问题包括功能用法,所以需要分两部分回答。首先解释ap_ctrl_hs的功能,然后说明如何在代码中使用它。根据引用[1],HLS在生成硬件模块时,会提取控制逻辑形成状态机,这些握手信号是状态机的一部分。因此,ap_ctrl_hs的作用是管理模块的执行流程,确保数据控制信号的正确时序。 关于使用方法,引用[2][3]提到在顶层函数中设置接口协议为ap_ctrl_hs,通常通过HLS指令或pragma来实现。例如,在C代码中使用#pragma HLS interface ap_ctrl_hs port=return来指定接口协议。需要确认这个pragma的语法是否正确,可能参考官方文档或用户提供的引用资料中的例子。引用[3]中的代码示例显示在模块定义中使用了ap_ctrl_hs,但具体在C代码中的实现可能需要通过pragma指定。 另外,用户可能想知道如何在实际项目中应用ap_ctrl_hs,比如如何连接这些信号到其他模块或处理器。根据引用[4],ap_ctrl_hs适用于顺序执行流水线执行,但需要下游模块的控制时可能需要ap_ctrl_chain。因此,在教程部分需要说明何时选择ap_ctrl_hs,以及它的典型应用场景,比如与处理器配合使用时,处理器通过驱动ap_start来启动模块,并轮询ap_done来判断完成状态。 可能存在疑问的是,这些信号的具体时序关系是怎样的。例如,ap_ready何时有效,ap_idleap_done的关系如何。根据一般的握手协议,ap_start有效后模块开始运行,ap_idle在模块空闲时有效,ap_done在操作完成时置高。ap_ready可能表示模块可以接受新的启动信号。需要确保这些解释与引用资料一致,避免错误。 最后,用户可能需要示例代码来理解如何在HLS中实现ap_ctrl_hs。根据引用中的Python示例,可能需要提供一个C代码片段,展示如何添加pragma指令,并解释生成的RTL接口信号。同时,需要强调正确连接这些信号在硬件集成中的重要性,避免出现控制逻辑错误。 总结回答结构:先介绍功能,包括四个信号的作用;再说明使用方法,包括代码中的设置集成时的注意事项;最后给出示例代码相关问题。需要确保引用正确的来源,比如引用[2][3]关于信号定义,引用[4]关于与其他协议的区别。</think>### HLSap_ctrl_hs的作用及使用方法 #### 一、ap_ctrl_hs的功能 ap_ctrl_hsVivado/Vitis HLS中用于**模块级控制握手**的接口协议,主要用于协调硬件模块的启动、执行状态完成通知。它包含以下信号[^2][^3][^5]: 1. **ap_start**:输入信号,高电平触发模块开始执行。 2. **ap_ready**:输出信号,高电平表示模块已准备好接受新任务。 3. **ap_idle**:输出信号,高电平表示模块处于空闲状态。 4. **ap_done**:输出信号,高电平表示模块已完成当前任务。 通过这些信号,外部控制器(如CPU或状态机)可以精确控制硬件模块的执行流程,例如: - 通过拉高`ap_start`启动模块; - 通过检测`ap_done`判断任务完成; - 通过`ap_idle``ap_ready`监控模块状态。 #### 二、使用方法 ##### 1. 代码级配置 在HLS C/C++代码中,通过**编译指令(Pragma)**指定接口协议: ```cpp #pragma HLS interface ap_ctrl_hs port=return ``` 此指令需添加到**顶层函数**的参数列表中,表示对函数返回值(通常为模块控制端口)应用`ap_ctrl_hs`协议[^2]。 ##### 2. 硬件集成注意事项 - **信号时序**: - `ap_start`需在`ap_ready=1`时拉高,确保模块已准备好; - `ap_done`拉高后,需外部控制器复位`ap_start`以结束当前周期[^4]。 - **典型应用场景**: - 顺序执行任务(非流水线); - 与处理器通过AXI-Lite总线交互(常见于Zynq SoC)。 ##### 3. 示例代码 ```cpp // 示例:HLS模块的顶层函数配置 void example_module(int *data_in, int *data_out) { #pragma HLS interface ap_ctrl_hs port=return #pragma HLS interface s_axilite port=data_in #pragma HLS interface s_axilite port=data_out // 模块功能逻辑... } ``` #### 三、与其他协议对比 | 协议 | 关键信号 | 适用场景 | |---------------|-----------------------------|------------------------| | ap_ctrl_hs | ap_start, ap_ready, ap_done | 简单顺序执行 | | ap_ctrl_chain | 增加ap_continue | 流水线/多模块协作 | | ap_ctrl_none | 无控制信号 | 纯数据流驱动模块 | #### 四、常见问题 1. **信号未生效**:检查Pragma是否绑定到`port=return`,且未与其他接口协议冲突。 2. **死锁风险**:若未在`ap_done=1`后复位`ap_start`,模块可能无法进入下一周期。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值