xzy610030

一起探讨,一起进步,一起分享!

zedboard--用户自定义IP核(pwm发生器)设计(二十)

0
阅读(6996)

1:实验说明:

对于Zedboard的用户自定义的IP核有两种可行的方案:

一:通过EMIO交换数据(GPIO,SPI),这个其实就是将PL的IP核看作系统的外设,在数据交互性能和效率上都有很大的缺陷。(不常用)

二:利用向导来制作满足AXI协议的IP核,向导自动生成总线相关的代码,做好地址译码逻辑,读写控制逻辑,并在用户工作区生成一些寄存器。我们写的PL逻辑通过读写这些寄存器和PS交互。这也是常用的方法。

Zedboard也有一些自己做好了的IP core,实验八就是用的自带的IP core。

本实验就是采用第二种方法,制作一个简单的PWM发生器。在PL端开发了这个IP核以后,先在裸跑的程序里面调用这个IP core,测试我们的逻辑有没有实现,这个和之前做的实验没有什么区别(zedboard--zynq使用自带外设IP让ARM PS访问FPGA(八),只不过这里是我们自己写的IP core)

PWM发生器内部只有两个寄存器,一个是调节周期的周期寄存器,另一个是调节占空比的占空比寄存器,其中周期寄存器的最高位是状态位,控制PWM波最后是否产生。


2:具体步骤

启动PlanAhead,创建工程,Next,图1

输入工程名project_10,Next,图2

Next,RTL工程 图3

一路Next,不添加任何文件 图4

选择board 图5

完成工程 图6

PlanAhead进入工作视图,在Project Manager中单击那个有+的图标(addsources),出现下图,选择Embedded Sources 图7,图8


Next 选着Create Sub-Design。 图9

输入名称,这里为system 图10

点击finish 图11

进入了XPS,提示所建立的一个zynq工程,提示是否建立bsb Wizard,选择yes 图12

出现下图 图13

点击ok 出现 图14

选择next 这里不要大意,一定要把右侧的两个东西来remove掉,我当时就是卡在这里。,remove后出现这样的图 图15

Finish,点击finish就可以了,然后进入zynq的配置界面,Diligent公司做好了一个配置方案,可以到网上下载到配置文件。

如图16 17 18



Hardware- Createor Import Periphera 来到欢迎界面 图19

Next,创建新的模板(默认选择) 图20

Next 默认 图21

Next命名工程 图22

采用AXI4-Lite 图23

Next,这里只要 User logic master support 图24

Next,我们要两个寄存器,分别是占空比寄存器和周期寄存器,图25

Next,不做任何修改 图26

Next,不需要仿真平台 图27

Next, 全选图28

第一个选项表示生成的User Logic使用VerilogHDL

第二个选项表示同时生成一个ISE的工程,便于调试和测试Ipcore

第三个选项表示生成软件驱动库文件,方便在SDK里使用Ipcore

Next,点击finish就可以了 图29

我们自己配置的IP核就建立好了,接下来添加刚完成的IP核,在IP Catalog里面的USER选项中找到它 图30

双击PWM_IP,出现 图31

选择YES, 图32

点击两次ok,出现 图33

注意一下不要粘贴外面的(如word文档里面的),容易出错,输入法选择在英文输入法下。

右击pwm_ip_0,View MPD,添加PORT pwm_out=””,DIR=O,如图34(添加在60行),保存并关闭

右击pwm_ip_0,Brouse HDLsources,打开pwm_ip.vhd.添加代码

1添加(138行) 将pwm_out接口设置为模块的输出接口

pwm_out :out std_logic; 图35


2添加(253行)将pwm_out接口到user_logic设备

pwm_out :out std_logic; 图36


3添加(342)将设备的pwm_out接口和IP核的pwm_out接口连接

pwm_out =>pwm_out, 图37

保存,退出,右击pwm_ip_0,Brouse HDLsources,打开user_logic.v.添加代码

1添加(58行),声明pwm_out接口,添加pwm_out, 图38


2添加(88行)定义pwm_out为输出,而且位宽为1,添加

output pwm_out; 图39


3接下来就是用户实现段了,令slv_reg0为周期寄存器,slv_reg1为占空比寄存器。此外我们还需要一个计数器(pwm_counter),下一个周期的开始信号(Over Period)和预输出信号(pre_pwm_out)。

在110添加逻辑

wire ovprd;

reg [C_SLV_DWIDTH-1 :0] pwm_counter;

wire pre_pwm_out;

