PWM定制组件实现过程

module pwm_task_logic
(
    clk,
    pwm_enable,
    resetn,
    clock_divide,
    duty_cycle,
    pwm_out
);

//Inputs
input clk;                //Input Clock to be divided
input [31:0] clock_divide;    //Clock Divide value
input [31:0] duty_cycle;    //Duty Cycle vale
input pwm_enable;            //Enable signal
input resetn;            //Reset

//Outputs
output pwm_out;            //PWM output

//Signal Declarations
reg [31:0] counter;        //PWM Internal Counter
reg pwm_out;            //PWM output

//Start Main Code
always @(posedge clk or negedge resetn)         //PWM Counter Process
begin
    if (~resetn)begin
        counter <= 0;
    end
    else if(pwm_enable)begin
        if (counter >= clock_divide)begin
            counter <= 0;
        end
        else begin
            counter <= counter + 1;
        end
    end
    else begin
        counter <= counter;
    end
end

always @(posedge clk or negedge resetn)      //PWM Comparitor
begin
    if (~resetn)begin
        pwm_out <= 0;
    end
    else if(pwm_enable)begin
        if (counter >= duty_cycle)begin
            pwm_out <= 1‘b1;
        end
        else begin
            if (counter == 0)
                pwm_out <= 0;
            else
                pwm_out <= pwm_out;
            end
        end
    else begin
        pwm_out <= 1‘b0;
    end
end

endmodule

module pwm_register_file
(    //Avalon Signals
    clk,
    resetn,
    chip_select,
    address,
    write,
    write_data,
    read,
    read_data,

    //PWM Output Signals
    pwm_clock_divide,
    pwm_duty_cycle,
    pwm_enable
);

//Parameters
parameter clock_divide_reg_init = 32‘h0000_0000;
parameter duty_cycle_reg_init   = 32‘h0000_0000;

//Inputs

input clk;                  //System Clock
input resetn;            //System Reset
input chip_select;        //Avalon Chip select signal
input [1:0] address;          //Avalon Address bus
input write;            //Avalon Write signal
input [31:0] write_data;    //Avalon Write data bus
input read;                  //Avalon read signal

//Outputs
output [31:0] read_data;      //Avalon read data bus
output [31:0] pwm_clock_divide; //PWM clock divide drive signals
output [31:0] pwm_duty_cycle;   //PWM duty cycle drive signals
output        pwm_enable;       //PWM enable drive signals

//Signal Declarations    

reg [31:0] clock_divide_register;    //Clock divider register
reg [31:0] duty_cycle_register;      //Duty Cycle Register
reg        enable_register;         //Enable Bit
reg [31:0] read_data;            //Read_data bus

//Nodes used for address decoding
wire clock_divide_reg_selected, duty_cycle_reg_selected, enable_reg_selected;
//Nodes for determining if a valid write occurred to a specific address
wire write_to_clock_divide, write_to_duty_cycle, write_to_enable;
//Nodes for determining if a valid read occurred to a specific address
wire read_to_clock_divide, read_to_duty_cycle, read_to_enable;
//Nodes used to determine if a valid access has occurred
wire valid_write, valid_read;

//Start Main Code    

//address decode
assign clock_divide_reg_selected = !address[1] & !address[0];  //address 00
assign duty_cycle_reg_selected   = !address[1] &  address[0];  //address 01
assign enable_reg_selected       =  address[1] & !address[0];  //address 10

//determine if a vaild transaction was initiated
assign valid_write = chip_select & write;
assign valid_read  = chip_select & read;

//determine if a write occurred to a specific address
assign write_to_clock_divide = valid_write & clock_divide_reg_selected;
assign write_to_duty_cycle   = valid_write & duty_cycle_reg_selected;
assign write_to_enable       = valid_write & enable_reg_selected;

//determine if a read occurred to a specific address
assign read_to_clock_divide = valid_read & clock_divide_reg_selected;
assign read_to_duty_cycle   = valid_read & duty_cycle_reg_selected;
assign read_to_enable       = valid_read & enable_reg_selected;

//Write to clock_divide Register
always@(posedge clk or negedge resetn)
begin
    if(~resetn)begin //Async Reset
        clock_divide_register <= clock_divide_reg_init; //32‘h0000_0000;
    end
    else begin
        if(write_to_clock_divide) begin
            clock_divide_register <= write_data;
        end
        else begin
            clock_divide_register <= clock_divide_register;
        end

    end
end    

//Write to duty_cycle Register
always@(posedge clk or negedge resetn)
begin
    if(~resetn)begin //Async Reset
        duty_cycle_register <= duty_cycle_reg_init; //32‘h0000_0000;
    end
    else begin
        if(write_to_duty_cycle) begin
            duty_cycle_register <= write_data;
        end
        else begin
            duty_cycle_register <= duty_cycle_register;
        end
    end
