【NiosII学习】第七篇、自定义PWM的IP核

目录

第一部分、关于PWM的IP核的储备知识

1、什么是IP核

2、为什么要自己写IP核

3、PWM_IP核的写法

第二部分、新建Quartus II工程

1、注意

第三部分、添加自己的IP核

1、添加自己IP核的详细步骤

第四部分、修改别人的软核

1、调用自己的IP核详细步骤

第五部分、编写Quartus中的verilog代码

1、代码

2、注意

第六部分、编写ecplise里面的C代码

1、代码的功能阐述

2、代码

第七部分、总结

1、效果展示

2、感想

3、完整资料


第一部分、关于PWM的IP核的储备知识

1、什么是IP核

IP核(Intellectual Property core),就是知识产权核或知识产权模块的意思。同时IP又分为软IP固IP硬IP。我们这里面主要做的软IP,软IP是用Verilog/VHDL等硬件描述语言描述的功能块,但是并不涉及用什么具体电路元件实现这些功能。

2、为什么要自己写IP核

我猜铁子们的Quartus II都是破解版,破解版它已经破解了很多Altera的IP核(这就是为什么正版软件这么贵),但是这些IP核有时候不能满足我们的设计需求,比如我想驱动LCD屏,那我就得自己写一个LCD的IP核。

所以学会自己写IP核就特别重要,但是这个需要你学到一定的高度之后你才具备这个本领,博主现在也还是个辣鸡,你让我写,我也不会。但是这里我想教的是,别人把IP核写好了,你怎么把他导入到你的系统中去。

3、PWM_IP核的写法

PWM_IP核是别人用verilog语言写的,这个需要一定的水平,反正我还不会,我这里的“pwmip2020.v”文件是我嫖来的🐶🐶🐶。如图为PWM_IP核的部分verilog代码的截图

第二部分、新建Quartus II工程

1、注意

这里我还是复制小梅哥的LCD9341的初始工程到自己建立的文件夹中去,上一篇【NiosII学习】第六篇、从零搭建属于自己的SOPC系统已经教你们如何搭建自己的SOPC系统了,但是我怕有些读者没成功,所以这一我还是到别人工程上面改,这里不会的去看【NiosII学习】第一篇、如何烧录NiosII工程:https://blog.csdn.net/Learning1232/article/details/110225728

如果你和我FPGA型号不一样,那就复制你的SOPC工程文件到文件夹中,和前面一样,因为其他的步骤大致都和我的一样,没有区别。

第一步、复制小梅哥的LCD9341的初始工程,到自己建立的文件夹中,然后打开工程

第三部分、添加自己的IP核

1、添加自己IP核的详细步骤

第一步、打开Platform Designer,打开添加IP核的对话框

第二步、定义你IP核的名称,翻译这些英文,你就知道填啥了

第三步、添加pwmip2020.v文件(注意:这个文件要放到你的工程文件夹中的IP文件中,在这个文件夹中新建一个PWM文件夹,然后将“pwmip2020.v”文件放进去,如图我放的位置),然后再分析这个文件,步骤如图。

 第四步、分析过后会报这些错误和警告,但是不要慌。点击close,关闭弹窗,点击NEXT

第五步、点击NEXT,第四个参数配置窗口不用管。再点击NEXT,打开第五个参数配置窗口

第六步、将第五个参数配置窗口拉到最,鼠标左键单击CPU_Addr [2] 如图,并将Signal Type:选为adress。其他参数默认。

第七步、同理鼠标左键单击CPU_CS如图,并将Signal Type:选为chipselect(片选信号,chipselect表示高电平有效,chipselect_n表示低电平有效)

注意:这里为什么选高电平有效,这和你的“pwmip2020.v”这个文件的写法有关。如果你想搞的很清楚可以私聊我,如果人多我就出一期教程讲解,主要是说起来太麻烦,教程字太多,我自己都懒得看。

 第八步、剩下的几个同理,鼠标左键单击,然后并将Signal Type:选为下面表格中的。

名称

 

Signal Type:

CPU_Addr

