zynq板zedboard+vitis设计(三)状态机及中断,PL与PS部分的状态交互

该文介绍了如何在Zynq平台上使用状态机和中断实现PL与PS部分的状态交互。状态机在接收到开始指令后触发PS端中断,PS端执行任务并返回响应后,状态机切换状态,LED灯亮起。当检测到按键按下时,状态机返回初始状态。文章提供了状态机代码、BlockDesign配置和Vitis中断处理程序的实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

本期讲的是一个状态机以及中断相结合的应用,展示的试验功能较为简单,主要是实现PL与PS部分的状态交互。

1.状态机部分

首先是状态机实现的功能。初始处于idle状态(led_idle亮起)收到开始指令(start)后切换到状态a,并向ps端发出一条指令,使ps端产生中断并执行相应命令(这里是输出一句话)。ps端完成任务后,返回一条指令done,状态机收到done指令后切换到状态b,并点亮led灯。保持b状态直到检测到按下按键(key),熄灭led并切回idle状态。

状态机代码

module blog(
input clk,
input rst_n,
input key,
input start,
input done,

output reg print,
output reg led_done,
output reg led_idle
);

parameter idle=0,a=1,b=2;
reg [1:0] state,nstate;

always @(posedge clk or negedge rst_n)begin
    if(!rst_n)
        state<=idle;
    else
        state<=nstate;
end

always @(*)begin
    case(state)
        idle:begin
            if(start)
                nstate=a;
            else
                nstate=state;
        end
        a:begin
            if(done)
                nstate=b;
            else
                nstate=state;
        end
        b:begin
            if(key)
                nstate=idle;
            else
                nstate=state;
        end
        default:;
    endcase
end

always @(posedge clk or negedge rst_n)begin
    if(!rst_n)begin
        print<=1'b0;
        led_done<=1'b0;
        led_idle<=1'b0;
    end
    else if(state==idle)begin
        print<=1'b0;
        led_done<=1'b0;
        led_idle<=1'b1;
    end
    else if(state==a)begin
        print<=1'b1;
        led_done<=1'b0;
        led_idle<=1'b0;
    end
    else if(state==b)begin
        print<=1'b0;
        led_done<=1'b1;
        led_idle<=1'b0;
    end
    else begin
        print<=1'b0;
        led_done<=1'b0;
        led_idle<=1'b0;
    end
end
endmodule

block design设计

 bd内添加zynq后如图添加中断及emio接口

 在bd内右击空白处可以将编写的状态机设计文件作为模块添加进来

如图进行连线

 约束文件

set_property IOSTANDARD LVCMOS33 [get_ports key]
set_property IOSTANDARD LVCMOS33 [get_ports start]
set_property IOSTANDARD LVCMOS33 [get_ports led_done]
set_property IOSTANDARD LVCMOS33 [get_ports led_idle]
set_property PACKAGE_PIN N15 [get_ports key]
set_property PACKAGE_PIN R18 [get_ports start]
set_property PACKAGE_PIN T22 [get_ports led_done]
set_property PACKAGE_PIN T21 [get_ports led_idle]

 2.vitis部分

代码

#include "stdio.h"
#include "xparameters.h"
#include "xgpiops.h"
#include "xscugic.h"
#include "xil_exception.h"
#include "xil_printf.h"

#define GPIOPS_ID XPAR_XGPIOPS_0_DEVICE_ID   //PS端  GPIO器件 ID
#define SCUGIC_ID    XPAR_SCUGIC_0_DEVICE_ID    //中断控制器 ID

#define intr_id 61     //中断号

#define print_done 54  //将print_done信号连接到EMIO0

XGpioPs gpiops_inst;            				 //PS端 GPIO 驱动实例
XGpioPs_Config *gpiops_cfg_ptr; 				 //PS端 GPIO 配置信息
XScuGic          scugic_inst;                    //中断控制器  驱动实例
XScuGic_Config * scugic_cfg_ptr;                 //中断控制器  配置信息


void print_handler(void *CallbackRef);           //中断服务函数

int main()
{
    //根据器件ID查找配置信息
    gpiops_cfg_ptr = XGpioPs_LookupConfig(GPIOPS_ID);
    scugic_cfg_ptr = XScuGic_LookupConfig(SCUGIC_ID);

    //初始化器件驱动
    XGpioPs_CfgInitialize(&gpiops_inst, gpiops_cfg_ptr, gpiops_cfg_ptr->BaseAddr);
    XScuGic_CfgInitialize(&scugic_inst, scugic_cfg_ptr, scugic_cfg_ptr->CpuBaseAddress);

    //设置print_done为输出
    XGpioPs_SetDirectionPin(&gpiops_inst, print_done, 1);
    //使能输出
    XGpioPs_SetOutputEnablePin(&gpiops_inst, print_done, 1);

    //设置中断优先级和触发类型(高电平触发)
    XScuGic_SetPriorityTriggerType(&scugic_inst, intr_id, 0xA0, 0x1);
    //关联中断ID和中断处理函数
    XScuGic_Connect(&scugic_inst, intr_id, print_handler,(void *) intr_id);
    //使能AXI GPIO中断
    XScuGic_Enable(&scugic_inst, intr_id);

    //设置并打开中断异常处理功能
    Xil_ExceptionInit();
    Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
            (Xil_ExceptionHandler)XScuGic_InterruptHandler, &scugic_inst);
    Xil_ExceptionEnable();

    return 0;
}

