SoC-PWM

文章目录

  • 一、原理图
  • 二、工程代码

avalon 读数据

在这里插入图片描述

avalon 写数据

在这里插入图片描述
在这里插入图片描述

一、原理图

在这里插入图片描述

二、工程代码

1.hps_0.h文章来源地址https://uudwc.com/A/y5qop

#ifndef _ALTERA_HPS_0_H_
#define _ALTERA_HPS_0_H_

/*
 * This file was automatically generated by the swinfo2header utility.
 * 
 * Created from SOPC Builder system 'soc_system' in
 * file './soc_system.sopcinfo'.
 */

/*
 * This file contains macros for module 'hps_0' and devices
 * connected to the following masters:
 *   h2f_axi_master
 *   h2f_lw_axi_master
 * 
 * Do not include this header file and another header file created for a
 * different module or master group at the same time.
 * Doing so may result in duplicate macro names.
 * Instead, use the system header file which has macros with unique names.
 */

/*
 * Macros for device 'sld_hub_controller_system_0_link', class 'altera_mm_debug_link'
 * The macros are prefixed with 'SLD_HUB_CONTROLLER_SYSTEM_0_LINK_'.
 * The prefix is the slave descriptor.
 */
#define SLD_HUB_CONTROLLER_SYSTEM_0_LINK_COMPONENT_TYPE altera_mm_debug_link
#define SLD_HUB_CONTROLLER_SYSTEM_0_LINK_COMPONENT_NAME sld_hub_controller_system_0_link
#define SLD_HUB_CONTROLLER_SYSTEM_0_LINK_BASE 0x0
#define SLD_HUB_CONTROLLER_SYSTEM_0_LINK_SPAN 128
#define SLD_HUB_CONTROLLER_SYSTEM_0_LINK_END 0x7f

/*
 * Macros for device 'pwm_0', class 'pwm'
 * The macros are prefixed with 'PWM_0_'.
 * The prefix is the slave descriptor.
 */
#define PWM_0_COMPONENT_TYPE pwm
#define PWM_0_COMPONENT_NAME pwm_0
#define PWM_0_BASE 0x80
#define PWM_0_SPAN 16
#define PWM_0_END 0x8f

/*
 * Macros for device 'sysid_qsys', class 'altera_avalon_sysid_qsys'
 * The macros are prefixed with 'SYSID_QSYS_'.
 * The prefix is the slave descriptor.
 */
#define SYSID_QSYS_COMPONENT_TYPE altera_avalon_sysid_qsys
#define SYSID_QSYS_COMPONENT_NAME sysid_qsys
#define SYSID_QSYS_BASE 0x1000
#define SYSID_QSYS_SPAN 8
#define SYSID_QSYS_END 0x1007
#define SYSID_QSYS_ID 2899645186
#define SYSID_QSYS_TIMESTAMP 1658294069

/*
 * Macros for device 'dipsw_pio', class 'altera_avalon_pio'
 * The macros are prefixed with 'DIPSW_PIO_'.
 * The prefix is the slave descriptor.
 */
#define DIPSW_PIO_COMPONENT_TYPE altera_avalon_pio
#define DIPSW_PIO_COMPONENT_NAME dipsw_pio
#define DIPSW_PIO_BASE 0x4000
#define DIPSW_PIO_SPAN 16
#define DIPSW_PIO_END 0x400f
#define DIPSW_PIO_BIT_CLEARING_EDGE_REGISTER 1
#define DIPSW_PIO_BIT_MODIFYING_OUTPUT_REGISTER 0
#define DIPSW_PIO_CAPTURE 0
#define DIPSW_PIO_DATA_WIDTH 3
#define DIPSW_PIO_DO_TEST_BENCH_WIRING 0
#define DIPSW_PIO_DRIVEN_SIM_VALUE 0
#define DIPSW_PIO_EDGE_TYPE NONE
#define DIPSW_PIO_FREQ 50000000
#define DIPSW_PIO_HAS_IN 0
#define DIPSW_PIO_HAS_OUT 1
#define DIPSW_PIO_HAS_TRI 0
#define DIPSW_PIO_IRQ_TYPE NONE
#define DIPSW_PIO_RESET_VALUE 0

/*
 * Macros for device 'button_pio', class 'altera_avalon_pio'
 * The macros are prefixed with 'BUTTON_PIO_'.
 * The prefix is the slave descriptor.
 */
