文档

具有MicroBlaze处理器的IP核心生成工作流程:Xilinx Kintex-7 KC705

此示例显示了如何使用HDL Coder™IP核心生成工作流程为没有嵌入式ARM®处理器的Xilinx®零件开发参考设计,但仍然利用HDL Coder™生成的AXI接口来控制DUT。具体而言,此示例将使用Xilinx Kintex-7 KC705板和MicroBlaze™软处理器在参考设计中运行基于LightwightIP(LWIP)的TCP / IP固件服务器,以从连接的网络上的任何位置访问HDL Coder™生成的DUT寄存器。此外,该示例还将突出显示从实现为多个标量端口的寄存器的集合和实现为单个矢量端口的寄存器集合之间的差异。

要求

  • Xilinx Vivado设计套件,带有支持的版本金宝appHDL编码器文档

  • Xilinx Kintex-7 KC705开发板

  • Xilinx FPGA金宝app板的HDL编码器™支持包

  • 以太网连接

Xilinx Kintex-7 KC705开发板

示例参考设计

MicroBlaze是一种简单的多功能软核处理器,可用于Xilinx FPGA仅平台,例如Kintex-7,以执行全剥离处理器的功能,或作为灵活的可编程IP。当节目很小时,ELF可以坐在BRAM中,并且设计变得完全包含在FPGA中。许多应用程序很适合在微毛上实施。在这里,我们只列出一些:

  1. 远程网络控制部署IP核心算法

  2. 嵌入式web服务器用于控制和数据显示

  3. 将现有软件算法集成到仅硬件平台

以下是该微毛系统的系统级图:

参考设计“Xilinx MicroBlaze TCP / IP到AXI4-Lite Master”,使用Vivado™MicroBlaze IP将TCP / IP数据包转换为AXI4-Lite读取和写入。以下是完整系统的框图,包括通过UART串行控制台操作TCP / IP服务器所需的所有外设。

微毛绒设置

要操作TCP / IP服务器,MicroBlaze IP需要几个基本外设:

  • 用于数据/指令的本地存储器(BRAM)

  • 用于传输和接收帧的以太网核心

  • UART核心用于发送调试消息

  • 用于生成超时中断的计时器核心

  • 用于处理所有这些外围设备的中断的中断控制器。

可以在下面的地址编辑器中看到,所有这些外设通过AXI4接口连接到微孔。

使用BRAM分配的本地内存量为1MB。运行LWIP堆栈需要此金额。为本地存储器指定BRAM的好处是可执行的ELF可以包含在比特流中,这简化了编程,并实现了可能没有外部DRAM内存的现有FPGA板。但是,这种便利性以增加的利用率提出:

如果考虑到BRAM的利用率,并且DRAM资源可用,您可以选择用外部DRAM内存替换本地BRAM内存。关于备用配置和应用程序信息的更多细节,请参见Xilinx应用程序注释“xapp1026”。

示例参考设计插件_rd.m

plugin_rd。本次参考设计的M为:

功能hrd = plugin_rd()%参考设计定义
%Copyright 2014-2018 Mathworks,Inc。
%构造参考设计对象hRD = hdlcoder。ReferenceDesign ('合成池''Xilinx Vivado');
hRD。ReferenceDesignName ='Xilinx MicroBlaze TCP / IP到Axi4-Lite Master';hRD。BoardName ='Xilinx Kintex-7 KC705开发板';
%工具信息hrd.金宝appsupportedtoolversvers = {'2017.2''2017.4'};
%%添加自定义设计文件%添加自定义Vivado设计hRD.addCustomVivadoDesign (......“CustomBlockDesignTcl”'system_top.tcl'......“VivadoBoardPart”“xilinx.com: kc705: part0:1.1”);
%添加自定义文件,使用相对路径hrd.cusomfiles = {“mw_lwip_tcpip_axi4.elf”};
%%添加接口%添加时钟接口hRD.addClockInterface (......“ClockConnection”'clk_wiz_0 / clk_out1'......'resetConnection''proc_sys_reset_0 / peripheral_aresetn'......'defaultfrequencymhz',100,......'minfrequencymhz',100,......'maxfrequencymhz',100,......'clocknumber', 1......'clockmoduleinstance''clk_wiz_0');
%添加AXI4和AXI4-Lite从属接口hRD.addAXI4SlaveInterface (......“InterfaceConnection”'microblaze_0_axi_periph / m04_axi'......'baseaddress''0x44a00000'......'masteraddressspace''microblaze_0 / data'......'interfacetype''axi4-lite'......“InterfaceID”'MicroBlaze Axi4-Lite接口');
hrd.embeddedcoder金宝appsupportpackage = hdlcoder.embeddedcodersupportpackage.none;%没有

