1
\$\begingroup\$

I encountered something weird in a Verilog code, and I have doubts about it.

Someone used a function in Verilog in the following way:

Pipe #(.W($bits(Data))) MetaO (Clock, MyFunc(DataIn, I0, I1), DataOut);
function [DATA_SIZE-1:0] MyFunc (input [DATA_SIZE-1:0] DataIn, input I0, input I1);
  MyFunc    = DataIn;
  MyFunc[1] = X;
  if(I0) begin
    MyFunc[2]  = Y;
    MyFunc[3]  = K;
    MyFunc[4]  = I1;
end endfunction

So, what he tried to do here is to pipe DataIn to DataOut,
but to manipulate DataIn bits before the pipe, so he used function as the input to the Input port of the pipe.

My doubts are in the function itself.
He first of all kind of initialized MyFunc with DataIn,
and then in the following lines, assigns different values in the other bits depending on some stuff.

Because it's eventually combinatorial logic, I ask myself if it's a correct way to write Verilog.

Doesn't it create a race condition on some of these bits?
Can it make timing issues eventually?

What is another better way to write the same combinatorial logic?

\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

Doesn't it create a race condition on some of these bits?

No, there is no race condition between the bits. As you mentioned, the function is used to model combinational logic. It correctly uses blocking assignments (=).

Can it make timing issues eventually?

No, there are no timing issues. The function explicitly sets 4 bits of MyFunc: 1-4. But, all bits of MyFunc are set by the initialization line, no matter how big DATA_SIZE is:

MyFunc    = DataIn;

Since there are assignments to all bits, this avoids inferring unintended latches.

What is another better way to write the same combinatorial logic?

Another way (not necessarily better) is:

always_comb begin
    MyFunc    = DataIn;
    MyFunc[1] = X;
    if (I0) begin
        MyFunc[2] = Y;
        MyFunc[3] = K;
        MyFunc[4] = I1;
    end
end

You would replace MyFunc with another signal name.

One advantage of the function is that it can be called many times in the code without duplicating the 9 lines of code above and with a different set of input signals.

\$\endgroup\$
3
  • \$\begingroup\$ so, the synthesizer in Verilog reads always_comb and function line by line from the first line and on? I imagined that all the lines inside the always_comb and function implemented in parallel. \$\endgroup\$ Commented Mar 6 at 12:57
  • \$\begingroup\$ @MichaelRahav: The assignments all occur during the same time step in simulation, but they occur in the order that you wrote in the code since you use the blocking assignment operator (=). \$\endgroup\$
    – toolic
    Commented Mar 6 at 13:02
  • \$\begingroup\$ OK good to know, thanks! \$\endgroup\$ Commented Mar 6 at 13:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.