一,摘要

本文主要用于记录作者本人实现ZYNQ动态修改LUT内容过程中主要参考的资料,实现的步骤,遇到的问题等。主要参考的文章链接如下:https://cloud.tencent.com/developer/article/1528881,其中该工作大部分的原理部分该篇博客都有介绍,本篇博客不再赘述。
在此我主要介绍一下使用Vivado进行部分动态重构系统的开发流程AXI_HWICAP IP基本的使用方法,以及通过ARM部分实现LUT内容动态修改的程序流程(此部分见下篇博客)

二,系统框图


系统结构主要如上图,其中LUT的读写操作由PS端的程序控制,通过PC端的串口助手可以观察读取的配置帧数据,设置要修改的LUT位置以及修改后的LUT中的新数据。

三,PL工程的创建,综合,布局布线。

考虑到调试过程中可能要多次设置目标LUT的初始值来搞清楚bitstream中数据与LUT中数据的映射关系,为了提高该系统的编译调试效率,本文针对目标操作的LUT采取局部动态重构的设计方法。实际应用中不采用部分重构设计流程也可以对LUT进行动态读写。
以下是本次设计使用Vivado进行部分重构系统开发的整体流程:

  1. 使用Vivado创建整个设计,将部分重构模块保留为空模块。综合工程生成静态设计的.dcp文件(如top_syn_static.dcp)。
  2. 综合部分重构模块的源文件,生成对应的.dcp文件(如:pr_lut_syn.dcp)。
  3. 打开第一步生成的top_syn_static.dcp,读入第二步生成的pr_lut_syn.dcp,设置重构属性,保存设计点。
  4. 为重构模块指定重构区域,读入约束文件。
  5. 优化,布局,布线,保存设计点。
  6. 生成bitstream文件,及ila调试相关文件。
  7. 将重构模块清除保留为黑盒,将其他部分在布局布线后的级别上保存其设计点。
  8. 打开上一步保存的设计点,读入新的重构模块,优化,布局布线,保存设计点,生成bitstream等。
  9. 使用pr_verify指令对生成的bitstream进行验证。

第一步,创建设计。

可直接在给出的工程目录下面执行脚本自动创建,综合,以及硬件的导出。在工程目录下执行以下代码(windows下需要在Vivado的命令行下操作):

source ./tcl/step1_create_project.tcl

具体工程文件结构如下图所示:

其中原理图部分如下:

这一步我们要用到的文件为.\vivado\lut_modify.runs\synth_1\top.dcp,我们需要将此文件复制到.\checkpoints\synth\static\路径下,便于后续操作。
当然也可以自己手动来创建工程,编写相关文件。

第二步,综合重构模块

直接执行脚本文件即可,脚本代码如下:

read_verilog ./src/rms/pr_lut1/pr_lut.v
synth_design -mode out_of_context -flatten_hierarchy rebuilt -top pr_lut -part xc7z020clg400-1
write_checkpoint ./checkpoints/synth/rms/pr_lut1.dcp
close_design
close_project

以下是重构模块的verilog代码,该模块例化一个内部的固定位置的LUT,便于我们以后寻址更改其内部内容:

