Search code examples
verilogsystem-veriloghdl

Best way to optionally register inputs


I have a systemverilog module with a LOT of input signals of varying sizes. I want to optionally register them before use. Here is my desired criteria for the code that does this optional registering:

  1. I should only need to write out the assignments once (no duplicate code)
  2. I should not need to use any macros (I don't want scoping issues)

Here's a minimal reproducible example of my current solution:

module optional_register #(
  parameter bit REGISTER_INPUTS=1
)(
  input wire clk,
  
  input wire a_in,
  input wire b_in,
  input wire c_in,
  input wire d_in,
  
  output logic a_out,
  output logic b_out,
  output logic c_out,
  output logic d_out
    );

  function assign_inputs();
    a_out <= a_in;
    b_out <= b_in;
    c_out <= c_in;
    d_out <= d_in;
  endfunction

generate if (REGISTER_INPUTS) begin
  always_ff @ (posedge clk)
    assign_inputs();
end else begin
  always_comb
    assign_inputs();
end endgenerate

endmodule

This code synthesizes correctly in Vivado 2020.2 with both the registers on and off. But I am worried that the non-blocking assignments in the function are technically invalid, according to The IEEE Std for Verilog (1364-2001), section "10.3.4 Function rules" which states:

A function shall not have any nonblocking assignments.

So my concern is that this won't work in other synthesizers, and may cause unexpected behavior in simulation. Can anyone speak to this?

Any other ideas?


Solution

  • This is SystemVerilog code, you should be using the IEEE 1800-2017 LRM.

    Nonblocking assignments are allowed inside function as long as LHS target is not a variable with an automatic lifetime. Do not use NBA to assign to argument outputs or the return value of a function with a static lifetime because their current values get copied out before the NBA updates happens.

    You should declare your function with no return value.

    function void assign_inputs();
    

    Using NBAs in combinational logic is not the best for simulation performance, but is usually OK functionality wise.