【Soc FPGA】Soc之PWM实现呼吸灯

一、生成PWM_IP核

实现socPWM呼吸灯需要自己生成一个PWM的IP核添加外设

一、PWM_IP核代码

PWM_IP核需要产生一个PWM波,PWM核代码如下:

// An highlighted block
module pwm_logic( 
    input				clk		        ,
    input				rst_n	        ,
    input				cnt_en		    ,       //计数器使能
    input		[31:0]  counter_arr		,       //预重转载值
    input		[31:0]	counter_ccr 	,       //比较直
    output	reg	     	o_pwm	        

);								 
    //参数定义			 
                        
    //中间信号定义		 
    reg		[31:0]	        cnt                     ;
    wire    	            add_cnt                 ;
    wire		            end_cnt                 ;

    reg     [31:0]          counter_ccr_r           ;  

    //计数器
    always @(posedge clk or negedge rst_n)begin 
       if(!rst_n)begin
            cnt <= 0;
        end 
        else if(add_cnt)begin 
                if(end_cnt)begin 
                    cnt <= 0;
                end
                else begin 
                    cnt <= cnt + 1;
                end 
        end
       else  begin
           cnt <= cnt;
        end
    end 
    
    assign add_cnt = cnt_en;
    assign end_cnt = add_cnt && cnt == counter_arr - 1;

    //counter_ccr_r
    always @(posedge clk )begin 
        if(!cnt)begin
            counter_ccr_r <= counter_ccr;
        end 
        else begin 
            counter_ccr_r <= counter_ccr_r;
        end 
    end

    //o_pwm
    always @(posedge clk or negedge rst_n)begin 
        if(!rst_n)begin
            o_pwm <= 0;
        end 
        else if(counter_ccr_r >= cnt)begin 
            o_pwm <= 0;
        end 
        else if(counter_ccr_r < cnt)begin 
            o_pwm <= 1;
        end 
        else begin
            o_pwm <= o_pwm;
        end
    end

                        
endmodule

module pwm_avalon_port( 
    input				clk		,
    input				rst_n	,
    //avalon memory mappe slave信号
    input				as_chipselect		,       //片选信号
    input		[1:0]   as_address		    ,       //地址信号
    input		     	as_write 	        ,       //写请求信号
    input	    [31:0]	as_writedata	    ,       //写数据输入信号
    output	reg	[31:0]	as_readdata	        ,       //读数据输出信号
    output              o_pwm               
);								 
    //参数定义			 
                        
    //中间信号定义	
    reg         [31:0]  counter_arr ;       //预重转载值
    reg         [31:0]  counter_ccr ;       //比较直
    reg                 control     ;       //控制pwm输出

    //counter_arr
    always @(posedge clk or negedge rst_n)begin 
        if(!rst_n)begin
            counter_arr <= 32'b0;
        end 
        else if(as_chipselect && as_write && (as_address == 0))begin 
            counter_arr <= as_writedata;
        end 
        else begin 
            counter_arr <= counter_arr;
        end 
    end
    //counter_ccr
    always @(posedge clk or negedge rst_n)begin 
        if(!rst_n)begin
            counter_ccr <= 32'b0;
        end 
        else if(as_chipselect && as_write && (as_address == 1))begin 
            counter_ccr <= as_writedata;
        end 
        else begin 
            counter_ccr <= counter_ccr;
        end 
    end

    //control
    always @(posedge clk or negedge rst_n)begin 
        if(!rst_n)begin
            control <= 0;
        end 
        else if(as_chipselect && as_write && (as_address == 2))begin 
            control <= as_writedata[0];
        end 
        else begin 
            control <= control;
        end 
    end
    
    //as_readdata
    always @(posedge clk or negedge rst_n)begin 
        if(!rst_n)begin
            as_readdata <= 32'b0;
        end 
        else if(as_chipselect)begin 
           case (as_address)
               0:as_readdata <= counter_arr;
               1:as_readdata <= counter_ccr;
               2:as_readdata <= control;
               default: as_readdata <= 0;
           endcase
        end 
    end

    pwm_logic u_pwm_logic
    ( 
    /*input				*/.clk		        (clk        ),
    /*input				*/.rst_n	        (rst_n      ),
    /*input				*/.cnt_en		    (control    ),       //计数器使能
    /*input		[31:0]  */.counter_arr		(counter_arr),       //预重转载值
    /*input		[31:0]	*/.counter_ccr 	    (counter_ccr),       //比较值
    /*output	reg	    */.o_pwm	        (o_pwm      )        

);
                        
endmodule

二、Platform Designer生成自己的IP核

打开我们的黄金工程进入Platform Designer
在这里插入图片描述
Platform Designer
在这里插入图片描述
打开soc_system.qsys文件
在这里插入图片描述
点击New创建自己的ip
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
双击add interface 分别添加Reset input 和Conduit
在这里插入图片描述
将o_pwm和rst_n分别拉入conduit_end和rst_n(Reset)下,o_pwm -> Signal Type 改为wire,删除avalon_slave_0

在这里插入图片描述
点击Finish,这就生成自己的IP核

三、添加外设

当生成了自己的IP核后就添加外设,在Platform Designer页面IP Catalong下添加双击自己生成的IP核,双击后会产生一个窗口直接Finish
在这里插入图片描述
在这里插入图片描述
软件改地址只需点击Sy ->Assign Base Addresses
编译
在这里插入图片描述
编译完成后进入Generate ->show Instantiation Template