end    

//Write to enable register
always@(posedge clk or negedge resetn)
begin
    if(~resetn)begin //Async Reset
        enable_register <= 1‘b0;
    end
    else begin
        if(write_to_enable)begin
            enable_register <= write_data[0];
        end
        else begin
            enable_register <= enable_register;
        end
    end
end

//Read Data Bus Mux
always@(read_to_clock_divide or read_to_duty_cycle or read_to_enable or clock_divide_register or duty_cycle_register or enable_register)
begin
    if(read_to_clock_divide) begin
        read_data = clock_divide_register;
    end
    else if(read_to_duty_cycle) begin
        read_data = duty_cycle_register;
    end
    else if(read_to_enable) begin
        read_data = {31‘d0,enable_register};
    end
    else begin
        read_data = 32‘h0000_0000;
    end
end

//assign register values to register file outputs to the PWM
assign pwm_clock_divide = clock_divide_register;
assign pwm_duty_cycle = duty_cycle_register;
assign pwm_enable = enable_register;

endmodule

 

module pwm_avalon_interface
(    clk,
    resetn,
    avalon_chip_select,
    address,
    write,
    write_data,
    read,
    read_data,
    pwm_out
 );

//Parameter values to pass to pwm_register_file instance
parameter clock_divide_reg_init = 32‘h0000_0000;
parameter duty_cycle_reg_init = 32‘h0000_0000;

//Avalon_Slave_PWM Avalon I/O
input clk;                   //System clock - tied to all blocks
input resetn;             //System reset - tied to all blocks
input avalon_chip_select;    //Avalon Chip select
input [1:0]address;          //Avalon Address bus
input write;            //Avalon Write signal
input [31:0]write_data;        //Avalon Write data bus
input read;                    //Avalon Read signal

output [31:0]read_data;        //Avalon Read data bus

//Avalon_Slave_PWM Exported I/O
output pwm_out;              //PWM output signal

//Avalon_Slave_PWM Interal Nodes
wire [31:0] pwm_clock_divide;  //Clock divide wire from register file to pwm task logic
wire [31:0] pwm_duty_cycle;    //Duty cycle value from register file to pwm task logic
wire           pwm_enable;        //PWM enable signal from register file to pwm task logic

//PWM Instance
pwm_task_logic task_logic
(
    .clk             (clk ),
    .pwm_enable       (pwm_enable),
    .resetn           (resetn),
    .clock_divide     (pwm_clock_divide),
    .duty_cycle       (pwm_duty_cycle),
    .pwm_out        (pwm_out)
);

//Register File instance
pwm_register_file #(clock_divide_reg_init, duty_cycle_reg_init) memory_element
(
    .clk                 (clk),
    .resetn            (resetn),
    .chip_select       (avalon_chip_select),
    .address           (address),
    .write             (write),
    .write_data        (write_data),
    .read              (read),
    .read_data         (read_data),
    .pwm_clock_divide  (pwm_clock_divide),
    .pwm_duty_cycle     (pwm_duty_cycle),
    .pwm_enable           (pwm_enable)
);

endmodule

PWM软件测试代码:

#include <stdio.h>
#include "system.h"
#include "unistd.h"

typedef struct{
        volatile unsigned int divi;
        volatile unsigned int duty;
        volatile unsigned int enable;
    }PWM;

    int main()
    {
    int dir = 1;
    int d = 0 ;

        //将pwm指向PWM_0_BASE首地址
    PWM *pwm = (PWM *)PWM_AVALON_INTERFACE_0_BASE;
    //对pwm进行初始化,divi最大值为232-1。
        pwm->divi = 50000000;
        pwm->duty = 0;
        pwm->enable = 1;

        //通过不断的改变duty值来改变LED一个周期亮灯的时间长短
        while(1){
            if(dir > 0){
                if(pwm->duty < pwm->divi)
                { pwm->duty += 1000000;
                    d++ ;
                }
                else
                { dir = 0;
                    d = 0;}
            }
            else{
                if(pwm->duty > 0)
                {
                    pwm->duty -= 1000000;
                d--;
                }
                else
                    dir = 1;
            }

            usleep(1000000);

            printf("hello from pwm %d",d);
        }

        return 0;
    }

时间: 2024-10-14 21:15:01

PWM定制组件实现过程的相关文章

Android 用户界面---定制组件(Custom Components)

基于布局类View和ViewGroup的基本功能,Android为创建自己的UI界面提供了先进和强大的定制化模式.首先,平台包含了各种预置的View和ViewGroup子类---Widget和layout,可以使用它们来构造自己的UI界面. 部分的可以利用的widget包括:Button.TextView.EditText.ListView.CheckBox.RadioButton.Gallery.Spinner.以及比较特殊用途的AutoCompleteTextView.ImageSwitch

