赞
踩
项目需求,FPGA的程序部署到ZYNQ上。查了一下发现网上几乎所有的教程都是打包成IP核,这对于我这个多层文件多个IP核很难实现。整体打包始终报错,加上觉得后面修改程序啥的太麻烦,而且PS和PL数据传输比较少,没有时效性要求。就尝试将PL和PS独立出来,方便修改。我觉得这应该是个挺常见的需求不知道为什么搜不到,可能关键字没找对。
再次强调,ZYNQ是个有PL外设的ARM。这就很好办了。首先block design反应了各个模块和ARM 核的关系,生成的wrapper也就是最终的外设部署。那么只要在顶层文件中直接添加PL模块,实现了PS和PL 的并列排布。PS和PL的数据通过AXI总线访问,预留端口,在顶层模块中直接wire 相连即可
程序涉密,所以用个简单的PL程序代替。
PL程序如图。除了心跳灯,就是assign将ps输入的数据回传给ps。
将一个AXI lite的总线打包为IP核
顶层添加输入输出
低层添加
AXI总线改写,用过的都懂
将AXI的IP核添加到block design,并引出输入输出
接下来就生成底层文件,并将PL模块添加到其中
- `timescale 1 ps / 1 ps
-
- module ps_system_wrapper
- (DDR_addr,
- DDR_ba,
- DDR_cas_n,
- DDR_ck_n,
- DDR_ck_p,
- DDR_cke,
- DDR_cs_n,
- DDR_dm,
- DDR_dq,
- DDR_dqs_n,
- DDR_dqs_p,
- DDR_odt,
- DDR_ras_n,
- DDR_reset_n,
- DDR_we_n,
- FIXED_IO_ddr_vrn,
- FIXED_IO_ddr_vrp,
- FIXED_IO_mio,
- FIXED_IO_ps_clk,
- FIXED_IO_ps_porb,
- FIXED_IO_ps_srstb,
- led,
- clk,
- rst_n
- );
- inout [14:0]DDR_addr;
- inout [2:0]DDR_ba;
- inout DDR_cas_n;
- inout DDR_ck_n;
- inout DDR_ck_p;
- inout DDR_cke;
- inout DDR_cs_n;
- inout [3:0]DDR_dm;
- inout [31:0]DDR_dq;
- inout [3:0]DDR_dqs_n;
- inout [3:0]DDR_dqs_p;
- inout DDR_odt;
- inout DDR_ras_n;
- inout DDR_reset_n;
- inout DDR_we_n;
- inout FIXED_IO_ddr_vrn;
- inout FIXED_IO_ddr_vrp;
- inout [53:0]FIXED_IO_mio;
- inout FIXED_IO_ps_clk;
- inout FIXED_IO_ps_porb;
- inout FIXED_IO_ps_srstb;
- output[3:0] led;
- input clk;
- input rst_n;
-
- wire [14:0]DDR_addr;
- wire [2:0]DDR_ba;
- wire DDR_cas_n;
- wire DDR_ck_n;
- wire DDR_ck_p;
- wire DDR_cke;
- wire DDR_cs_n;
- wire [3:0]DDR_dm;
- wire [31:0]DDR_dq;
- wire [3:0]DDR_dqs_n;
- wire [3:0]DDR_dqs_p;
- wire DDR_odt;
- wire DDR_ras_n;
- wire DDR_reset_n;
- wire DDR_we_n;
- wire FIXED_IO_ddr_vrn;
- wire FIXED_IO_ddr_vrp;
- wire [53:0]FIXED_IO_mio;
- wire FIXED_IO_ps_clk;
- wire FIXED_IO_ps_porb;
- wire FIXED_IO_ps_srstb;
- wire [31:0]pl_to_ps_0;
- wire [31:0]ps_to_pl_0;
-
- ps_system ps_system_i
- (.DDR_addr(DDR_addr),
- .DDR_ba(DDR_ba),
- .DDR_cas_n(DDR_cas_n),
- .DDR_ck_n(DDR_ck_n),
- .DDR_ck_p(DDR_ck_p),
- .DDR_cke(DDR_cke),
- .DDR_cs_n(DDR_cs_n),
- .DDR_dm(DDR_dm),
- .DDR_dq(DDR_dq),
- .DDR_dqs_n(DDR_dqs_n),
- .DDR_dqs_p(DDR_dqs_p),
- .DDR_odt(DDR_odt),
- .DDR_ras_n(DDR_ras_n),
- .DDR_reset_n(DDR_reset_n),
- .DDR_we_n(DDR_we_n),
- .FIXED_IO_ddr_vrn(FIXED_IO_ddr_vrn),
- .FIXED_IO_ddr_vrp(FIXED_IO_ddr_vrp),
- .FIXED_IO_mio(FIXED_IO_mio),
- .FIXED_IO_ps_clk(FIXED_IO_ps_clk),
- .FIXED_IO_ps_porb(FIXED_IO_ps_porb),
- .FIXED_IO_ps_srstb(FIXED_IO_ps_srstb),
- .pl_to_ps_0(pl_to_ps_0),
- .ps_to_pl_0(ps_to_pl_0));
-
-
- wire [3:0] led;
- wire clk;
- wire rst_n;
- led_stream pl_system
- (
- .led(led),
- .clk(clk),
- .rst_n(rst_n),
- .cnt_output_pl2ps(pl_to_ps_0),

最终的效果如图所示
可以看到实现了PS和PL 的并列
裸机 SDK程序如图,写入、加一、读出、串口打印
串口打印,可以看到满足了需求
linux系统代码测试如图:
- 22 #define ZYNQ_AXI_REG_BASE 0x43C00000
- 23 #define WRITE_AXI_REG_BASE 0
- 24 #define READ_AXI_REG_BASE 4
- 25
- 26
- 27 /* 映射后的寄存器虚拟地址指针 */
- 28 static void __iomem *write_addr;
- 29 static void __iomem *read_addr;
- 30
- 31 static int AXI_wr_rd_init(void)
- 32 {
- 33 u32 val = 100;
- 34 //int ret;
- 35
- 36 /* 寄存器地址映射 */
- 37 write_addr = ioremap(ZYNQ_AXI_REG_BASE + WRITE_AXI_REG_BASE, 4);
- 38 read_addr = ioremap(ZYNQ_AXI_REG_BASE + READ_AXI_REG_BASE, 4);
- 39
- 40 printk("testing……");
- 41
- 42 writel(val, write_addr);
- 43 msleep(1000);
- 44 val = readl(read_addr);
- 45
- 46 printk("%d",val);
- 47
- 48 /* 取消寄存器地址映射 */
- 49 iounmap(write_addr);
- 50 iounmap(read_addr);
- 51
- 52 return 0;
- 53 }

通过ioremap找到linux中的虚拟地址之后写入,读出
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。