在这里插入图片描述
复制 .pwm_conduit_end_wire (<connected-to-pwm_conduit_end_wire>), // pwm_conduit_end.wire

在这里插入图片描述
复制完成Close 后Finish
外设添加完成后会弹出Quartus Prime窗口 直接OK
在这里插入图片描述

四、修改黄金工程&编译

将复制代码粘贴到黄金工程中
在这里插入图片描述
因为编写的PWM输出为一位宽的,LED位四位宽,需将其转为四位宽
在这里插入图片描述
完成后直接全编译工程,黄金工程编译要很长时间等待我们可以去编写其他的程序

二、生成dtb、hps_0.h、rbf文件

当黄金工程编译完成后要生成dtb、hps_0.h、rbf文件,打开 SoC EDS Command Shell软件
在这里插入图片描述
进入黄金工程文件路径
在这里插入图片描述
输入make dtb 、./generate_hps_qsys_header.sh、./sof_to_rbf.bat分别生成dtb、hps_0.h、rbf文件,./sof_to_rbf.bat,需在F:\seven_code\soc\C5MB_GHRD\output_files路经下,将dtb、rbf文件复制到储存卡内,

三、编写代码

输入命令eclipse&进入app-Remote System Explorer-Eclipse Platform
在这里插入图片描述
点击OK
在这里插入图片描述
默认会创建工程
将产生的hps_0.h文件复制到工程文件
在这里插入图片描述

代码

// An highlighted block
//gcc标准头文件
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>

//HPS厂家提供的底层定义头文件
#define soc_cv_av //开发平台Cyclone V 系列

#include "hwlib.h"
#include "socal/socal.h"
#include "socal/hps.h"

//与用户具体的HPS 应用系统相关的硬件描述头文件
#include "hps_0.h"

#define HW_REGS_BASE (ALT_STM_OFST)     //HPS外设地址段基地址
#define HW_REGS_SPAN (0x04000000)		//HPS外设地址段地址空间 64MB大小
#define HW_REGS_MASK (HW_REGS_SPAN - 1) //HPS外设地址段地址掩码

static volatile unsigned long *led_pio_virtual_base=NULL;
static volatile unsigned long *key_pio_virtual_base=NULL;
static volatile unsigned long *my_pwm=NULL;

int fpga_init(int *virtual_base)
{
	int fd;
	void *perph_virtual_base;
	//1.open打开mmu
	fd = open("/dev/mem",(O_RDWR | O_SYNC));
	if(fd == -1)
	{
		printf("open failed..\n");
		exit(1);
	}
	//mmap 映射虚拟地址
	perph_virtual_base = mmap(NULL,HW_REGS_SPAN, ( PROT_READ | PROT_WRITE ),MAP_SHARED,fd,HW_REGS_BASE);

	if(perph_virtual_base == MAP_SHARED)
	{
		printf("mmap() is failed..\n");
		return 1;
	}
    //接口
	led_pio_virtual_base = perph_virtual_base + ((unsigned long)(ALT_LWFPGASLVS_OFST + PIO_LED_BASE) & (unsigned long)(HW_REGS_MASK));
	key_pio_virtual_base = perph_virtual_base + ((unsigned long)(ALT_LWFPGASLVS_OFST + PIO_KEY_BASE) & (unsigned long)(HW_REGS_MASK));
	my_pwm = perph_virtual_base + ((unsigned long)(ALT_LWFPGASLVS_OFST + PWM_BASE) & (unsigned long)(HW_REGS_MASK));
	//保存虚拟地址
	*virtual_base = perph_virtual_base;

	return fd;
}

int main()
{
	int virtual_base;
	int fd;
	fd = fpga_init(&virtual_base);
	 int tmp = -0xffff;
	//打开使能
	*(my_pwm+2) = 0x1;
	*(my_pwm+0) = 65536;   //65536

	while(1)
	{
		tmp = tmp+10;
		if(tmp>65536)
		{
			tmp =-65536;
		}
		else if(tmp>0)
		{
			*(my_pwm+1) = tmp;
		}
		else
		{
			*(my_pwm+1) = -tmp;
		}
		usleep(150);
	}
	if(munmap(virtual_base,HW_REGS_SPAN) != 0)
	{
		printf("munmap() is failed..\n");
		close(fd);
		return 1;
	}
	close(fd);
	return 0;
}

四、环境配置

环境配置
在这里插入图片描述
右击工程进入properties
在这里插入图片描述
这是已经添加好了的,添加Quartus安装路径下…\Quartus\embedded\ip\altera\hps\altera_hps\hwlib\include\soc_cv_av和…\Quartus\embedded\ip\altera\hps\altera_hps\hwlib\include
在这里插入图片描述

五、设置设备地址

进入MobaXterm_Personal_21.1软件,设备复位,登录。
在这里插入图片描述
更改地址
在这里插入图片描述
电脑地址
设置
在这里插入图片描述
网络和internet
在这里插入图片描述
更改设配器
在这里插入图片描述
以太网 属性
在这里插入图片描述
internet协议版本 4(TCP/IPv)
在这里插入图片描述

电脑和设备网络地址要在同一网络下

六、执行

复制该文件
在这里插入图片描述

右上角切换
在这里插入图片描述
粘贴至该文件下
在这里插入图片描述
连接&进入终端 运行
在这里插入图片描述

  • 3
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值