2
\$\begingroup\$

I have been trying to run this Verilog code which simulates traffic decongestion, but I am getting this error. I have also tried to use an always block, but I am still not able to resolve it. Following are my design and testbench files in that order.

// main module

module test2(v1, v2, v3, v4, v5, h, l, lane_no);

input v1, v2, v3, v4, v5, h, l;
output[1 : 0] lane_no;

wire local;
wire x1, x2, p;
wire e3, e2, e1;

assign local = v1 & v2 & v3;
wire[2 : 0] count1 = 3'b000;
wire[2 : 0] count2 = 3'b000;

wire a1, a2, a3, b1, b2, b3;
assign a1 = count1[0];
assign a2 = count1[1];
assign a3 = count1[2];
assign b1 = count2[0];
assign b2 = count2[1];
assign b3 = count2[2];

if (local) begin      // This is Line 26 (see error messages)
    assign lane_no = 2'b11;
end
else
begin
    assign e3 = ~(a3^b3);
    assign e2 = ~(a2^~b2);
    assign e1 = ~(a1^~b1);
    assign x1 = (~a3 & b3) + (e3 & ~a2 & b2) + (e3 & e2 & ~a1 & b1);
    assign x2 = ~x1;
    assign p = e3 & e2 & e1;

    if (p == 1)
    begin
        if (count1 == 3'b000)
        begin
            assign lane_no = 2'b01;
            assign count1 = count1 + 3'b001;
            assign count1 = count1 - 3'b001;
        end
    end
end

endmodule

I am getting this error when I execute the following command:

harshal@dl8-OptiPlex-9010:~/Desktop$ iverilog test.v testbench.v 
test.v:26: error: Unable to bind parameter `local' in `main.dut'
test.v:26: error: Cannot evaluate genvar conditional expression: 
local
test.v:26: error: Unable to bind parameter `local' in `main.dut'
test.v:26: error: Cannot evaluate genvar conditional expression: 
local
4 error(s) during elaboration.
module main;
    reg v1,v2,v3,v4,v5,h,l;
    wire[2:0] lane_no;
    test2 dut(v1,v2,v3,v4,v5,h,l,lane_no);
    
    initial begin
        v1=1;v2=1;v3=1;v4=0;v5=0;h=1;l=0;
        #10 v1=1;v2=0;v3=1;v4=0;v5=0;h=1;l=0;
        #10 v1=1;v2=1;v3=0;v4=0;v5=0;h=0;l=1;
    end

    initial begin
        $monitor("  output= %b%b%b",lane_no);
    end
endmodule

I am not able to figure out the exact error as I am beginner in Verilog programming.

\$\endgroup\$
1
  • \$\begingroup\$ Can you add the code with always block and error messages for the code with always block? \$\endgroup\$ Commented Jan 5, 2023 at 6:19

2 Answers 2

2
\$\begingroup\$

When the Verilog compiler sees an if/else which is not inside an always block, it assumes the code is a generate construct. It expects the if conditional expression to be a constant, which means it expects local to be a parameter, for example. However, you declared local to be a variable type (wire). This explains the error message you received. Refer to IEEE Std 1800-2017, section 27. Generate constructs.

It is possible to place the if/else code inside an always block, but other changes are needed as well. All signals assigned inside the always procedural block should be declared as reg, not wire. Also, there is no need for the assign keyword in the always block.

module test2(v1,v2,v3,v4,v5,h,l,lane_no);
   input v1,v2,v3,v4,v5,h,l;
   output reg [1:0] lane_no;
   wire             local;
   reg              x1,x2,p;
   reg              e3,e2,e1;

   assign local=v1&v2&v3;
   reg [2:0]        count1=3'b000;
   reg [2:0]        count2=3'b000;

   wire             a1,a2,a3,b1,b2,b3;
   assign a1=count1[0];
   assign a2=count1[1];
   assign a3=count1[2];

   assign b1=count2[0];
   assign b2=count2[1];
   assign b3=count2[2];

   always @* begin
      if(local) begin
         lane_no= 2'b11;
      end else
        begin
           e3=~(a3^b3);
           e2=~(a2^~b2);
           e1=~(a1^~b1);

           x1=(~a3&b3)+(e3&~a2&b2)+(e3&e2&~a1&b1);
           x2=~x1;
           p=e3&e2&e1;
           if(p==1) begin
              if(count1==3'b000)
                begin
                   lane_no=2'b01;
                   count1=count1+3'b001;
                   count1=count1-3'b001;
                end
           end
        end
   end
endmodule

I used emacs Verilog-mode to reformat the code using reasonable indentation.

This code compiles without errors for iverilog.


Note that local is now a keyword for SystemVerilog (IEEE Std 1800). Apparently, it has not yet been implemented with iverilog, but I recommend you change local to something else like local1.

\$\endgroup\$
0
1
\$\begingroup\$

Your problem lies in the use of if-else statements otside of a procedural block (always, etc).

Your code below will not work:

if(local) begin 
assign lane_no= 2'b11;
end

else
begin

assign e3=~(a3^b3);
...

You need to think about what the code will describe in terms of hardware, as this is not a programming language, but a hardware description language.

Here you say "if signal local is high, add some circuitry to set lane_no. Otherwise, remove that circuitry and add some other circuitry to assign e3 etc.". This can't work because the hardware must be fixed once synthesis is complete - you can't suddenly add extra circuitry at run time.

To use if-else you should switch to using always blocks and =/<= rather than assign (note that this will require the target variables to be reg rather than wire):

reg x;
always @ (trigger) begin
    if (condition) begin
        x <= val_if_true;
    end else begin
        x <= val_if_false;
    end
end

In other cases you can use the ternary operator with assign statements if appropriate:

assign x = (condition) ? val_if_true : val_if_false;

I would suggest going back to basics and finding a tutorial on how to program in Verilog. This is one that I found quite useful way back when I was learning Verilog.

\$\endgroup\$

Your Answer

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