请注意,参考设计包括微勃布可执行文件mw_lwip_tcpip_axi4.elf在参考设计属性Customfiles.。这将将可执行文件从参考设计复制到Vivado项目,以便它可以与MicroBlaze IP相关联。

system_top中的附加代码。将ELF附加到uBlaze

包含在大多数引用设计中的“system_top.tcl”文件用于创建包含大多数参考设计IP的顶级Vivado IP Integrator框图。在这里,我们在创建了框图之后向该文件添加一些额外的TCL代码,以将独立的MicroBlaze ELF与MicroBlaze IP相关联。

import_files -norecurse mw_lwip_tcpip_axi4。Elf generate_target all [get_files system_top.]set_property SCOPED_TO_REF system_top [get_files -all -of_objects [get_fileset sources_1] {mw_lwip_tcpip_axi4. txt][get_fileset sources_1] {mw_lwip_tcpip_axi4.elf}] set_property SCOPED_TO_CELLS {microblaze_0}

这样做可以使ELF与位流打包,并与FPGA同时编程到MicroBlaze BRAM内存中。

执行IP核心工作流程

使用上述参考设计,您将产生一个HDL IP核心,闪烁的LEDs在KC705板。然后使用tcpclient.要将格式化的数据包发送到MicroBlaze以发出通过AXI4-Lite接口的读/写入所生成的HDL IP核心。以下演示中使用的文件位于:

  • matlab /工具箱/ hdlcoder / hdlcoderdemos / customboards / KC705

1.使用命令将Mic​​roBlaze参考设计文件添加到MATLAB路径:

>> AddPath(FullFile(Matlabroot,'工具箱''hdlcoder'“hdlcoderdemos”'监视''kc705'));

2.使用以下命令设置Xilinx Vivado™工具路径:

