这里写目录标题
一、生成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)
电脑和设备网络地址要在同一网络下
六、执行
复制该文件
右上角切换
粘贴至该文件下
连接&进入终端 运行