图40


pwm产生器的逻辑

在124行添加逻辑 图41

// USER logic implementation added here

always @(posedgeBus2IP_Clk)

begin

if(!Bus2IP_Resetn || ovprd ||~slv_reg1[31])

pwm_counter=32'h8000_0000;

else if(slv_reg1[31])

pwm_counter=pwm_counter+1'b1;

else pwm_counter=pwm_counter;

end

assignovprd=(pwm_counter[30:0]==slv_reg0[30:0])?1'b1:1'b0;

assignpre_pwm_out=(slv_reg1

assignpwm_out=pre_pwm_out & slv_reg1[31];

保存,退出,在project菜单中选择RescanUser Repositories,从port中可以看到我们新添加的引脚pwm_out.选择External Ports把引脚引出去,如图42

打开Address标签页,单击右上角的GeneratedAddresses按钮,如图43

单击project –>Design Rule Check,没有报错,关闭xps,回到PlanAhead图44


在system.xmp文件上右击,选择CreateTop HDL 图45,46


单击Add source按钮,选择Add orCreate Constrains 单击Next 图47

单击 Create File…选项 图48

改文件名 图49,finish就可以了

单击左边的Run Synthesis ,这里就出错了,如图50,

在tcl console 按下ctrl +f 输入error,如图51一看是user_logic.v出错了, is not d eclared这个时候启动xps,改正错误,可以看到图41,确实是错的,应该在128和134行为slv_reg1,而我漏掉了1,改正,保存,退出xps,重新Run Synthesis,这里也是寻找解决错误的方法。


过程结束后会弹出对话框,图52

选择Open Synthesized Design,会有一些警告,忽略,打开I/O Port标签,由于以前一直用Altera,这个标签找了一会儿(window->I/O Port),设置pwm_out的引脚,保存。图53

选择Select an existing file

看不到system.ucf,重启PlanAhead,这时候就可以看到system.ucf文件的内容如下 图54

单击左边的Generate Bitstream.单击yes,完成implementation,至此硬件工程就做完了。(这个过程又点长)

在PlanAhead中,单击File->Export->ExportHardware 图55

建立c工程 图56

选择Xilinx Tools->Repositories,单击new,找到工程路径,图57


在hello_bsp_0上右击,选择BoardSupport Package Setting ,找到drivers中得pwm_ip_0,修改Driver,图58,如果你没有出现估计就悲剧了。

然后我们将自设的IP核的Driver添加进来后就可以添加c代码了。图59

修改bug在hello_bsp_0上面有一个红色的叉,是有一个宏没有设置,需要手动设置这个宏,找到pwm_ip_selftest,c这个文件,C:\zedboard\project_11\project_11.srcs\sources_1\edk\system/drivers/pwm_ip_v1_00_a/src/pwm_ip_selftest.c(我的目录在这里)

注释 #include "xio.h"

添加#definePWM_IP_USER_NUM_REG 2 图60


保存,等待工程编译结束。

出现图61的错误,解决办法。重新建立一个c工程。然后和上面的是一样的,至于原因就不知道了。


测试

选择Xilinx Tools->Program FPGA

在hello_world_0工程上右击,选择RunAs->Launch on Hardware,用示波器看波形结果是正确的,修改helloworld.c 中的占空比可以看到不同的波形。


易出错的地方:

第一个:在添加vhdl和verilog代码的时候以及找错误的方法。

第二个是出现类似于以下的错误:"Building target: hello_world_0.elf Invoking: ARM gcc linker arm-xilinx-eabi-gcc -Wl,-T -Wl,../src/lscript.ld -L../../standalone_bsp_0/ps7_cortexa9_0/lib -o"hello_world_0.elf" ./src/helloworld.o ./src/platform.o -l-Wl,--start-group,-lxil,-lgcc,-lc,--end-group ../lib/gcc/arm-xilinx-eabi/4.6.1/../../../../arm-xilinx-eabi/bin/ld.exe: cannot find -l-Wl,--start-group,-lxil,-lgcc,-lc,--end-group collect2: ld returned 1 exit status make: *** [hello_world_0.elf] Error 1"解决方法就是重新新建一个c工程,(冲PlanAhead重新导入一次),原因不祥。

以上都在上面有提到过。这次是用裸跑的程序来调用IPcore,下次实验是要为这个IPcore开发Linux系统上的设备驱动,使得运行在Linux上的应用程序可以使用这个驱动程序与PL端进行通信,从而控制PWM的输出。

Baidu
map