verilog,提高PWM的速度

verilog,提高PWM的速度,verilog,Verilog,我试图设计一个PWM+死区,在250MHz的输入时钟下工作。 (我需要大约250KHz的PWM频率,用于定制降压调节器) 这就是我到目前为止使用Lattice中的IceCube2,使用iCE40LP1K设备实现的。 获得的最大频率(模拟)在最坏情况下为142 MHz,在最佳情况下为260 MHz(-40度) 我想知道对于包含互补输出死区的PWM发生器来说,这是否是正确的方法,或者换句话说,这是否可以进一步改进 module top( input clk_16, input [9:0] d

我试图设计一个PWM+死区,在250MHz的输入时钟下工作。 (我需要大约250KHz的PWM频率,用于定制降压调节器)

这就是我到目前为止使用Lattice中的IceCube2,使用iCE40LP1K设备实现的。 获得的最大频率(模拟)在最坏情况下为142 MHz,在最佳情况下为260 MHz(-40度)

我想知道对于包含互补输出死区的PWM发生器来说,这是否是正确的方法,或者换句话说,这是否可以进一步改进

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
模块顶部(
输入时钟16,
在中输入[9:0]数据,
输出调节PWM_H,
输出调节脉宽调制
);
reg[9:0]比较;
reg[9:0]计数器=0;
始终@(posedge PLLOUTCORE)
开始

比较这是一个有点开放性的问题,有点基于观点,但是,因为你问的是带死区的PWM,我将用一个例子来回答,并指出我在你的代码中看到的一些错误做法

您分配的PWM_H是一个很好的例子,您有一个IF和一个ELSE IF设置PWM_H。您编写PWM_L的方式没有那么好,这种方式可能会导致合成错误。如果两个独立的IF同时为同一变量赋值,则可能会出现多个驱动因素问题。你可能认为/知道情况并非如此,但不要这样做。如果合成器检测到这一点,它将有希望抛出一个错误。相反,像为PWM_H所做的那样,重新编写IF和ELSE IF

接下来,我得到reg counter=0将为模拟重置计数器,但显然不是为合成重置计数器。这在你的例子中是有效的,因为你使用的是全计数,它实际上是一个非常快速的合成计数器

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

与您的代码非常相似,我的PWM_L比PWM_H稍微复杂一点,但请注意,我将它放在一个语句中,而不是两个语句中,因此不可能有多个驱动器

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
模块pwm\u db
(输入时钟,
输入复位,
输入[9:0]偏移量,
输出pwm_l,
输出脉宽调制
);
reg[9:0]计数器=0;
reg[9:0]程序偏移量;
注册脉宽调制;
reg pwm_hd;
参数计数器_MAX=1024-1;
参数死区宽度=16;
参数DB_X2=死区宽度*2;
参数COUNTER_DB=COUNTER_MAX-死区宽度;
//在内部限制偏移量,以防止死区被过度写入
//为此燃烧一些寄存器以提高最终合成速度。
始终@(posedge clk)
开始

proc_offset=DB_X2)&&(offset我不认为“如果两个独立的IF同时为同一个变量赋值,那么可能会出现多个驱动程序问题。”第二个赋值将简单地覆盖第一个赋值。如果该语句使用了阻塞赋值,那可能是真的,但在这种情况下,我认为你链接到的“光子”的答案是胡说八道。(我想我会加入“电子学”来这么说。)非阻塞分配不是并行执行的。看起来可能是这样,但事实并非如此。请参阅。这是关于VHDL的,但是一个VHDL信号分配运算符(
PWM\u H
PWM\u L
都是由1位FSM驱动的。如果要分离出
始终
块,您会看到这一点。但是
PWM\u H
的FSM使用相等运算符(
=
),而
PWM\u L
的FSM使用比较运算符(