-09-EMIO Slice 自定义IP设计【Xilinx-Petalinux学习】
2017-03-14 18:37
423 查看
前一阵与一个朋友一起测试了petalinux中的GPIO驱动先关的代码。
一开始使用的AXI_GPIO这个IP核,输出的驱动还好,但是输入要加入中断等功能,就有点麻烦,而且配置来配置去的总是出问题,所以以后再来试这个吧。
因此决定以后再petalinux中使用GPIO功能时,都直接使用PS内的MIO和EMIO来实现。这样两者的驱动程序不仅相同,EMIO还能够自定义管脚位置,并且还不需要AXI_GPIO这个IP核需要消耗掉的逻辑资源。最重要的是,没有写驱动程序,而是直接使用了内核中的gpio-keys, leds-gpio驱动实现了我需要的功能 。
GPIO_0及是PS的EMIO输入输出管脚,这里面可能包含了按键、LED等不同功能的GPIO,但我们没有办法,必须在约束文件中对他们进行区分,可视性不太好。所以想着做一个IP,实现EMIO各个位的引脚对应不同功能的区分。最终的IP GUI如下图:
下面来进行设计。
针对ZedBoard开发板来看,它有5个btn,8个sw,8个led,所以我们在命令行运行python脚本,并附加“5 8 8”的参数:
这样在子目录src文件夹下就能得到后面需要使用到的两个verilog源文件:
接下来就是一系列的生成自定义IP的操作。
创建和打包IP:
打包当前工程:
指定IP的生成目录:
接着就会弹出一个窗口,进行详细的IP配置。
设置IP名称、版本号等信息:
兼容所有Zynq平台:
<
bd17
strong>不知道为何vivado识别不到我在verilog里面的宏描述,导致必须手动配置接口总线,以后再来研究[/b]
进入Ports and Interfaces界面,如下图,我们需要把每组的GPIO信号进行分组。
点击上图的+号按钮,弹出下面的窗口。把Interface选择为gpio,然后手动指定管脚对应的_i,_o,_t。需要注意Din是gpio的从接口,所以mode需要选择mirroredMaster,而Out*则选择Master就好。同时也可根据信号的不同进行命名,我这里将Din定义为PS_EMIO,Out0定义为BTN,Out1定义为SW,Out2定义为LED。
全部配置完后如下图:
检查GUI是否正确:
点击Package IP生成IP:
这样,EMIO Slice IP就设计完成了,在指定的目录下将生成若干IP相关的文件:
然后在PS中配置EMIO的位宽,这里为:5+8+8=21
添加我们的min_sys_emio_slice自定义IP并连接到PS,最终效果如下图所示。
现在的问题就是在verilog源码中下面的定义,不知为什么vivado工具识别不了,必须要我手动去定义gpio bus,略显麻烦。
下一次,生成新的hdf和bit文件,并编译出petalinux,试一试这个IP使用起来是否正确。
一开始使用的AXI_GPIO这个IP核,输出的驱动还好,但是输入要加入中断等功能,就有点麻烦,而且配置来配置去的总是出问题,所以以后再来试这个吧。
因此决定以后再petalinux中使用GPIO功能时,都直接使用PS内的MIO和EMIO来实现。这样两者的驱动程序不仅相同,EMIO还能够自定义管脚位置,并且还不需要AXI_GPIO这个IP核需要消耗掉的逻辑资源。最重要的是,没有写驱动程序,而是直接使用了内核中的gpio-keys, leds-gpio驱动实现了我需要的功能 。
EMIO Slice设计
在block design中,一开始做的时候,引脚连接如下图:GPIO_0及是PS的EMIO输入输出管脚,这里面可能包含了按键、LED等不同功能的GPIO,但我们没有办法,必须在约束文件中对他们进行区分,可视性不太好。所以想着做一个IP,实现EMIO各个位的引脚对应不同功能的区分。最终的IP GUI如下图:
下面来进行设计。
S1. verilog源码生成
我用Python脚本做了一个脚本,可以根据需要对EMIO的分支个数、每个分支的位宽进行配置,可以用来生成verilog源代码文件。脚本如下:#! usr/bin/python #coding=utf-8 import time import os import sys out_width_max = 64 out_width_unuse = 0 out_width = 0 out_arg = "" src_dir = "src" def min_system_emio_slice_verilog_generate(): File = open("./" + src_dir + "/min_system_emio_slice.v", "w") # File.write("// Company:\n") File.write("// Engineer: vacajk\n") File.write("// \n") File.write("// Create Tool: emio slice python script\n") File.write("// Create Date: " + time.strftime('%Y/%m/%d %H:%M:%S',time.localtime(time.time())) + "\n") File.write("// Design Name: \n") File.write("// Module Name: emin_system_mio_slice\n") File.write("// Tool Versions: vivado 2015.4\n") File.write("\n") # File.write("`timescale 1ns / 1ps\n") File.write("\n") # File.write("module min_system_emio_slice (\n\t") File.write("Din_i, Din_o, Din_t,\n\t") for Index in range(len(out_arg)): string_out = "Out" + str(Index) File.write(string_out + "_i," + string_out + "_o," + string_out + "_t") if Index < (len(out_arg) - 1): File.write(",\n\t") else: File.write("\n\t") File.write(");\n") File.write("\n") # File.write("(* X_INTERFACE_INFO = \"xilinx.com:interface:gpio:1.0 Din TRI_I\" *)\n") File.write("output wire [" + str(out_width-1) +":0] Din_i;\n") File.write("(* X_INTERFACE_INFO = \"xilinx.com:interface:gpio:1.0 Din TRI_O\" *)\n") File.write("input wire [" + str(out_width-1) +":0] Din_o;\n") File.write("(* X_INTERFACE_INFO = \"xilinx.com:interface:gpio:1.0 Din TRI_T\" *)\n") File.write("input wire [" + str(out_width-1) +":0] Din_t;\n") # out_base = 0 for Index in range(len(out_arg)): string_out = "Out" + str(Index) string_out_base_low = str(out_base) string_out_base_high = str(out_base + out_arg[Index] - 1) File.write("(* X_INTERFACE_INFO = \"xilinx.com:interface:gpio:1.0 " + string_out + " TRI_I\" *)\n") File.write("input wire [" + string_out_base_high + ":" + string_out_base_low + "] " + string_out + "_i;\n") File.write("(* X_INTERFACE_INFO = \"xilinx.com:interface:gpio:1.0 " + string_out + " TRI_O\" *)\n") File.write("output wire [" + string_out_base_high + ":" + string_out_base_low + "] " + string_out + "_o;\n") File.write("(* X_INTERFACE_INFO = \"xilinx.com:interface:gpio:1.0 " + string_out + " TRI_T\" *)\n") File.write("output wire [" + string_out_base_high + ":" + string_out_base_low + "] " + string_out + "_t;\n") F 4000 ile.write("\n") # File.write("emio_slice #(\n\t") File.write(".NUM_PORTS(" + str(len(out_arg)) +"),\n\t") File.write(".DIN_WIDTH(" + str(out_width) +"),\n\t") for Index in range(out_width_max): if Index < len(out_arg): File.write(".OUT" + str(Index) + "_WIDTH(" + str(out_arg[Index]) + ")") else: File.write(".OUT" + str(Index) + "_WIDTH(1)") if Index < (out_width_max - 1): File.write(",\n\t") else: File.write("\n\t") # File.write(") emio_slice_inst (\n\t") File.write(".Din_i(Din_i), .Din_o(Din_o), .Din_t(Din_t),\n\t") for Index in range(out_width_max): str_i = "Out" + str(Index) + "_i" str_o = "Out" + str(Index) + "_o" str_t = "Out" + str(Index) + "_t" if Index < len(out_arg): File.write("." + str_i + "(" + str_i + "), ") File.write("." + str_o + "(" + str_o + "), ") File.write("." + str_t + "(" + str_t + ")") else: File.write("." + str_i + "(1'b0), ") File.write("." + str_o + "(), ") File.write("." + str_t + "()") if Index < (out_width_max - 1): File.write(",") if Index < len(out_arg): File.write("\n\t") else: File.write(" ") if ((Index - len(out_arg)) % 4) == 3: File.write("\n\t" ) else: File.write("\n\t" ) File.write(");\n") File.write("\n") File.write("endmodule\n") File.write("\n") def emio_slice_verilog_generate(max_num_ports = 64): File = open("./" + src_dir + "/emio_slice.v", "w") # File.write("// Company:\n") File.write("// Engineer: vacajk\n") File.write("// \n") File.write("// Create Tool: emio slice python script\n") File.write("// Create Date: " + time.strftime('%Y/%m/%d %H:%M:%S',time.localtime(time.time())) + "\n") File.write("// Design Name: \n") File.write("// Module Name: emio_slice\n") File.write("// Tool Versions: vivado 2015.4\n") File.write("\n") # File.write("`timescale 1ns / 1ps\n") File.write("\n") # File.write("module emio_slice (\n\t") File.write("Din_i, Din_o, Din_t,\n\t") for Index in range(max_num_ports): File.write("Out" + str(Index) + "_i, ") File.write("Out" + str(Index) + "_o, ") if Index < (max_num_ports - 1): File.write("Out" + str(Index) + "_t, ") if (Index % 4) == 3: File.write("\n\t" ) else: File.write("Out" + str(Index) + "_t") File.write("\n\t" ) File.write(");\n") File.write("\n") # File.write("parameter NUM_PORTS = 2;\n") File.write("parameter DIN_WIDTH = 2;\n") File.write("output [DIN_WIDTH-1:0] Din_i;\n") File.write("input [DIN_WIDTH-1:0] Din_o, Din_t;\n") File.write("\n") # for Index in range(max_num_ports): File.write("parameter OUT" + str(Index) + "_WIDTH = 1;\n") File.write("\n") # for Index in range(max_num_ports): if (Index % 10) == 0: File.write("//" + str(Index) + "~" + str(Index+9) + "\n") File.write("input [OUT" + str(Index) + "_WIDTH-1:0] Out" + str(Index) + "_i;\n") File.write("output [OUT" + str(Index) + "_WIDTH-1:0] Out" + str(Index) + "_o, Out" + str(Index) + "_t;\n") File.write("\n" ) # string_line0 = "" string_line1 = "" string_line2 = "" pre_string_line0 = "" pre_string_line1 = "" pre_string_line2 = "" for Index in range(max_num_ports): if (Index % 10) == 0: File.write("//" + str(Index) + "~" + str(Index+9) + "\n") string_line0 = "Out" + str(Index) + "_i" + pre_string_line0 string_line1 = "Out" + str(Index) + "_o" + pre_string_line1 string_line2 = "Out" + str(Index) + "_t" + pre_string_line2 pre_string_line0 = ", " + string_line0 pre_string_line1 = ", " + string_line1 pre_string_line2 = ", " + string_line2 File.write("generate if (NUM_PORTS == " + str(Index+1) + ")\n") File.write("begin : S_NUM_" + str(Index+1) + "\n") File.write("\tassign Din_i = {" + string_line0 + "};\n") File.write("\tassign {" + string_line1 + "} = Din_o;\n") File.write("\tassign {" + string_line2 + "} = Din_t;\n") File.write("end\n") File.write("endgenerate\n") File.write("\n" ) File.write("endmodule\n") File.write("\n") File.close() def make_src_dir(dir_name = "src"): src_dir = dir_name if(os.path.isdir(dir_name) == False): os.mkdir(dir_name) if __name__ == "__main__": out_arg = sys.argv del out_arg[0] out_arg = map(int, out_arg) out_width = sum(out_arg) out_width_unuse = out_width_max - out_width make_src_dir() emio_slice_verilog_generate() min_system_emio_slice_verilog_generate() print "emio_slice verilog sources generated done!!!"
针对ZedBoard开发板来看,它有5个btn,8个sw,8个led,所以我们在命令行运行python脚本,并附加“5 8 8”的参数:
这样在子目录src文件夹下就能得到后面需要使用到的两个verilog源文件:
S2. 自定义IP生成
首先,以ZedBoard为平台新建vivado工程,这里就不描述了,然后导入刚才生成的两个源文件emio_slice.v和min_system_emio_slice.v,可以进行综合验证其是否有错误。接下来就是一系列的生成自定义IP的操作。
创建和打包IP:
打包当前工程:
指定IP的生成目录:
接着就会弹出一个窗口,进行详细的IP配置。
设置IP名称、版本号等信息:
兼容所有Zynq平台:
<
bd17
strong>不知道为何vivado识别不到我在verilog里面的宏描述,导致必须手动配置接口总线,以后再来研究[/b]
进入Ports and Interfaces界面,如下图,我们需要把每组的GPIO信号进行分组。
点击上图的+号按钮,弹出下面的窗口。把Interface选择为gpio,然后手动指定管脚对应的_i,_o,_t。需要注意Din是gpio的从接口,所以mode需要选择mirroredMaster,而Out*则选择Master就好。同时也可根据信号的不同进行命名,我这里将Din定义为PS_EMIO,Out0定义为BTN,Out1定义为SW,Out2定义为LED。
全部配置完后如下图:
检查GUI是否正确:
点击Package IP生成IP:
这样,EMIO Slice IP就设计完成了,在指定的目录下将生成若干IP相关的文件:
S3. 在block design中加入EMIO Slice IP
首先在建立好的zynq工程中加入上面IP所在的目录。然后在PS中配置EMIO的位宽,这里为:5+8+8=21
添加我们的min_sys_emio_slice自定义IP并连接到PS,最终效果如下图所示。
总结
虽然说这样子弄了半天才仅仅是把EMIO的信号更加形象的在block design中表现出来,有用没用我谈不上,但对于我这种使用GUI进行连线并伴有严重强迫症的人来说还是有点用的。现在的问题就是在verilog源码中下面的定义,不知为什么vivado工具识别不了,必须要我手动去定义gpio bus,略显麻烦。
(* X_INTERFACE_INFO = "xilinx.com:interface:gpio:1.0 Din TRI_I" *) output wire [20:0] Din_i; (* X_INTERFACE_INFO = "xilinx.com:interface:gpio:1.0 Din TRI_O" *) input wire [20:0] Din_o; (* X_INTERFACE_INFO = "xilinx.com:interface:gpio:1.0 Din TRI_T" *) input wire [20:0] Din_t;
下一次,生成新的hdf和bit文件,并编译出petalinux,试一试这个IP使用起来是否正确。
相关文章推荐
- petalinux&zedboard(自定义IP学习笔记)
- 【Xilinx-Petalinux学习】-02-建立PetaLinux工程
- 【Xilinx-Petalinux学习】-07-OpenCV的软硬件处理速度对比
- -07-OpenCV的软硬件处理速度对比【Xilinx-Petalinux学习】
- 【Xilinx-Petalinux学习】-03-PetaLinux通过eMMC方式启动
- zynq的自定义IP的驱动(带中断)怎么写?(petalinux实现方式)
- -10-GPIO驱动程序【Xilinx-Petalinux学习】
- 【Xilinx-Petalinux学习】-05-OpenCV程序测试
- -04-OpenCV的移植【Xilinx-Petalinux学习】
- -00-开始【Xilinx-Petalinux学习】
- 请问哪位大神能详细说说:zynq自定义IP,用petalinux生成镜像的步骤?
- 【Xilinx-Petalinux学习】-00-开始
- 【Xilinx-Petalinux学习】-06-OpenCV通过USB摄像头采集图像。
- -02-建立PetaLinux工程【Xilinx-Petalinux学习】
- 【Xilinx-Petalinux学习】-01-开发环境搭建与PetaLinux的安装
- -05-OpenCV程序测试【Xilinx-Petalinux学习】
- 本地sstate-cache配置【Xilinx-Petalinux学习】
- -06-OpenCV通过USB摄像头采集图像【Xilinx-Petalinux学习】
- ZYNQ中的UIO驱动和中断程序学习【Xilinx-Petalinux学习】
- -03-PetaLinux通过eMMC方式启动【Xilinx-Petalinux学习】