`timescale 1ns/1ps //*******************
//DEFINE MODULE PORT
//*******************
module  pr_lut   (     input           clk  ,input           rst  ,input   [5:0]   din  ,output  reg     dout         ) ;//*********************
//INNER SIGNAL DECLARATION
//*********************
//REGS
reg [5:0] din_ff ;//WIRESwire  dout_pre ;
//*********************
//MAIN CORE
//*********************
always @(posedge clk or posedge rst) beginif (rst == 1'b1) begindin_ff <= 'd0 ;endelse begindin_ff <= din ;end
endalways @(posedge clk or posedge rst) beginif (rst == 1'b1) begindout <= 'd0 ;endelse begindout <= dout_pre ;end
end
// 0001 0010 0011(* DONT_TOUCH= "TRUE" *) (*BEL="D6LUT",LOC="SLICE_X57Y53"*)    LUT6 #(.INIT(64'h1234123412341234)  // Specify LUT Contents ) LUT6_inst_D_right (.O(dout_pre),   // LUT general output.I0(din_ff[0]), // LUT input.I1(din_ff[1]), // LUT input.I2(din_ff[2]), // LUT input.I3(din_ff[3]), // LUT input.I4(din_ff[4]), // LUT input.I5(din_ff[5])  // LUT input);//*********************
endmodule

该步操作主要生成的文件如下图,后面可用不同lut初始值的rm来创建完整设计,方便在bitstream文件中找到目标lut配置数据的位置及内容。便于分析bitstream配置数据同实际LUT中数据的映射关系:

第三步,打开设计点,读入重构模块,划分重构区域

执行以下脚本

open_checkpoint ./checkpoints/synth/static/top.dcp
read_checkpoint -cell pr_lut_0 ./checkpoints/synth/rms/pr_lut1.dcp
set_property HD.RECONFIGURABLE 1 [get_cells pr_lut_0]
write_checkpoint ./checkpoints/synth/top_link_lut.dcp -force #划分重构区域。
startgroup
create_pblock pblock_pr_lut_0
resize_pblock pblock_pr_lut_0 -add {SLICE_X54Y50:SLICE_X59Y59 RAMB18_X3Y20:RAMB18_X3Y23 RAMB36_X3Y10:RAMB36_X3Y11}
add_cells_to_pblock pblock_pr_lut_0 [get_cells [list pr_lut_0]] -clear_locs
endgroup

其中为重构模块划分重构区域手动操作如下图,然后在layout上面绘制相应的重构区域即可,注意:此例中由于指定了LUT的位置信息,所以重构区域必须覆盖到该LUT的物理区域。

此例中划分的重构区域如下:

第四步,优化,布局布线,保存设计点,生成.bit及.rbt文件。

直接执行以下命令:

opt_design
place_design
route_design
write_checkpoint -force ./checkpoints/implement/top_route_design.dcp
write_checkpoint -force -cell pr_lut_0 ./checkpoints/implement/pr_lut_instance_route_design.dcp
write_bitstream  -raw_bitfile ./bitstreams/top1 -force
write_debug_probes -force ./bitstreams/top

执行上述命令后可以观察到器件已经完成布局布线,此时可生成对应的bitstream文件及部分bitstream文件。我们可通过生成的top.rbt来分析top.bit的结构,(top.rbt为top.bit的二进制asii格式表示,可通过python脚本来将rbt文件转换为16进制格式表示数据并保存为txt文件,后续我们从器件中读配置数据的时候要与之进行对比,来验证读操作的正确性

第五步,保存静态设计。

脚本命令如下:

update_design -cell pr_lut_0 -black_box
lock_design -level routing
write_checkpoint -force ./checkpoints/routed/static_route_design.dcpupdate_design -buffer_ports -cell pr_lut_0
place_design
route_design
write_checkpoint -force ./checkpoints/implement/top_route_design.dcp
close_project

第六步,读入新的重构模块,生成的完整bit文件及部分bit文件。

脚本和上面操作多有重复,这里不再给出。
本操作的意义在于利用前面保存过的静态设计,载入新的重构模块进行综合,布局布线,大大减少了整个工程综合,布局布线的时间成本。
针对此次设计任务需求,需要多次更改目标LUT的初始值,采用此种设计流程能够大大减少后期bitstream文件的生成时间,而不必牵一发而动全身,每次都浪费这么长的时间来进行类似的操作。

第七步,验证两个设计是否兼容。

脚本命令如下:

pr_verify -initial ./checkpoints/implement/top_route_design.dcp  -additional {./checkpoints/implement/top_route_design2.dcp }
close_project

验证结果如下图

至此整个重构系统基于Vivado的脱离上下文的设计流程结束。

四、AXI_HWICAP相关信息

相关寄存器如下表:



读写配置:

  1. 将bitstream写进写FIFO寄存器进行配置。
  2. 从读FIFO寄存器读取配置bitstream。
  3. 向CR寄存器写值去启动bitstream的读取或写入,控制寄存器决定了数据传输的方向。向控制寄存器写入0x00000001开始写配置。写0x00000002开始读配置。
  4. 状态寄存器的Done位表明了ICAPEn接口是否处于忙碌状态,并不代表读配置或写配置是否成功完成。
  5. 在成功进行读或者写配置之后硬件清零CR寄存器。
  6. 在CR寄存器未被清零的情况下,软件不能初始化另一个读或写配置操作。

精简模式下写序列:

  1. 将指令写进写FIFO寄存器进行配置。
  2. 向控制寄存器写控制字初始化写指令。
  3. 成功完成配置后硬件清零控制寄存器位。
  4. 向写FIFO寄存器写入第二个指令,写控制字执行向ICAPEn端口的写操作。
  5. 继续执行上述操作直到所有指令被写到ICAPEn端口。

中止:

  1. 向控制寄存器写控制字开始bitstream读写。
  2. 将bitstream写入到FIFO寄存器执行配置,从读FIFO寄存器获取读取到的bitstream。
  3. 向控制寄存器的第五位写1来执行中止。
  4. 状态寄存器的Done位显示了ICAPEn端口是否正处于忙碌状态,不表示读,写操作成功完成。
  5. 在成功执行中止操作后硬件清零控制寄存器位。
  6. 在CR寄存器未被清零的情况下,软件不能初始化另一个读或写配置操作。

注意:

  1. 帧是配置数据允许被读或写的最小粒度。
  2. 修改单个LUT内容必须读出整帧,修改后再将整帧数据读入。

五、总结

本篇博客主要记录了使用Vivado工具进行脱离上下文(Out Of Context)方式进行开发的流程。以本篇生成的硬件系统为基础,可以进一步通过PS端的软件编程来实现对目标LUT的内容进行修改,亦可通过软件来为PR区域加载不同的重构模块来实现FPGA内部电路的动态重构。

使用ZYNQ实现单LUT内容的动态修改(一)PL端OOC设计流程相关推荐

  1. android 状态栏一体化 fragment,单Activity多Fragment动态修改状态栏颜色功能

    目录介绍 1.关于如何集成 2.关于如何使用 3.关于鸣谢 4.关于版本更新说明 5.关于其他介绍 0.说明 状态栏工具类,应该可以满足绝大多数的使用场景.具体可以参考代码案例,欢迎star!! 1. ...

  2. Logback中使用TurboFilter实现日志级别等内容的动态修改

    可能看到这个标题,读者会问:要修改日志的级别,不是直接修改log.xxx就好了吗?为何要搞那么复杂呢? 所以,先说一下场景,为什么要通过TurboFilter去动态的修改日志级别.我们在使用Java开 ...

  3. Zynq笔记(一) —PL端(FPGA部分)的设计流程

    文章目录 前言 一.PL部分 1.创建工程 2.添加.V文件 3.编写程序后分析综合(就是普通的verilog程序) 4.编写仿真文件并进行仿真(和上述方法一样,只是在添加文件的时候选择仿真文件即可) ...

  4. Tkinter组件Label动态修改内容

    最近在使用组件Lable时,遇见了text内容不能动态修改,最后发现是自己写错了. 动态修改现在发现有两种方法,一种是修改Lable的text属性的办法,一种是用varibale的双向绑定, 首页是t ...

  5. 怎么改vue项目的标题_Vue动态修改网页标题的方法及遇到问题

    业务需求,进入页面的时候,网页有个默认标题,加载的网页内容不同时,标题需要变更. 例:功能授权,功能授权(张三). Vue下有很多的方式去修改网页标题,这里总结下解决此问题的几种方案: 一.最笨方案 ...

  6. 生成PL设备树及动态加载PL程序和设备树

    实验说明 操作环境: Windows 7/10 64bit Xilinx Vivado 2017.4 Ubuntu 14.04 表 1 开发板型号 是否支持本实验 TLZ7x-EasyEVM 支持 T ...

  7. springBoot下使用quartz定时任务;动态修改任务执行时间

    先上依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spri ...

  8. antd 动态添加表单_ZooTeam 拍了拍你,来看看如何设计动态化表单

    ? 这是第 58篇不掺水的原创,想要了解更多,请戳上方蓝色字体:政采云前端团队关注我们吧- 本文首发于政采云前端团队博客:ZooTeam 拍了拍你,来看看如何设计动态化表单 https://www.z ...

  9. layui追加或动态修改表单元素不生效

    转自:https://blog.csdn.net/qq_29712303/article/details/80030757 在layui的post中请求后台,获取数据,数据获取后修改html页面中内容 ...

  10. 无表单不业务,动态表单让业务系统更高级

    编者按:表单对于业务系统有什么意义?本文分析了业务系统和表单的关系,并比较了普通表单和动态表单和优劣,指出动态表单对业务系统的增益,最后介绍了动态表单的应用实践. 关键词:低代码平台:表单引擎:动态表 ...

最新文章

  1. AIX下删除LV后的现场保护和数据恢复方案
  2. 输出整数的位数、按位输出(两种)以及逆序输出
  3. 如何生成WebPart的部署文件(wsp文件)
  4. 通俗易懂讲解RPC、SpringCloud、Dubbo、Zookeeper、Hadoop、hive等概念的区别
  5. 小米净水器压力传感器_净水器中RO的完整形式是什么?
  6. 从一个简单的“欢迎“页面开始小程序之旅
  7. Oracle经典面试题,你都掌握了吗?
  8. 访问被拒绝:“Interop.jmail”
  9. (第三场) C Shuffle Cards 【STL_rope || splay】
  10. MySQL数据库分区的概念与2大好处(1)
  11. delete postman 传参_Postman高级应用——串行传参和动态传参详解
  12. 软件工程的完整生命周期
  13. 上班可明目张胆摸鱼玩的游戏(这谁能看出是在玩游戏)
  14. 一个字符等于多少磅?
  15. 【Python 打开Raw data】
  16. iOS 将状态栏设置成白色
  17. 计算机上无线网络开关在哪里,笔记本电脑的无线网开关在哪里打开
  18. oracle 推进scn号
  19. 理解特征向量/特征空间和样本空间
  20. 您的计算机无法启动后,在多次尝试后,你的电脑上的操作系统仍无法启动

热门文章

  1. jmeter测试报告分析
  2. calico源码分析-ipam(1)
  3. QQ微云图标升级方法 空间免费扩容攻略
  4. echarts 随时间推移得刻度线_抖音超火❤罗盘时钟(免费附源码)
  5. Java编程思想-并发(5)
  6. uniapp 苹果安全区配置
  7. 掌上英雄联盟服务器维护,掌上英雄联盟更改绑定大区的详细方法
  8. matlab图上面加箭头,利用matlab如何在图形中绘制箭头
  9. 使用Vite搭建基础项目
  10. Android开发:vivo企业开发者账号注册