VMware vSphere虚拟化-VMware ESXi 5.5组件安装过程记录

服务端安装步骤: VMWARE ESXi 5.5安装步骤:1.通过软碟通将VMWare ESXi 5.5的iso镜像文件刻录到U盘里,通过U盘安装ESXi虚拟机2.将U盘插入服务器上,设定USB闪存驱动器启动,选择第一个ESXi-5.5.0-13331820-standard Installer安装.读取安装文件 3.在引导过程中,可以看到主机的cpu和内存的基本信息 4.在出现的第一个安装引导界面中,点击Enter(回车键),确定继续安装 5.按F11同意协议并继续 6.选择磁盘,按回车键继续

SQL Server阻止了对组件xp_cmdshell过程的解决方案

错误描述:SQL Server阻止了对组件'xp_cmdshell'的过程'sys.xp_cmdshell'的访问.因为此组件已作为此服务嚣安全配置的一部分而被关闭.系统管理员可以通过使用sp_configure启用'xp_cmdshell'.有关启用'xp_cmdshell'的详细信息,请参阅sQL帮助文件. [分析]: 查询网络资料以及SQL帮助可知,xp_cmdshell可以让系统管理员以操作系统命令行解释器的方式执行给定的命令字符串,并以文本行方式返回任何输出,是一个功能非常强大的扩展存

Activity组件启动过程(二)

前面启动过程图:(源码基于Android5.1) 获得到ActivityManagerProxy的实例后,会通过ActivityManagerProxy将启动Activity组件的相关信息写入到Parcel对象data中,然后发送一个类型为START_ACTIVITY_TRANSACTION的进程间通信请求给AMS(ActivityManagerService),接下来的工作的会在AMS进程中进行完成. 接下来的启动过程总结为下图: 处理START_ACTIVITY_TRANSACTION类型的

vue组件初始化过程

之前文章有写到vue构造函数的实例化过程,只是对vue实例做了个粗略的描述,并没有说明vue组件实例化的过程.本文主要对vue组件的实例化过程做一些简要的描述. 组件的实例化与vue构造函数的实例化,大部分是类似的,vue的实例可以当做一个根组件,普通组件的实例化可以当做子组件.真实的DOM是一个树形结构,虚拟DOM本质只是真实DOM的抽象,也是一个树形结构.简单来说,整个vue工程的实例化过程如下: 如上图所示,在调用render函数时,会依次调用createElement方法,createE

java实现自定义同步组件的过程

实现同步组件twinsLock:可以允许两个线程同时获取到锁,多出的其它线程将被阻塞. 以下是自定义的同步组件类,一般我们将自定义同步器Sync定义为同步组件TwinsLock的静态内部类. 实现同步器需要继承AbstractQueuedSynchronizer并覆盖相应的方法. package com.lock; import java.util.concurrent.TimeUnit;import java.util.concurrent.locks.AbstractQueuedSynchr

从源码的角度理解四大组件的工作过程——Android开发艺术探索笔记

原文链接http://sparkyuan.me/2016/03/14/四大组件的工作过程/ 转载注明出处 系统对四大组件的过程进行了很大程度的封装,日常开发中并不需要了解底层的工作原理,那么研究这些原理的意义在哪里呢? 如果你想在技术上更进一步,那么了解一些系统的工作原理是十分必要的,也是开发人员日后成长为高级工程师所必备的技术能力. Android作为一个优秀的基于Linux操作系统,其内部一定有很多值得我们学习的地方,通过对Android操作系统的学习对提高开发人员的内功有很大的好处. 如果

Activity组件的启动过程

最近在学习Activity的组件过程,在这里把过程写一遍,当作记忆,如果想看时序图或者源码的,可以网上另找. Laucher组件启动程序中MainActivity组件的过程: (1)Laucher组件向ActivityManagerService发送一个启动MainActivity组件的进程间通信. (2)ActivityManagerService首先将要启动的MainActivity组件的intent信息保存起来,同时向Laucher组件发送一个进入中止状态的进程间通信请求. (3)Lauc

《Nodejs开发加密货币》之二十七:开发通用的HTML组件

人的懒惰常常是麻烦的开始.多数程序员都希望自己的工作一劳永逸,一次开发,到处使用,成了人人追逐的目标,我也不例外.最初写<Nodejs开发加密货币>系列文章,因为不喜欢设定好了去写,所以目录反复修改,索性弄了小工具gitbook-summary:在写入门文章的时候,反复搜索github,索性把检索与制图集成到一起,弄了个开发语言检索统计工具(见<Node.js让您的前端开发像子弹飞一样>文章实例):阅读源码的时候,手动整理Uml图很辛苦,干脆写成了js2uml工具(见<轻松从