对应

adress

CPU_CS

对应

chipselect

CPU_RD

对应

read

CPU_RD_DATA

对应

readdata

CPU_WR

对应

write

CPU_WR_DATA

对应

writedata

第九步、注意:PWM_Out不能像上面几个一样操作了,首先在左边点击《add interface》,然后选中Conduit。

选中Conduit后

接下来,在下面添加信号,鼠标右键选中PWM_Out,然后将它到Conduit_end下面

第十步、同理上面的步骤,新建一个Reset Input

和上面一样,将rst拉下来,并且将Signal Type:选为reset

第十一步、接着你会看到一条错误“Interface must have an associated reset”

解决办法,按照图中的文字操作

第十二步、回过头看第二个参数窗口,你就会看到生成了这么一个东西,就证明你做对了。

第十三步,点击Finish,选择YES,Save

第十四步,查看你创建的IP核,(如果你的软件没有自动生成,那你就按照右图的办法操作,我没有试过),接下来就是调用了呗。

第四部分、修改别人的软核

1、调用自己的IP核详细步骤

第一步、这个就和前面的IP核调用方法一样,这里没有参数配置,直接Finish

第二步、唯一要注意的就是这里要双击,把端口导出来。

第三步、生成自己的软核,再等待片刻。注意:生成好了之后记得将新生成的端口复制,这里容易忘

第五部分、编写Quartus中的verilog代码

1、代码

module AC620_GHRD(
	input  wire        clk,                           //                        clk.clk
	input  wire        reset_n,                     //                      reset.reset_n
	output wire        lcd_rst,                    //                    lcd_rst.export
	output wire        lcd_rd_n,                     //                     lcd_rd.export
	output wire        lcd_bl,                     //                     lcd_bl.export
	output wire        lcd_wr_n,                     //                     lcd_wr.export
	output wire        lcd_rs,                     //                     lcd_rs.export
	output wire        lcd_cs_n,                     //                     lcd_cs.export
	inout  wire [15:0] lcd_data,                     //                     lcd_db.export
	output wire        sdram_clk,                     //                  sdram_clk.clk
	output wire [11:0] sdram_addr,                        //                      sdram.addr
	output wire [1:0]  sdram_ba,                          //                           .ba
	output wire        sdram_cas_n,                       //                           .cas_n
	output wire        sdram_cke,                         //                           .cke
	output wire        sdram_cs_n,                        //                           .cs_n
	inout  wire [15:0] sdram_dq,                          //                           .dq
	output wire [1:0]  sdram_dqm,                         //                           .dqm
	output wire        sdram_ras_n,                       //                           .ras_n
	output wire        sdram_we_n,                         //                           .we_n
	input  wire        uart_0_rxd,                        //                     uart_0.rxd
	output wire        uart_0_txd,                        //                           .txd
	output wire        epcs_dclk,                         //                       epcs.dclk
	output wire        epcs_sce,                          //                           .sce
	output wire        epcs_sdo,                          //                           .sdo
	input  wire        epcs_data0,                         //                           .data0

	//对新的端口进行定义
	output wire        pwm_out
	
	);

    mysystem u0 (
		.clk_clk                           (clk),                           //                        clk.clk
		.reset_reset_n                     (reset_n),                     //                      reset.reset_n
      .uart_0_rxd                        (uart_0_rxd),                        //                     uart_0.rxd
      .uart_0_txd                        (uart_0_txd),                        //                           .txd
      .epcs_dclk                         (epcs_dclk),                         //                       epcs.dclk
      .epcs_sce                          (epcs_sce),                          //                           .sce
      .epcs_sdo                          (epcs_sdo),                          //                           .sdo
      .epcs_data0                        (epcs_data0),                        //
		.lcd_rst_export                    (lcd_rst),                    //                    lcd_rst.export
		.lcd_bl_export                     (lcd_bl),                     //                     lcd_bl.export
		.lcd_wr_n                          (lcd_wr_n),                          //                        lcd.wr_n
		.lcd_rd_n                          (lcd_rd_n),                          //                           .rd_n
		.lcd_data                          (lcd_data),                          //                           .data
		.lcd_rs                            (lcd_rs),                            //                           .rs
		.lcd_cs_n                          (lcd_cs_n),                           //  
		.sdram_clk_clk                     (sdram_clk),                     //                  sdram_clk.clk
		.altpll_0_phasedone_conduit_export (), // altpll_0_phasedone_conduit.export
		.altpll_0_locked_conduit_export    (),    //    altpll_0_locked_conduit.export
		.altpll_0_areset_conduit_export    (),    //    altpll_0_areset_conduit.export
		.sdram_addr                        (sdram_addr),                        //                      sdram.addr
		.sdram_ba                          (sdram_ba),                          //                           .ba
		.sdram_cas_n                       (sdram_cas_n),                       //                           .cas_n
		.sdram_cke                         (sdram_cke),                         //                           .cke
		.sdram_cs_n                        (sdram_cs_n),                        //                           .cs_n
		.sdram_dq                          (sdram_dq),                          //                           .dq
		.sdram_dqm                         (sdram_dqm),                         //                           .dqm
		.sdram_ras_n                       (sdram_ras_n),                       //                           .ras_n
		.sdram_we_n                        (sdram_we_n),                         //                           .we_n
	  
	   //PWM端口
	   .pwm_writeresponsevalid_n          (pwm_out)  //       pwm.writeresponsevalid_n
	
	);

