首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >verilog,提高PWM的速度

verilog,提高PWM的速度
EN

Stack Overflow用户
提问于 2020-12-04 04:02:29
回答 1查看 90关注 0票数 2

我正在尝试设计一个工作在250 PWM输入时钟的PWM+死区。(我需要250 PWM左右的PWM频率。用于自定义降压调节器)

这就是我到目前为止使用来自网格的IceCube2,使用iCE40LP1K设备实现的东西。最高频率得到(模拟)的是142 MHz最坏情况和260 Mhz最佳情况(-40°)。

我想知道这是否是包括互补输出死区的PWM发生器的正确方法,或者换句话说,这是否可以改进得更多。

代码语言:javascript
运行
复制
module top(
  input clk_16,
  input [9:0] data_in,
  output reg PWM_H,
  output reg PWM_L
);

  reg [9:0] compare;
  reg [9:0] counter = 0;

  always @(posedge PLLOUTCORE)
  begin
   compare <= data_in;
  end

  always@ (posedge PLLOUTCORE )
  begin

    if ( counter < compare )
        PWM_H <= 1;
    else // >= compare
        PWM_H <= 0;

    if ( counter == compare + 16 )
        PWM_L <= 1;
        
    if ( counter == (1024-16) )
        PWM_L <= 0;    
        
    counter <= counter+1;
  end
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-12-04 12:01:50

这是一个有点开放式的问题,有点基于观点,但是,因为你问的是带有死区的PWM,我会用一个例子来回答,并指出我在你的代码中看到的IMHO是糟糕的做法。

你对PWM_H的赋值就是一个很好的例子,你有一个IF和ELSE IF来设置PWM_H,你写PWM_L的方式不是很好,这种风格可能会导致合成错误。如果两个独立的if赋值相同的变量,如果这两个IF恰好同时为真,则可能会出现多驱动问题。你可能认为/知道事实并非如此,但不要去做。如果合成器检测到这一点,它很可能会抛出一个错误。取而代之的是重写IF和ELSE IF,就像对PWM_H所做的那样。

接下来,我得到了reg counter=0将为模拟重置计数器,但显然不是为了合成。这将在您的情况下工作,因为您使用的是完整的计数,并且它实际上将是一个非常快速的合成计数器。

我在下面写了一个例子,并使用了参数。这只是一个个人选择,但如果你以后想要调整的话,这确实会让事情变得很酷。我有一些额外的代码,因为当我模拟它时,我发现在偏移量设置的极端处发生了糟糕的事情。

与您的代码非常相似,我的PWM_L比PWM_H稍微复杂一些,但请注意,我将它放在一条语句中,而不是两条语句中,因此不可能实现多驱动程序。

代码语言:javascript
运行
复制
module pwm_db
    (input clk,
     input reset,
     input [9:0] offset,
     output pwm_l,
     output pwm_h
     );

    reg [9:0] counter = 0;
    reg [9:0] proc_offset;  
    reg pwm_ld;
    reg pwm_hd;

    parameter COUNTER_MAX = 1024-1;
    parameter DEADBAND_WIDTH = 16;
    parameter DB_X2 = DEADBAND_WIDTH * 2;
    parameter COUNTER_DB = COUNTER_MAX - DEADBAND_WIDTH;
    
    // Limit the offset internally to keep the deadband from being over written
    // Burning some registers for this to increase final synthesis speed.
    always @ (posedge clk)
    begin
    proc_offset <= (offset >= DB_X2) && (offset <= COUNTER_MAX - DB_X2) ? offset :
                      offset < DB_X2                                      ? DB_X2  : COUNTER_MAX - DB_X2; 
    end


    always @ (posedge clk)
        begin
            counter <= counter + 10'h001;
            pwm_hd <= counter <  proc_offset - DEADBAND_WIDTH;  // on initially and turn off a DB width prior to offset
            pwm_ld <= counter > proc_offset && counter < COUNTER_DB; // on at offset and off DW width prior to max count;
        end
    assign pwm_h = pwm_hd;
    assign pwm_l = pwm_ld;
    
endmodule
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65133267

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档