1
votes

I'm attempting to write a general-purpose Verilog latch module with width and delay parameters (delay for synchronization/CDC purposes). At first I wanted to generate a number of delay registers based on the delay parameter, but I decided instead to simply have one shift register, sized according to the delay, as I believe it's cleaner. The code is as follows:

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 has no problem with this, even when instantiated with DELAY = 0. However, Vivado synthesis returns:

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

when this module is instantiated with DELAY = 0. How would you get around this? I thought I might be able to get away with defining a max macro and setting the top index of the register to max(0, (WIDTH*(DELAY-1))-1), but of course that gets rejected as a variable width register. Is it possible to conditionally declare registers based on parameters?

2

2 Answers

1
votes

Yes, you can conditionally declare registers using a generate if construct.

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
1
votes

You can try a generate if statement to conditionally declare the registers:

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

The generate keyword is optional. Refer to IEEE Std 1800-2017, section 27. Generate constructs