>> HDLSetuptoolPath(“ToolName”'Xilinx Vivado''工具路径'“C: \ Xilinx \ Vivado \ 2017.4 \ bin \ vivado.bat ');

在执行命令时使用自己的Xilinx Vivado™安装路径。

3.打开实现LED闪烁金宝app的Simulink模型,以及矢量输出端口,用于使用命令与标量端口进行比较:

Open_System(“hdlcoder_led_vector”

4.启动HDL工作流顾问从hdlcoder_led_vector / dut.右键单击子系统DUT.子系统,选择HDL码>HDL工作流程顾问

5.从步骤1.2中的下拉菜单中选择参考设计

6.将寄存器端口分配给“MicroBlaze Axi4-Lite接口”。然后将在表格中显示的十六进制偏移量访问这些。

7.运行工作流中的剩余步骤以生成比特流并编程目标设备。

确定IP核心报告的地址

HDL Coder™IP核心的基地地址在参考设计plugin_rd中定义。M用下面的命令:

%添加AXI4和AXI4-Lite从属接口hRD.addAXI4SlaveInterface (......“InterfaceConnection”'microblaze_0_axi_periph / m04_axi'......'baseaddress''0x44a00000'......'masteraddressspace''microblaze_0 / data'......'interfacetype''axi4-lite'......“InterfaceID”'MicroBlaze Axi4-Lite接口');

对于这种设计,基地址是0 x44a0_0000。可以在IP核心报告寄存器地址映射表中找到偏移量:

带频闪灯同步的矢量数据读写

R2017A的Axi4 / A金宝appxi4-Lite接口支持矢量数据。与标量端口的集合不同,向量数据的所有元素都被视为与IP核心算法逻辑同步。为每个向量输入和输出端口添加的附加选通寄存器在多个顺序AXI4读/写入跨越多个顺序AXI4的同步。

对于输入端口,选通寄存器控制启用在一组影子寄存器上,允许IP核心逻辑同时查看所有更新的矢量元素。对于输出端口,选通寄存器控制要读取的矢量数据的同步捕获。以下是使用矢量数据生成的同步逻辑的图:

连接到TCP / IP服务器

要开始与运行在MicroBlaze上的TCP/IP服务器交互,首先连接UART串行控制台以查看调试消息,这将有助于确保工作正常。首先找到单板上连接到UART的串口:

然后使用PuTTY™等程序连接该端口:

一旦连接到UART串行控制台,运行hdlworkflow_programtargetdevice.m.脚本重新编程的板。

>>hdlworkflow_ProgramTargetDevice ###工作流开始。###从模型加载设置### ++++++++++++++任务程序目标设备++++++++++++++ ###生成日志文件:hdl_prj\hdlsrc\hdlcoder_led_vector\workflow_task_ProgramTargetDevice.log ###任务“程序目标设备”成功。# # #工作流程完成。

在控制台窗口中,您应该看到以下标头,显示服务器连接到的IP地址和端口号。

注意:如果电路板已启用DHCP服务器连接到网络,则IP信息将与上图不同。在这种情况下,您需要修改第43行read_write_test.m.脚本连接到正确的单板IP地址:

t = tcpclient ('192.168.1.10',7);

使用Matlab使用AX4-Lite交易发送到Matlab的MicroBlazetcpipclient

为了通过TCP / IP和AXI4-Lite发出读取和写入IP核心,必须在发送到TCP / IP服务器的数据包中编码要执行的地址,数据和命令。对于此示例,我们使用以下数据包格式:

[——Address——]32位[----Cmd----] 32位字的小字节(READ = 0, WRITE = 1, DEBUG = 2)[——Length——]32位工作的小字节(N<255) [----Data——]32位,仅用于WRITE Cmd

例如,在地址0x44a0010c开始发出3个连续值的数据包:

[44 a0 01 0c] [00 00 00] [00 00 03]

这将在偏移0x10c,0x110,0x114处返回数据。

例如,向偏移0x04的写入0x0写入的数据包将是:

[44 a0 00 04] [00 00 01] [00 00 00 01] [00 00 00]

要更改用于打印到控制台的调试级别,请发送调试CMD数据包:

[xx xx xx xx] [00 00 00 03] [00 00 00 01]%0 = no msg,1 =写入,2 =完整pkt

运行read_write_test.m脚本

此示例包括一个脚本,该脚本将设置与在MicroBlaze上运行的TCP / IP服务器的连接,创建命令以启用/禁用DUT,读取6个标量端口和与向量端口相同的数据并比较结果。

1.要运行此脚本,请先将其复制到本地目录

>> COPYFILE(FullFile(MatlaBroot,'工具箱''hdlcoder'“hdlcoderdemos”“ublaze_lwip_read_write_vector_test.m”),'Ublaze_test.m');

并在编辑器中打开脚本:

>>编辑('UBLAZE_TEST.M');

该脚本有三个部分。第一部分连接到板并设置将使用的命令。如果需要,请更新第41行单板的IP地址。

2.执行第一节。将以下命令生成为uint32类型的数组:

read6_cmd = uint32([hex2dec('44A0010C')0 6]);%读6个32位regsread_vec_cmd = uint32 ([hex2dec ('44A00140')0 6]);%读取vec的6个元素strobe_vec_cmd = uint32 ([hex2dec (“44 a00160”)1 1 1]);%写频闪的VEC启用_cmd = uint32([hex2dec('44A00004')1 1 1]);%启用IP核心disable_cmd = uint32([hex2dec('44A00004')1 1 0]);%禁用ip核心debug0_cmd = uint32([hex2dec('00000000')3 0]);%禁用所有调试打印机debug1_cmd = uint32([hex2dec('00000000') 3 1]);%启用阅读|写printfsdebug2_cmd = uint32([hex2dec('00000000')3 2]);%启用pkt printfs

注意:这些数组以本地计算机使用的endian格式存储数据,这对于许多x86系统来说是小的endian格式。但是,TCP / IP服务器期望Big Endian格式(网络字节顺序)的值。结果,如果您所在的系统是小endian,则必须将每个元素中的字节交换使用swapbytes

3.执行第2节禁用DUT逻辑,并读取连接到6个标量端口的单个计数器值以及矢量端口中的所有6个元素。请注意,所有计数器值都匹配。这是因为禁用了所有端口和DUT所驱动相同的数据,因此AXI4接口的异步访问不明显。

标量端口(上)和矢量端口(底部)访问DUT禁用:7 e8aec14 7 e8aec14 7 e8aec14 7 e8aec14 7 e8aec14 7 e8aec14
7E8AEC14 7E8AEC14 7E8AEC14 7E8AEC14 7E8AEC14 7E8AEC14

4.执行第3节重新启用DUT逻辑并读取相同的计数器值。请注意,6个标量端口都显示出不同的值,而向量端口的6个元素都是相同的。这是由于在AXI4接口中必须发生的顺序访问以及标量港口外壳中的缺少同步寄存器以及在矢量端口外壳中存在显式同步寄存器。

标量港口(顶部)VS矢量端口(底部)启用DUT访问:7F7796DC 7FC70E4B 8016860A 8065FDCE 80B5758D 8104ED4D
815964DD 815964DD 815964DD 815964DD 815964DD 815964DD 815964DD

串行控制台上的相应调试输出将是:

概括

该演示突出显示在FPGA设计中使用MicroBlaze软核处理器。微勃朗非常适合用作全方形的处理器或作为固件应用程序的灵活IP运行传统C代码。该演示还显示了在AXI4接口上的数据同步的标量端口和矢量端口之间的集合之间的差异。

附录A:创建和编辑Xilinx SDK应用程序

本节将显示如何创建新的Xilinx SDK项目并从此示例中包含代码,然后修改或扩展。

1.点击HDL Workflow Advisor步骤4.1“Create project”中的链接,打开Xilinx Vivado项目:

2.将现有设计(包括生成的位流)导出到本地文件夹。一旦这完成了,继续和“启动SDK”。

3.在SDK中创建一个新的应用程序项目

然后,您可以选择命名项目并创建新BSP

接下来,您可以从一些预先配置的示例/模板项目中进行选择来开始。此示例是“LWIP Echo Server”项目的构建,因此现在选择。

5.使用Echo Server作为模板,可以使用下面的代码段替换以下3个方法来修改服务器的行为

附录B:复制C文件内容到项目

#define ipcorebase 0x44a00000 #define write 0x01 #define读取0x00 #define debug 0x03 int transfer_data(){return 0;} void print_app_header(){xil_printf(“\ n \ r \ n \ r ----- mathworks hdl编码器AXI4-Lite IP核读/写服务器------ \ n \ r”);Xil_printf(“发送到端口7的TCP数据包将被发出为AXI4-Lite读/写\ n \ r”);xil_printf(“\ n \ r”);xil_printf(“[32位地址](基地址= 0x44a0_0000)\ n \ r”);xil_printf(“[32位cmd](read = 0x00,write = 0x01,debug = 0x03)\ n \ r”);xil_printf(“[32位len](n <255)\ n \ r”);xil_printf(“[32位数据](写cmd的n 32位数据值)\ n \ r”);xil_printf(“-------------------------------------------------------- ------ \ n \ r“);void print_packet(struct pbuf * p){U16 II; u8 *pktPtr; pktPtr = p->payload; xil_printf("DEBUG | packet payload:\r\n"); for (ii=0;iilen;ii+=4) { xil_printf("%02x %02x %02x %02x\r\n",*(pktPtr+ii),*(pktPtr+ii+1),*(pktPtr+ii+2),*(pktPtr+ii+3)); } } err_t recv_callback(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err) { u8 *pktPtr,*pktEnd; volatile u32 *addr; u32 data[255],cmd; u16 len; int ii; static u8 debug = 3; /* do not read the packet if we are not in ESTABLISHED state */ if (!p) { tcp_close(tpcb); tcp_recv(tpcb, NULL); return ERR_OK; } /* indicate that the packet has been received */ tcp_recved(tpcb, p->len); if (debug > 1) print_packet(p); //[ 32 bits address ] //[ 32 bits read = 0x00, write =0x01] //[ 32 bits length ] //[ 32 bits write data] pktPtr = p->payload; pktEnd = pktPtr+p->len; /* could be multiple commands per packet */ while ( pktPtr < pktEnd) { addr = (u32*) (pktPtr[0]<<24 | pktPtr[1]<<16 | pktPtr[2]<<8 | pktPtr[3]); cmd = (u32) pktPtr[7]; // cmd is 32 bits, but only 1st byte used, ignore rest pktPtr += 8; switch(cmd) { case WRITE : len = (u32) pktPtr[3]; // len is 32 bits, but only 1st byte used, ignore rest pktPtr += 4; for (ii=0;ii 0) xil_printf("WRITE | address: 0x%08x, data[0]: 0x%08x\r\n",addr,data[0]); addr++; pktPtr += 4; } break; case READ : len = (u32) pktPtr[3]; // len is 32 bits, but only 1st byte used, ignore rest pktPtr += 4; for (ii=0;ii 0) xil_printf("READ | address: 0x%08x, data[%d]: 0x%08x\r\n",addr,ii,data[ii]); addr++; } /* send the packet back */ if (tcp_sndbuf(tpcb) > p->len) err = tcp_write(tpcb, data, 4*len, 1); else xil_printf("no space in tcp_sndbuf\n\r"); break; case DEBUG: debug = pktPtr[3]; // only need the low byte pktPtr += 4; xil_printf("Debug level set to : 0x%02x\r\n",debug); break; default : xil_printf("INVALID | cmd: 0x%08x\r\n",cmd); } } /* free the received pbuf */ pbuf_free(p); return ERR_OK; }

6.保存修改后的echo.c文件,将重建应用程序。

附录C:使用ELF和比特流程为FPGA进行编程

现在,您可以使用导出的比特流和新创建的ELF文件编程FPGA。