//中断服务(处理)函数
void print_handler(void *CallbackRef)
{
    printf("print done!\n");
	XGpioPs_WritePin(&gpiops_inst, print_done,1);//中断完成后,将print_done信号拉高,使状态机切换状态
}

上板验证

 烧录好程序后,LD1会亮起,表示此刻处于idle状态

按下BTNR按键后(对应状态机内start命令),ps端会产生一个中断并在右下角terminal内输出一句话“print done!”,然后LD0亮起,表示此刻切换到了状态b,按下BTNL按键后(对应key命令),LD0熄灭,LD1亮起,即又切换回到IDLE状态

 

<think>好的,我现在需要回答用户关于ZynqPL端逻辑是否需要封装成IP才能PS协同工作的问题。首先,我得回忆一下Zynq的基本架构和相关知识。Zynq是Xilinx的SoC,结合了ARM处理器(PS)和FPGAPL)。用户的问题集中在PL端逻辑是否需要封装成IP才能PS交互,以及相关流程。 根据系统级指令中的引用内容,特别是引用[1]和[2],里面提到了IP核在PSPL之间的重要性,以及AXI协议的作用。引用[1]提到PS通过AXI接口访问PL中的IP核,而引用[2]说明AXI是Xilinx用于连接IP核的协议。这可能意味着使用IP核是标准做法,但需要确认是否必须。 首先,用户的问题是“是否必须封装成IP核”。根据经验,虽然AXI接口是主要的数据交互方式,但可能用户可以直接在PL中编写逻辑并手动添加AXI接口,而不使用IP核。但封装成IP核会简化流程,尤其是使用Vivado的IP集成器时会更方便。因此,可能回答是“不一定必须,但推荐”。 接下来,流程部分需要说明两种方式:直接实现AXI接口和使用IP封装。对于直接实现,需要手动编写AXI协议的逻辑,这可能复杂且容易出错。而封装成IP核可以利用工具生成模,简化开发。引用[3]提到初学者可能感到迷糊,因此流程需要清晰分步骤说明,比如创建IP、添加逻辑、生成封装、集成到Block Design等。 另外,需要考虑用户可能的后续问题,比如优化或性能问题,所以在相关问题上可以提出IP核封装的优势,如复用性、兼容性等,以及AXI接口的不同类型选择。 需要确保回答结构清晰,分点说明必要性和流程,同时引用相关的参考资料。最后生成相关问题,帮助用户深入理解,比如必要性、流程步骤、优缺点、替代方案等。</think>在Zynq平台上,PL端逻辑**不一定必须封装成IP核**才能PS协同工作,但通过IP核形式实现是Xilinx推荐的标准流程,能显著提高开发效率和系统可靠性[^1][^2]。以下是具体分析及流程说明: --- ### 一、PL端逻辑PS协同工作的两种方式 1. **直接实现AXI接口** - **无需封装IP核**:PL端逻辑可直接实现AXI协议(如AXI-Lite、AXI-Stream或AXI4),通过自定义硬件模块PS交互。 - **适用场景**:适用于简单逻辑或对时序有特殊要求的场景。 - **缺点**:需手动编写AXI协议状态机开发复杂度高,验证困难,且难以复用[^2]。 2. **封装成IP核** - **标准化流程**:将PL逻辑封装为AXI兼容的IP核,通过Vivado IP Integrator集成到系统中。 - **优势**: - **兼容性**:直接调用Xilinx提供的AXI IP模(如AXI4-Lite从设备模),减少协议实现错误。 - **复用性**:IP核可跨项目复用,支持参数化配置。 - **工具链支持**:Vivado自动生成地址映射、驱动框架及验证环境[^3]。 --- ### 二、封装IP核的典型流程 1. **创建自定义IP** - 在Vivado中使用`Create and Package New IP`工具,选择AXI接口模(如AXI4-Lite)。 - 定义寄存器映射(Register Map),设置数据位宽和地址空间。 2. **添加PL端逻辑** - 在生成的IP模中插入自定义硬件逻辑(Verilog/VHDL)。 - 例:实现一个通过AXI-Lite控制的PWM模块: ```verilog // AXI4-Lite从设备接口 always @(posedge S_AXI_ACLK) begin if (slv_reg_wren && axi_awaddr == 8'h00) pwm_duty <= S_AXI_WDATA; // 通过寄存器配置占空比 end ``` 3. **封装集成** - 使用`Package IP`工具生成.xci文件。 - 在Block Design中将IP核添加到PL端,通过AXI Interconnect连接PS。 4. **软件驱动开发** - Vivado自动生成IP核的地址映射头文件(如`xparameters.h`)。 - PS端通过内存映射访问IP核寄存器: ```c #define PWM_DUTY_REG (*(volatile uint32_t *)0x43C00000) PWM_DUTY_REG = 50; // 设置占空比为50% ``` --- ### 、IP核封装的核心必要性 1. **协议标准化** AXI协议要求严格的握手信号(如VALID/READY),IP核封装可借助Xilinx AXI Infrastructure自动处理时序,避免协议冲突。 2. **资源管理** Vivado通过IP核自动分配地址空间,避免PSPL地址冲突,并生成系统互联逻辑(如Clock/Reset信号)。 3. **协同验证** ​封装后的IP核支持联合仿真(Vivado + SDK/Vitis),可直接在PS端调用驱动函数测试PL逻辑[^3]。 --- ### 四、替代方案注意事项 - **GPIO/EMIO直连**:适用于低速、小数据量场景(如控制LED),但带宽受限。 - **AXI DMA+Stream**:需流式数据传输时,可组合使用DMA IP核自定义Stream逻辑,无需完整封装。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值