#define BUTTON_PIO_COMPONENT_TYPE altera_avalon_pio
#define BUTTON_PIO_COMPONENT_NAME button_pio
#define BUTTON_PIO_BASE 0x5000
#define BUTTON_PIO_SPAN 16
#define BUTTON_PIO_END 0x500f
#define BUTTON_PIO_BIT_CLEARING_EDGE_REGISTER 1
#define BUTTON_PIO_BIT_MODIFYING_OUTPUT_REGISTER 0
#define BUTTON_PIO_CAPTURE 0
#define BUTTON_PIO_DATA_WIDTH 3
#define BUTTON_PIO_DO_TEST_BENCH_WIRING 0
#define BUTTON_PIO_DRIVEN_SIM_VALUE 0
#define BUTTON_PIO_EDGE_TYPE NONE
#define BUTTON_PIO_FREQ 50000000
#define BUTTON_PIO_HAS_IN 0
#define BUTTON_PIO_HAS_OUT 1
#define BUTTON_PIO_HAS_TRI 0
#define BUTTON_PIO_IRQ_TYPE NONE
#define BUTTON_PIO_RESET_VALUE 0

/*
 * Macros for device 'hex0_3_pio', class 'altera_avalon_pio'
 * The macros are prefixed with 'HEX0_3_PIO_'.
 * The prefix is the slave descriptor.
 */
#define HEX0_3_PIO_COMPONENT_TYPE altera_avalon_pio
#define HEX0_3_PIO_COMPONENT_NAME hex0_3_pio
#define HEX0_3_PIO_BASE 0x6000
#define HEX0_3_PIO_SPAN 16
#define HEX0_3_PIO_END 0x600f
#define HEX0_3_PIO_BIT_CLEARING_EDGE_REGISTER 0
#define HEX0_3_PIO_BIT_MODIFYING_OUTPUT_REGISTER 0
#define HEX0_3_PIO_CAPTURE 1
#define HEX0_3_PIO_DATA_WIDTH 32
#define HEX0_3_PIO_DO_TEST_BENCH_WIRING 0
#define HEX0_3_PIO_DRIVEN_SIM_VALUE 0
#define HEX0_3_PIO_EDGE_TYPE RISING
#define HEX0_3_PIO_FREQ 50000000
#define HEX0_3_PIO_HAS_IN 1
#define HEX0_3_PIO_HAS_OUT 0
#define HEX0_3_PIO_HAS_TRI 0
#define HEX0_3_PIO_IRQ_TYPE NONE
#define HEX0_3_PIO_RESET_VALUE 0

/*
 * Macros for device 'hex4_5_pio', class 'altera_avalon_pio'
 * The macros are prefixed with 'HEX4_5_PIO_'.
 * The prefix is the slave descriptor.
 */
#define HEX4_5_PIO_COMPONENT_TYPE altera_avalon_pio
#define HEX4_5_PIO_COMPONENT_NAME hex4_5_pio
#define HEX4_5_PIO_BASE 0x7000
#define HEX4_5_PIO_SPAN 16
#define HEX4_5_PIO_END 0x700f
#define HEX4_5_PIO_BIT_CLEARING_EDGE_REGISTER 0
#define HEX4_5_PIO_BIT_MODIFYING_OUTPUT_REGISTER 0
#define HEX4_5_PIO_CAPTURE 1
#define HEX4_5_PIO_DATA_WIDTH 16
#define HEX4_5_PIO_DO_TEST_BENCH_WIRING 0
#define HEX4_5_PIO_DRIVEN_SIM_VALUE 0
#define HEX4_5_PIO_EDGE_TYPE RISING
#define HEX4_5_PIO_FREQ 50000000
#define HEX4_5_PIO_HAS_IN 1
#define HEX4_5_PIO_HAS_OUT 0
#define HEX4_5_PIO_HAS_TRI 0
#define HEX4_5_PIO_IRQ_TYPE NONE
#define HEX4_5_PIO_RESET_VALUE 0


#endif /* _ALTERA_HPS_0_H_ */


  1. pwm_logic.v
module pwm_logic(
	clk,   
	rst_n,       
	cnt_en,
	counter_arr,
	counter_ccr,
	o_pwm
);
	input clk;	//时钟输入
	input rst_n;	//复位输入,低电平复位
	input cnt_en;	//计数使能信号
	input [31:0]counter_arr;//输入32位预重装值
	input [31:0]counter_ccr;//输入32位输出比较值
	output reg o_pwm;	//pwm输出信号

	reg [31:0]counter_ccr_r;
	
	always@(posedge clk)
	if(!counter)
		counter_ccr_r <= counter_ccr;
	else
		counter_ccr_r <= counter_ccr_r;	
	
	reg [31:0]counter;//定义32位计数器
	always@(posedge clk or negedge rst_n)
	if(!rst_n)
		counter <= 32'd0;
	else if(cnt_en)begin
		if(counter == 0)
			counter <= counter_arr;//计数到0,加载自动预重装寄存器值
		else
			counter <= counter - 1'b1;//计数器自减1
	end
	else
		counter <= counter_arr;	//没有使能时,计数器值等于预重装寄存器值

	always@(posedge clk or negedge rst_n)
	if(!rst_n)	//让PWM输出信号复位时输出低电平
		o_pwm <= 1'b0;
	else if(counter >= counter_ccr_r)//计数值大于比较值
		o_pwm <= 1'b0;	//输出为0
	else	//计数值小于比较值
		o_pwm <= 1'b1; //输出为1
		
