前言:ZYNQ型号7010,vivado版本2018.3
此次例程完成PS的串口并通PS通过AXI控制PL的灯
一、PS与PL互通IP核ZYNQ Processing system
IP核中的选项卡介绍:
PS-PL Configuration 选项卡能够配置 PS-PL接口,包括AXI、HP和ACP总线接口。
Peripheral IO Pins 选项卡可以为不同的 I/O 外设选择MIO/EMIO配置。
MIO Configuration 选项卡可以为不同的I/O 外设具体配置MIO/EMIO。
Clock Configuration 选项卡用来配置 PS输入时钟、外设时钟,以及DDR和CPU时钟等。
DDR Configuration 选项卡用于设置DDR控制器配置信息。
SMC Timing Calculation 选项卡用于执行 SMC 时序计算。
Interrupts 选项卡用于配置PS-PL中断端口。
1.Peripheral I/O Pins 标签
在此选项卡中选中UART以及对应的引脚(需要查原理图)
如上图所示,此板子的UART接到了PL的C5和C8引脚,并复用为了PS中MIO的14和15引脚,所以根据14、15这俩MIO选择了UART0,且为3.3V的BANK,如下图所示:
当以上步骤操作完成了就可以在PS-PL Configurtion选项卡中详细配置串口的波特率等信息
不使用FLCK的复位信号(在Clock Configuration中解释),使用一路AXI作为传输通道
Clock Configuration
根据原理图所示,PS的系统时钟为33.333333MHz(通常ZYNQ的PS时钟频率都为此,输入范围:30MHz-60MHz),在Clock Configuration选项卡中(本次例程不进行超/降频处理,所以选择默认的时钟频率即可)
在时钟配置界面的其他选项一一解释如下:
在基本时钟配置(BASIC CLOCKING)界面中:
系统/存储时钟配置(Processing/Mermory Clocks):
CPU PLL:分配给ARM Cortex-A9处理器
DDR PLL:分配给DDR存储器控制器。
I/O PLL:分配给各种I/O外设,如UART、SPI、I2C等
PL Fabric Clocks:PS输出给PL的时钟,可配置不同的频率
由此上介绍可知,此例程PL不需要PS的时钟(因为PL有自己的时钟晶振),所以取消掉FCLK_CLKx以及对应的复位信号FCLK_RESETx_N(在PS-PL Configuration选项卡中,并且要选择一路AXI作为传输接口)
3.DDR Configuration
因为PS程序运行需要内存,且内存就为DDR,所以DDR需要选择到,并根据原理图确定DDR的型号
4.例化bd文件
初始图如下
接口接完如下
axim_clk选择100m,axim_rstn选择低电平有效,axim_ctrl为AXI4_LITE,地址和数据线都选择32位
给AXI分配地址(0通道为43C开头,1通道为83C开头),因为本例程选的0通道,所以为43C开头
我写了AXI的对应Verilog程序,中定义了两个地址,分别为版本号(只读,基地址+0x0000)和LED灯控制(只写,基地址+0x0004)
然后保存,并生成bd,编译并launch到sdk,sdk自动创建一个项目,在此项目新建一个applatcion工程,选helloworld,此helloworld就为串口打印,将PL和PS分别在线烧写到芯片里,打开串口软件就可以看到Hello World的打印了
5.PL与PS互相读写AXI
PL端读写代码如下:
always @ (posedge usr_clk or posedge usr_rst) begin
if (usr_rst) begin
r_led_enable <= 1'b0;
end else begin
if (o_axi_wready && i_axi_wvalid) begin
case (r_axi_awaddr)
C_LED_ENABLE : r_led_enable <= i_axi_wdata[0]; //pl receive ps data
default : ;
endcase
end
end
end
assign o_led_enable = r_led_enable; //control led on/off
always @ (posedge usr_clk or posedge usr_rst) begin
if (usr_rst) begin
r_axi_rdata <= 32'h0;
end else begin
case (r_axi_araddr)
C_VERSION : r_axi_rdata <= VERSION;
default : r_axi_rdata <= 32'h0;
endcase
end
end
assign o_axi_rdata = r_axi_rdata; //tran pl data to ps
PS端AXI读写如下:
//读AXI版本号
uint32_t Read_AxiData(uint32_t addr)
{
return (uint32_t)Xil_In32(BASE_ADDR + addr);
}
//PL端的LED1点亮
void Led_On(void)
{
Xil_Out32(BASE_ADDR + LED_ADDR , 0x1);
}
//PL端的LED1熄灭
void Led_Off(void)
{
Xil_Out32(BASE_ADDR + LED_ADDR , 0x0);
}
int main()
{
init_platform();
printf("%x\n\r",Read_AxiData(VERSION_ADDR));
while(1) {
Led_On();
sleep(1);
Led_Off();
sleep(1);
}
cleanup_platform();
return 0;
}