endmodule

2、注意

第一步、粘贴复制过来的代码,然后定义变量。

第二步、分配引脚,我这里直接把这个引脚分配给我FPGA上面的一个LED灯,如果你有示波器,你可以分配给一个裸露的管脚,没有的话就LED,观察LED灯的呼吸,来判断PWM是否正常。

第六部分、编写ecplise里面的C代码

1、代码的功能阐述

一直改变占空比,然后你可以看到你的LED处于呼吸灯状态。

2、代码

/*
 * main.c
 *
 *  Created on: 2020年12月14日
 *      Author: dpt
 */
#include <io.h>
#include <string.h>
#include <sys/unistd.h>
#include <stdio.h>    //printf的头文件
#include "altera_avalon_pio_regs.h"
#include "system.h"
#include "alt_types.h"
#include "sys/alt_irq.h"


#define clk100m 100000000


int main()
{
	int freq=1000;
	float duty=0.5;
	alt_u32 n_high;
	alt_u32 n_low;
	printf("Hellow PWM IP LED!");
	 while(1)
	 {
		if(duty<1)
			duty =duty+0.1;
		if(duty>=1)
			duty=0.1;
		n_high=(alt_u32)((clk100m/freq)*duty);
		n_low=(alt_u32)((clk100m/freq)*(1-duty));
		IOWR_32DIRECT(PWM_0_BASE, 0*4, n_high);
		IOWR_32DIRECT(PWM_0_BASE, 1*4, n_low);
		IOWR_32DIRECT(PWM_0_BASE, 2*4, 1);

		usleep(400000);

	 }
	 return 0;
}

第七部分、总结

1、效果展示

已经拍成视频放在群文件中,可以去下载查看。你也可以先点击这个链接直接观看效果(https://live.csdn.net/v/120677),这里放张图片。

2、感想

其实我这里只教了你怎么导入IP核文件,然后怎么调用,这其实不难,只要你按部就班的来就不会出错。最难的就是“pwmip2020.v”这个文件的编写,博主以后会研究这个,争取出一期自己写IP核的教程,可能会很慢,因为我还是一名大三的学生,学校也很普通(我很骄傲来到自己的学校)况且我认为我自己不是一个很聪明的人,所以大家坚持和我一起学,难没关系,多花时间就可以。

最后希望有问题的铁子加下面这个群,群文件里面有所有的资料,有问题也可以直接提出来,当然也可以私聊我。

3、完整资料

欢乐的白嫖时光从来不会缺席!(完整工程、演示视频、参考资料下载链接:https://download.csdn.net/download/Learning1232/13688871)。

 

  • 12
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大屁桃

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值