如何编写参数化延迟寄存器?

How do you write a parameterized delay register?

我正在尝试编写具有宽度和延迟参数的通用 Verilog 锁存器模块(延迟用于 synchronization/CDC 目的)。起初我想根据延迟参数生成多个延迟寄存器,但我决定只使用一个移位寄存器,根据延迟调整大小,因为我认为它更简洁。代码如下:

module latch # (
    parameter WIDTH = 32,
    parameter DELAY = 0
  )
  (
    input                  clk,
    input                  resetn,
    input [WIDTH-1:0]      din,
    output reg [WIDTH-1:0] dout
  );

  reg [(WIDTH*(DELAY))-1:0] dly;

  always @ (posedge clk)
  begin
    if (!resetn)
    begin
      dly  <= 0;
      dout <= 0;
    end
    else
    begin
      if (DELAY == 0)
      begin
        dout <= din;
      end
      else
      begin
        dly  <= {dly[(WIDTH*(DELAY-1))-1:0], din};
        dout <= dly[(WIDTH*(DELAY))-1 -: WIDTH];
      end
    end
  end

endmodule

xvlog 对此没有问题,即使使用 DELAY = 0 实例化也是如此。然而,Vivado 综合 returns:

ERROR: [Synth 8-524] part-select [-1:0] out of range of prefix 'dly'

当此模块用 DELAY = 0 实例化时。你会如何解决这个问题?我以为我可以定义一个最大宏并将寄存器的顶部索引设置为 max(0, (WIDTH*(DELAY-1))-1),但当然这会被拒绝为可变宽度寄存器。是否可以根据参数有条件地声明寄存器?

您可以尝试使用 generate if 语句来有条件地声明寄存器:

module latch # (
    parameter WIDTH = 32,
    parameter DELAY = 0
  )
  (
    input                  clk,
    input                  resetn,
    input [WIDTH-1:0]      din,
    output reg [WIDTH-1:0] dout
  );

  if (DELAY == 0)
  begin

    always @ (posedge clk)
    begin
      if (!resetn)
      begin
        dout <= 0;
      end
      else
      begin
        dout <= din;
      end
    end

  end
  else if (DELAY == 1)
  begin

    reg [WIDTH-1:0] dly;

    always @ (posedge clk)
    begin
      if (!resetn)
      begin
        dly  <= 0;
        dout <= 0;
      end
      else
      begin
        dly  <= din;
        dout <= dly;
      end
    end

  end
  else
  begin

    reg [(WIDTH*(DELAY))-1:0] dly;

    always @ (posedge clk)
    begin
      if (!resetn)
      begin
        dly  <= 0;
        dout <= 0;
      end
      else
      begin
        dly  <= {dly[(WIDTH*(DELAY-1))-1:0], din};
        dout <= dly[(WIDTH*DELAY)-1 -: WIDTH];
      end
    end
  end

endmodule

generate 关键字是可选的。请参阅 IEEE 标准 1800-2017,第 27 节。生成构造

是的,您可以使用生成 if 构造有条件地声明寄存器。

module latch # (
    parameter WIDTH = 32,
    parameter DELAY = 0
  )
  (
    input                  clk,
    input                  resetn,
    input [WIDTH-1:0]      din,
    output reg [WIDTH-1:0] dout
  );

if (DELAY==0) begin
   dout <= din;
end else begin 
  reg [(WIDTH*(DELAY))-1:0] dly;

  always @ (posedge clk)
  begin
    if (!resetn)
    begin
      dly  <= 0;
      dout <= 0;
    end
    else
    begin
      if (DELAY == 0)
      begin
        dout <= din;
      end
      else
      begin
        dly  <= {dly[(WIDTH*(DELAY-1))-1:0], din};
        dout <= dly[(WIDTH*(DELAY))-1 -: WIDTH];
      end
    end
  end
end

endmodule