1

I am trying to implement a fitness evaluation function in Verilog called Rosenbrock function (https://en.wikipedia.org/wiki/Rosenbrock_function). The issue I am facing is that if I use the following code it gives me a undefined state since there are 4 drivers to the wire fitness_val.

module test_module1 ( x, fitness);
    input   [4*2 -1:0]  x;  
    output  [1:0]   fitness;

    wire [1:0] x_i;
    wire [1:0] x_im1;
    wire [3:0] fitness_val;
    wire [3:0] a;
    wire [3:0] b;
    wire [1:0] x_array1 [3:0];
    
    genvar k;
        assign fitness = fitness_val;
        genvar j;
    
        generate
        for (j =0 ; j <4 ; j = j+1) begin
                assign x_array1[j] = x[2*j +: 2];
        end
                for (k=1; k<4; k=k+1) begin
                    assign x_i      = x_array1[k];
                    assign x_im1    = x_array1[k-1];
                    assign a = 100*(x_i[1:0] - x_im1[1:0])*(x_i[1:0] - x_im1[1:0]);
                    assign b = (1 - x_im1[1:0])*(1 - x_im1[1:0]);
                    assign fitness_val = fitness_val + a[2:1] + b[2:1];
            end
        endgenerate
endmodule

module tb_tm1();
  wire  [1:0]   fitness;
  wire [4*2-1:0] x_array;
  test_module1 tm1(x_array, fitness);
  assign x_array = 8'b11100100;
endmodule

However if I expand the for loop in this format, I get a valid output.

assign fitness_val = 100*(x_array1[1] - x_array1[0])*(x_array1[1] - x_array1[0]) + (1 - x_array1[0])*(1 - x_array1[0]) 
+ 100*(x_array1[2] - x_array1[1])*(x_array1[2] - x_array1[1]) + (1 - x_array1[1])*(1 - x_array1[1])
+ 100*(x_array1[3] - x_array1[2])*(x_array1[3] - x_array1[2]) + (1 - x_array1[2])*(1 - x_array1[2]);

Is there a way to implement this recursively in Verilog?

1 Answers1

1

assign statements run concurrently; not sequentially. Generate loops are static unrolled during elaborations. When two assign statements drive different values to the same net, the result will be x.

To do sequential operations you will need to an always block.

Minimum change as follows (plus ANSI style header):

module test_module1 (
    input   [4*2 -1:0]  x,
    output  [1:0]   fitness ); // <-- ANSI style header

    reg  [1:0] x_i; // 'always' block assign 'reg' type
    reg  [1:0] x_im1;
    reg  [3:0] fitness_val;
    reg  [3:0] a;
    reg  [3:0] b;
    wire [1:0] x_array1 [3:0]; // 'assign' drives 'wire' type
    
    interger k; // index for loop in an always block
    genvar j;   // index for a generate loop
    assign fitness = fitness_val;
    
    generate
        for (j =0 ; j <4 ; j = j+1) begin
            assign x_array1[j] = x[2*j +: 2];
        end
    endgenerate
    
    always @* begin // @* is auto-sensitivity, use for combination logic
        fitness_val = 4'b0000; // initial value, otherwise it infers a latch
        for (k=1; k<4; k=k+1) begin
            x_i      = x_array1[k];
            x_im1    = x_array1[k-1];
            a = 100*(x_i[1:0] - x_im1[1:0])*(x_i[1:0] - x_im1[1:0]);
            b = (1 - x_im1[1:0])*(1 - x_im1[1:0]);
            fitness_val = fitness_val + a[2:1] + b[2:1];
        end
    end
endmodule

FYI: 4-bits is not enough to hold the value decimal 100. Do Do you want to make it bigger you did you intend the 100 to represent 4 in binary (4'b0100)?

Greg
  • 18,111
  • 5
  • 46
  • 68