endmodule

  1. pwm_avalon_port.v
module pwm_avalon_port(
	clk,
	reset_n,

	as_chipselect,
	as_address,
	as_write,
	as_readdata,
	as_writedata,
	
	o_pwm
);

	input clk;
	input reset_n;

	input as_chipselect;
	input [1:0]as_address;
	input as_write;
	output reg [31:0]as_readdata;
	input [31:0]as_writedata;

	output o_pwm;


	reg control;
	reg [31:0]counter_arr;
	reg [31:0]counter_ccr;


	pwm_logic pwm_generator(
		.clk(clk),
		.rst_n(reset_n),
		.cnt_en(control),
		.counter_arr(counter_arr),
		.counter_ccr(counter_ccr),
		.o_pwm(o_pwm)
	);

	//写预设寄存器
	always@(posedge clk or negedge reset_n)
	if(!reset_n)
		counter_arr <= 32'd0;
	else if(as_chipselect && as_write && (as_address == 0))
		counter_arr <= as_writedata;
	else
		counter_arr <= counter_arr;
		
	//写比较通道寄存器
	always@(posedge clk or negedge reset_n)
	if(!reset_n)
		counter_ccr <= 32'd0;
	else if(as_chipselect && as_write && (as_address == 1))
		counter_ccr <= as_writedata;
	else
		counter_ccr <= counter_ccr;
		
	//写控制寄存器
	always@(posedge clk or negedge reset_n)
	if(!reset_n)
		control <= 1'd0;
	else if(as_chipselect && as_write && (as_address == 2))
		control <= as_writedata[0];
	else
		control <= control;
		
//读寄存器逻辑		
	always@(posedge clk or negedge reset_n)
	if(!reset_n)
		as_readdata <= 32'd0;
	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 <= 32'd0;
		endcase	
	end

endmodule
  1. main.c
/*
 * pwm_test.c
 *
 *  Created on: 2022年6月16日
 *      Author: 86130
 */


#include <stdio.h>
#include <unistd.h>
#include <sys/mman.h>
#include <fcntl.h>

#define soc_cv_av

#include "hwlib.h"
#include "socal/socal.h"
#include "socal/hps.h"
#include "hps_0.h"
#define HW_RGES_BASE (ALT_STM_OFST)
#define HW_RGES_SPAN (0x04000000)
#define HW_RGES_MASK (HW_RGES_SPAN - 1)

typedef struct{
	volatile unsigned long arr;
	volatile unsigned long ccr;
	volatile unsigned long en;
}PWM;
PWM *my_pwm;

int init_fpga(void *virtual_base){
	int fd;
	void *per_virtual_base;
	fd = open("/dev/mem", (O_RDWR|O_SYNC));
	if(fd == -1){
		printf("ERROR: open is failed!\n");
		exit(0);
	}
	per_virtual_base = mmap(NULL, HW_RGES_SPAN, (PROT_READ|PROT_WRITE), MAP_SHARED, fd, HW_RGES_BASE);
	if(per_virtual_base == MAP_FAILED){
		printf("ERROR: mmap is failed!\n");
		close(fd);
	}
	my_pwm = (PWM *)(per_virtual_base + ((unsigned long)(ALT_LWFPGASLVS_OFST + PWM_0_BASE) & (unsigned long)(HW_RGES_MASK)));
	my_pwm->arr = 1000000;
	my_pwm->ccr = 0;
	my_pwm->en = 1;
	virtual_base = per_virtual_base;
	return fd;
}

int main(){
	int fd;
	void *virtual_base;
	int temp = -1000000;
	fd = init_fpga(virtual_base);
	while(1){
		temp = temp + 100;
		if(temp > 1000000){
			temp = -1000000;
		}
		else if(temp < 0){
			my_pwm->ccr = -temp;
		}
		else{
			my_pwm->ccr = temp;
		}
		usleep(100);//100us
	}
	if(munmap(virtual_base, HW_RGES_SPAN) == -1){
		printf("ERROR: munmap is failed!\n");
		close(fd);
	}
	close(fd);
	return 0;
}


原文地址:https://blog.csdn.net/weixin_43828944/article/details/124887021

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请联系站长进行投诉反馈,一经查实,立即删除!

h
上一篇 2023年09月18日 04:11
下一篇 2023年09月18日 04:19