疯狂的芯

  • 硬件
  • 软件
  • 随记
  • 折腾
  1. 首页
  2. 软件
  3. 正文

TLFM20S-EVM开发板PS和PL联合开发且程序运行在DDR中的工程搭建

2026年3月14日

工程目标

基于TLFM20S-EVM开发板,搭建PS和PL联合开发的基础功能,使用PS侧的CPU通过EMIO控制PL侧的LED灯闪烁,同时程序运行在DDR中。

开发环境

  • PL开发工具:VIVADO 2018.3,主要用于PL侧逻辑开发和使用XILINX丰富的IP资源(若无需复杂的IP资源,则可以单独使用PROCISE)。
  • PS开发工具:IAR 8.11.2.13606,用于编写PS侧的C语言
  • 转换工具:PROCISE 2025.1.1,用于转换VIVADO工程,生成相应的BSP供后续PS开发。
  • 开发板:TLFM20S-EVM,核心芯片为复旦微的FMQL20S400M,对标XILINX的XC7Z020CLG400-2。
  • 下载器:XILINX的JTAG下载器、JLINK仿真器。

工程搭建步骤

  1. 按照《TLFM20S-EVM开发板PS和PL联合开发工程搭建》完成工程搭建,并下载程序进入调试模式。
  2. 调试模式中,暂停程序运行,打开View -> Disassembly。

    image

    可以查看目前程序运行在0xE1FE_xxxx地址,属于AHB_SRAM范围(0xE1FE_0000 ~ 0xE1FF_FFFF)。说明程序运行在AHB_SRAM中。

    image

  3. 退出调试模式,关闭IAR。打开VIVADO,先打开Block Design。

    image

  4. 双击ZYNQ核进行配置。Page Navigator选择DDR Configuration,首先勾选Enable DDR,然后打开DDR Controller Configuration,Memory Type选择DDR3(Low Voltage),Memory Part选择MT41K128M16 JT-125。然后单击OK。

    image

    回到Block界面,选择DDR引脚,右击Make External,将DDR引脚引出。

    image

    最终完成的Block如下图。

    image

  5. 然后编译Block,最后生成wrapper HDL。修改top.v文件如下。

    `timescale 1ns / 1ps
    //////////////////////////////////////////////////////////////////////////////////
    // Company: 
    // Engineer: 
    // 
    // Create Date: 2026/02/28 22:44:57
    // Design Name: 
    // Module Name: top
    // Project Name: 
    // Target Devices: 
    // Tool Versions: 
    // Description: 
    // 
    // Dependencies: 
    // 
    // Revision:
    // Revision 0.01 - File Created
    // Additional Comments:
    // 
    //////////////////////////////////////////////////////////////////////////////////
    
    module top(
        DDR_0_addr        ,
        DDR_0_ba          ,
        DDR_0_cas_n       ,
        DDR_0_ck_n        ,
        DDR_0_ck_p        ,
        DDR_0_cke         ,
        DDR_0_cs_n        ,
        DDR_0_dm          ,
        DDR_0_dq          ,
        DDR_0_dqs_n       ,
        DDR_0_dqs_p       ,
        DDR_0_odt         ,
        DDR_0_ras_n       ,
        DDR_0_reset_n     ,
        DDR_0_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 ,
        PJTAG_0_tck       ,
        PJTAG_0_tdi       ,
        PJTAG_0_tdo       ,
        PJTAG_0_tms       ,
    
        PIN_PL_LED_OUT  
        );
    
        inout [14:0]    DDR_0_addr;
        inout [2:0]     DDR_0_ba;
        inout           DDR_0_cas_n;
        inout           DDR_0_ck_n;
        inout           DDR_0_ck_p;
        inout           DDR_0_cke;
        inout           DDR_0_cs_n;
        inout [3:0]     DDR_0_dm;
        inout [31:0]    DDR_0_dq;
        inout [3:0]     DDR_0_dqs_n;
        inout [3:0]     DDR_0_dqs_p;
        inout           DDR_0_odt;
        inout           DDR_0_ras_n;
        inout           DDR_0_reset_n;
        inout           DDR_0_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;
        input           PJTAG_0_tck;
        input           PJTAG_0_tdi;
        output          PJTAG_0_tdo;
        input           PJTAG_0_tms;
    
        output [0:0]    PIN_PL_LED_OUT;
    
        system_wrapper system(
            .DDR_0_addr          (DDR_0_addr       ),
            .DDR_0_ba            (DDR_0_ba         ),
            .DDR_0_cas_n         (DDR_0_cas_n      ),
            .DDR_0_ck_n          (DDR_0_ck_n       ),
            .DDR_0_ck_p          (DDR_0_ck_p       ),
            .DDR_0_cke           (DDR_0_cke        ),
            .DDR_0_cs_n          (DDR_0_cs_n       ),
            .DDR_0_dm            (DDR_0_dm         ),
            .DDR_0_dq            (DDR_0_dq         ),
            .DDR_0_dqs_n         (DDR_0_dqs_n      ),
            .DDR_0_dqs_p         (DDR_0_dqs_p      ),
            .DDR_0_odt           (DDR_0_odt        ),
            .DDR_0_ras_n         (DDR_0_ras_n      ),
            .DDR_0_reset_n       (DDR_0_reset_n    ),
            .DDR_0_we_n          (DDR_0_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),
            .GPIO_O_0            (PIN_PL_LED_OUT   ),
            .PJTAG_0_tck         (PJTAG_0_tck      ),
            .PJTAG_0_tdi         (PJTAG_0_tdi      ),
            .PJTAG_0_tdo         (PJTAG_0_tdo      ),
            .PJTAG_0_tms         (PJTAG_0_tms      )
        );
    
    endmodule
  6. VIVADO中重新编译工程,生成bit。
  7. 打开原Procise工程,PSOC -> From Vivado,按之前从VIVADO工程中导入的步骤完成Load Block Design配置。

    image

    导入过程中提示Overwrite Operation,选择Yes即可。

    image

    然后提示Make Interface External,选择OK即可。

    image

  8. 弹出Export Hardware对话框,勾选Empty和FSBL,然后单击OK即可。稍等片刻,会自动打开IAR工程。

    image

  9. 首先修改ICF文件,打开工程文件夹,procise -> SDK -> system_platform -> Empty,将a7_ahbsram.icf复制一份,并改名为a7_ddr_me.icf。然后使用文本编辑器打开,做如下修改。

    修改ICFEDIT_PS_DDR_end地址为0x20100000。(因为开发板配置的DDR为512MB;若配置了1GB,则无需修改)

    修改ICFEDIT_region_RAM_start和ICFEDIT_region_RAM_end的地址为ICFEDIT_PS_DDR_start和ICFEDIT_PS_DDR_end。(将RAM映射地址由AHB_SRAM改为PS DDR)

    image

    其余无需修改,保存即可。

  10. 回到IAR,workspace区域选择下方的Empty(即将Empty工程设为active)。然后单击Empty-Debug,右击选择Option。

    image

  11. Options for node "Empty"对话框中,Category中选择Linker,右侧选择Config,Linker Configuration file中选择...,找到前文修改的a7_ddr_me.icf文件。

    image

  12. 然后Category中选择J-Link/J-Trace,右侧选择Setup,Reset中选择Software。(因为调试时,先使用IAR加载FSBL文件,完成DDR初始化;然后再下载开发的APP文件。若下载的APP文件选择硬件复位,则会清除DDR的初始化状态,导致程序加载错误,故改为软件复位)

    image

  13. 单击OK关闭Options对话框。打开empty.c文件,注释init_platform()调用,新增icache_enable()调用。如下:

     #include "platform.h"
    
     #include "fmsh_gpio_public.h"
     #include "fmsh_ps_parameters.h"
    
     void main()
     {
         //init_platform();
         icache_enable();
    
         //Enable USER_LEVEL_SHIFTER REG
         FMSH_WriteReg(FPS_SLCR_BASEADDR, 0x008, 0xDF0D767BU);       //unlock SLCR
         FMSH_WriteReg(FPS_SLCR_BASEADDR, 0x838, 0xF);               //enablue usr_lvl_shifter        
         FMSH_WriteReg(FPS_SLCR_BASEADDR, 0x004, 0xDF0D767BU);       //lock SLCR
    
         FGpioPs_Config* gpio_cfgPpr;
         gpio_cfgPpr = FGpioPs_LookupConfig(FPAR_GPIOPS_2_DEVICE_ID);
    
         FGpioPs_T gpios;
         FGpioPs_init(&gpios, gpio_cfgPpr);
         FGpioPs_setDirection(&gpios, 0xf);
    
         while(1)
         {
             FGpioPs_writeData(&gpios, FMSH_BIT0);
             delay_ms(500);
             FGpioPs_writeData(&gpios, 0x0);
             delay_ms(500);
         }
    
         //example_test(Device_ID);
     }
  14. 单击Empty-Debug,右击,选择Rebuild All。编译完成即可。

    image

  15. workspace区域选择下方的FSBL(即将FSBL工程设为active)。单击FSBL-Deubg,右击选择Rebuild All。编译完成即可。

    image

  16. 给开发板接上xilinx下载器和JLINK仿真器,配置的拨码开关选择JTAG独立模式([3:0] = 1000),然后开发板加电。
  17. 回到VIVADO,烧写bit。
  18. 回到IAR,workspace下方选择FSBL,单击Download and Debug,下载FSBL程序并进入调试模式。单击Go,运行3-5秒钟即可退出调试模式。(此时已完成DDR的初始化)
  19. workspace下方选择Empty,单击Download and Debug,下载Empty程序并进入调试模式。单击Go,可以看到开发板上EMIO控制的LED灯在闪烁。
  20. 单击Break,中断程序运行。View -> Core,打开Cores窗口,可以看到PC寄存器的地址范围在0x0010_0000 ~ 0x3FFF_FFFF之间,该区域为DDR3的地址范围,说明程序运行在DDR中。(注,因开发板DDR实际大小为512MB,故PC寄存器的地址范围应在0x0010_0000 ~ 0x2010_0000之间)。

‍

总结:

  • ICF文件要修改正确。
  • APP工程的复位要改为软件复位,否则会重置DDR的状态,没法进行程序调试。
  • 软件烧写先后顺序:bit -> FSBL -> APP。
  • 开发板配置要正确,否则FSBL烧写完成后,会自动按配置进行加载,如SPI模式,则会读取SPI内的程序,导致后续APP烧写无法连接JLINK等问题。
  • APP的初始代码要屏蔽ps_init()调用(通过注释main中的init_platform()),防止重复初始化DDR。
  • 仅使能icache,不要使能dcache(dcache的使能方式还未摸索出来,使能会导致程序进入异常中断)。

如果这篇文章对您有帮助,欢迎打赏支持。

若需要工程原文件,请打赏5元后发送索取邮件到crazychip999@qq.com,记得附上打赏截图。

标签: DDR PS和PL联合开发 TLFM20S-EVM
最后更新:2026年3月15日

疯狂的芯

这个人很懒,什么都没留下

打赏 点赞
< 上一篇
下一篇 >
最新 热点 随机
最新 热点 随机
高云FPGA开发软件资源利用率在哪看? 光耦APY215S输出端不闭合或者闭合后缓慢断开的原因 GJB1032A-2020《电子产品环境应力筛选方法》概述 TLFM20S-EVM开发板PS和PL联合开发且程序运行在DDR中的工程搭建 TLFM20S-EVM开发板PS和PL联合开发工程搭建 电阻的额定电压、最高电压、最大过载电压
TLFM20S-EVM开发板PS和PL联合开发且程序运行在DDR中的工程搭建GJB1032A-2020《电子产品环境应力筛选方法》概述光耦APY215S输出端不闭合或者闭合后缓慢断开的原因高云FPGA开发软件资源利用率在哪看?
电阻的额定环境温度和使用温度范围 Coding平台、TortoiseGit和Git三者搭配使用 LTspice工具栏样式切换 电阻的额定电压、最高电压、最大过载电压 华为NAE12S03-B测试结果 快断保险丝和慢断保险丝的区别
标签聚合
PS和PL联合开发 PROCISE 最高电压 TLFM20S-EVM 最大过载电压 电阻 VIVADO GJB1032A-2020

COPYRIGHT © 2025 疯狂的芯. ALL RIGHTS RESERVED.

Theme Kratos Made By Seaton Jiang

苏ICP备14059515号