Zynq PL端调用PS端的时钟

本文介绍了在XCZU21DR环境下,如何配置ZynqUltraScale+MPSocIP,由PS端提供100MHz时钟给PL端,PL端通过计数器模块clk_div_N产生1S信号,用于控制LED闪烁。经过综合和实现后,上板测试成功。

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

ZYNQ PS端最多可以分配4个时钟供给PL端使用,见下图。

 本文的目的:在XCZU21DR环境下,PS给PL提供一个100MHz的时钟,PL端根据此时钟产生1S信号,点亮LED。

添加&配置Zynq UltraScale+ MPSoc IP

双击该IP,在Clock Configuration -> Output Clocks -> Low Power Domain Clocks -> PL Fabric Clocks中设置见上图。

这个PL Fabric Clocks就是PS提供给PL的100MHz时钟。
最终将pl_clk0引出,得到下图。

 执行Generate Output Products和Create HDL Wrapper,最后修改顶层文件如下:

module design_1_wrapper(
  output led
);

wire pl_clk0_0;

design_1 design_1_i(
.pl_clk0_0(pl_clk0_0));

clk_div_N #(
  //.FREQ_WORD(32'd43)  //1S闪烁1次
  // .FREQ_WORD(32'd20) //2S闪烁1次
  .FREQ_WORD(32'd86)    //0.5S闪烁1次
) clk_div_N_inst(
  .clk_in(pl_clk0_0),
  .rst_n(1'b1),
  .clk_out(led)
);

endmodule

 clk_div_N内容如下:

//clk_in = 50MHz, 可任选
//clk_out = clk_inK/(2^32),32表示计数器位数
//频率控制字FREQ_WORD = clk_out(2^32)/clk_in, 32表示计数器位数
module clk_div_N #(
  parameter FREQ_WORD = 32'd1431655765 //3分频
) (
  input clk_in,
  input rst_n,
  output reg clk_out);
  
//--------------------------------------
reg [31:0] max_value;

always@(posedge clk_in or negedge rst_n)
begin
  if(!rst_n)
    max_value <= 1'b0;
  else
    max_value <= max_value + FREQ_WORD;
end

//--------------------------------------
always@(posedge clk_in or negedge rst_n)
begin
  if(!rst_n)
    clk_out <= 1'b0;
  else
  begin
    if(max_value < 32'h7FFF_FFFF)
    clk_out <= 1'b0;
  else
  clk_out <= 1'b1;
  end
end

endmodule

执行综合、实现后,完成led的引脚约束即可,见下图。

 代码经过上板测试通过。

 

 

### Zynq PSPL之间通过UART实现串口通信 在Zynq SoC架构中,PSProcessing System)和PL(Programmable Logic)可以通过多种方式进行通信,其中一种常见的方式是使用UART Lite IP核来扩展PL中的串口功能,并结合PS的UART控制器完成数据交互[^3]。 #### 初始化PSUART 为了使能PS的UART通信,在硬件设计阶段需确保已启用相应的UART外设。随后可通过软件代码初始化该UART模块,包括设置波特率、停止位、校验模式等参数。以下是典型的初始化过程: ```c #include "xuartps.h" #define UART_DEVICE_ID XPAR_XUARTPS_0_DEVICE_ID int UartPsInitExample() { int Status; XUartPs Uart; // 创建XUartPs实例 /* 初始化UART */ Status = XUartPs_CfgInitialize(&Uart, XUartPs_LookupConfig(UART_DEVICE_ID), UART_DEVICE_ID); if (Status != XST_SUCCESS) { return XST_FAILURE; } /* 设置工作参数 */ XUartPs_SetBaudRate(&Uart, 115200); // 设置波特率为115200bps XUartPs_Send(&Uart, (u8*)"Initialization Complete\r\n", strlen("Initialization Complete\r\n")); return XST_SUCCESS; } ``` 上述代码片段展示了如何初始化PS的UART并发送一条测试消息[^1]。 #### 使用UART Lite IP核扩展PL侧串口 对于需要额外串口的应用场景,可以借助Vivado工具链中的`UART Lite` IP核创建新的串口通道。此IP核允许用户定义特定的工作频率及时钟分频因子以适配目标系统的时序需求。下面是一个简单的TCL脚本示例,用于向项目添加UART Lite组件及其连接关系: ```tcl set ipName uart_lite_0 create_ip -name axi_uartlite -vendor xilinx.com -library ip -module_name $ipName set_property -dict [list CONFIG.C_BAUDRATE {115200}] [get_ips $ipName] generate_target all [get_files ./$ipName/$ipName.xci] export_ip_user_files -of_objects [get_files ./$ipName/$ipName.xci] -no_script -sync -force -quiet ``` 这段脚本自动配置了一个运行于115200 bps速率下的UART Lite实例。 #### 数据交换流程说明 当PS接收到来自外部设备的数据包后,它会触发中断通知处理器执行回调函数处理新到达的信息;与此同时,也可以主动调用API将待传递的内容写入缓冲区等待传输至指定的目标地址。而位于FPGA fabric内部的UART Lite则负责监听物理层信号变化并将捕获到的有效载荷转发出去或者反之亦然[^4]。 例如,假设我们已经建立了双向链接,则可以在应用程序层面编写如下逻辑控制读取操作: ```c char RxBuffer[256]; unsigned int ByteCount; /* 接收数据直到遇到回车符 */ ByteCount = XUartPs_Recv(&Uart, (u8*)RxBuffer, sizeof(RxBuffer)-1); if(ByteCount > 0){ RxBuffer[ByteCount]='\0'; // 添加字符串终止标志 printf("Received Message:%s\n",RxBuffer); // 将相同的消息反射回去作为响应动作 XUartPs_Send(&Uart,(u8 *)RxBuffer,strlen((const char *)RxBuffer)); } else{ fprintf(stderr,"Error during reception.\n"); } ``` 以上程序段体现了基本的回显机制——即每当检测到来自远节点的一条完整记录之后立即将其原样返回给对方确认接收成功与否。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

努力不期待

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值