Magic square on system verilog

Hi,

I am trying to write a program where the rows, columns, and diag of the matrix should be equal to 15. when i enabled the first contraint it seems i am getting some random value instead of 15 any idea why?

// Code your design here

class magicsquare;
  
  rand bit [7:0] a [0:2][0:2];
  
  int i,j,k;
  
  constraint c1 {foreach (a[i,j]) 
    
    if (j==0) {a[i].sum() ==8'd15; } }
  
  function void display ();
                 $display ("The value of array is %p",a);
  endfunction
  
endclass

module test;
  magicsquare m1;
  
  
  initial begin
    m1=new ();
    m1.randomize();
    m1.display();
    
  end
  
endmodule

In reply to rag123:

See Constraint Randomization | Verification Academy

In reply to dave_59:

Hi Dave,

I modified the code, but i dont see rows 2 and 3 is equal to 15.

// Code your design here

class magicsquare;
  
  rand bit [7:0] a [0:2][0:2];
  rand bit [7:0] b [0:2][0:2];
  
  int i,j,k;
  
  constraint c1 {foreach (a[i,j]) 
    
  if (i==0)  {a.sum() with (int'(item)) ==8'd15; } }
      
      constraint c2 {foreach (a[i,j])
    
        if (i==1){ a.sum() with (int'(item)) == 8'd15 ;}}
      
    
      
   //   constraint c2 {foreach (a[i,j]) 
    
     //   if (i==0) {a.sum() with (int'(item)) ==8'd15; } }
  
  function void display ();
                 $display ("The value of array is %p",a);
                    
  endfunction
  
endclass

module test;
  magicsquare m1;
  
  
  initial begin
    m1=new();
    m1.randomize();
    m1.display();
    
  end
  
endmodule

Expected output:

2   7   6
  9   5   1
  4   3   8

In reply to rag123:

I believe you want

constraint c1 {foreach (a[i,])
 if (i==0||i==1){ a[i].sum() with (int'(item)) == 8'd15 ;}

In reply to dave_59:

class magicsquare;

rand bit [7:0] a [0:2][0:2];

int i,j,k;

constraint c1 {foreach (a[i,])

if (i==0||i==1||i==2){ a[i].sum() with (int'(item)) == 8'd15 ;}}
  
constraint c2 {foreach (a[i,j]) 

    if (j==0||j==1||j==2){ a[j].sum() with (int'(item)) == 8'd15 ;}}
  
 //     constraint c3 {foreach (a[i!=j]) 

 //     { a[i!=j].sum() with (int'(item)) == 8'd15 ;}}

function void display ();
$display (“The value of array is %p”,a);
endfunction

endclass

program test;
magicsquare m1;

initial begin
m1=new();
m1.randomize();
m1.display();

end

endprogram

The value of array is ‘{’{'h8, 'h1, 'h6}, '{'h3, 'h5, 'h7}, '{'hf, 'h0, 'h0}}

Thanks Dave. This satisfies the row constraints, but some how the column constraint is not satisfied. Also i need the sum of elements 00,11,22 to be 15 as well. I tried something like this, but it doesnt seem to compile.

constraint c3 {foreach (a[i!=j])

     { a[i!=j].sum() with (int'(item)) == 8'd15 ;}}
constraint c {
  a.sum() with (item.index(1)==0 ? item : 0) == 15;//row0
  a.sum() with (item.index(1)==1 ? item : 0) == 15;//row1
  a.sum() with (item.index(1)==2 ? item : 0) == 15;//row2
  a.sum() with (item.index(2)==0 ? item : 0) == 15;//col0
  a.sum() with (item.index(2)==1 ? item : 0) == 15;//col1
  a.sum() with (item.index(2)==2 ? item : 0) == 15;//col2
  a.sum() with (item.index(1) == item.index(2) ? item : 0) == 15; //diag1
  a.sum() with ((item.index(1) + item.index(2) == 2) ? item : 0) == 15; //diag2
}
1 Like

In reply to sam33rs:

I see syntax errors with this code.
Is it working for you?

a.sum() with (item.index(1)==0 ? item : 0) == 15;//row0

Error - This type is illegal in this context [SystemVerilog].

Regards,
Naveen

In reply to naveensv:

Works for me.

In reply to sam33rs:

constraint c {
a.sum() with (item.index(1)==0 ? item : 0) == 15;//row0
a.sum() with (item.index(1)==1 ? item : 0) == 15;//row1
a.sum() with (item.index(1)==2 ? item : 0) == 15;//row2
a.sum() with (item.index(2)==0 ? item : 0) == 15;//col0
a.sum() with (item.index(2)==1 ? item : 0) == 15;//col1
a.sum() with (item.index(2)==2 ? item : 0) == 15;//col2
a.sum() with (item.index(1) == item.index(2) ? item : 0) == 15; //diag1
a.sum() with ((item.index(1) + item.index(2) == 2) ? item : 0) == 15; //diag2
}

You can further simplify with a loop:


class magicsquare;
 
  rand bit [7:0] a [0:2][0:2];
 
  int i,j,k;
 
  constraint c1 {

        foreach(a[i,j]) {
            a.sum with (item.index(1) == i ? int'(item): 0) == 15; // rows
            a.sum with (item.index(2) == j ? int'(item): 0) == 15; // cols
        }
        a.sum with (item.index(1) == item.index(2) ? int'(item) : 0) ==15; // diag1
        a.sum with ( (item.index(1) + item.index(2)==2) ? int'(item) : 0) ==15; // diag2
  }
 
  function void display ();
                 $display ("The value of array is %p",a);
  endfunction
 
endclass

1 Like

I tried a different approach that involves matrix transpose. Its definitely much lengthier than the solutions described here, but this solution might scale better than the solution described above.

class magic_square#(int grid_size=4);
  rand bit[4:0] rand_array[grid_size][grid_size];
  rand bit[4:0] rand_array_transpose[grid_size][grid_size];
  rand bit[4:0] diagonal_0[grid_size];
  rand bit[4:0] diagonal_1[grid_size];
  rand int unsigned rand_sum;

  constraint magic_square_cnstr {
    rand_sum >= 0;
    rand_sum <= 8'hFF;
                                  
    foreach(rand_array[i]) {
      unique{rand_array[i]};
      rand_array[i].sum() with (int'(item)) == rand_sum;
    }

    foreach(rand_array[i,j]) {
      rand_array_transpose[j][i] == rand_array[i][j];
      if (i==j) {
        diagonal_0[i] == rand_array[i][j];
      }
      if ((i+j) == grid_size-1) {
        diagonal_1[i] == rand_array[i][j];
      }
    }

    foreach(rand_array_transpose[i]) {
      unique{rand_array_transpose[i]};
      rand_array_transpose[i].sum() with (int'(item)) == rand_sum;
    }

    foreach(rand_array[i,j]) {
      foreach(rand_array[i1,j1]) {
        if ((i!=i1) && (j!=j1)) {
          rand_array[i][j] != rand_array[i1][j1];
        }
      }
    }
    diagonal_0.sum() with (int'(item)) == rand_sum;
    diagonal_1.sum() with (int'(item)) == rand_sum;                            
  }

  function post_randomize();
    string row_print;
    $display("Solving for grid_size:0x%0x sum:0x%0x", grid_size, rand_sum);
    foreach (rand_array[row]) begin
      row_print = {row_print,$sformatf("%p \n", rand_array[row])};
    end
    $display ("%s", row_print);
  endfunction // post_randomize
    
  endclass // magic_square
  
module magic_square();

initial begin
  magic_square #(4) ms = new();
  assert(ms.randomize());
  
end
  
endmodule // magic_square

In reply to sam33rs:

class matrixsum;

rand bit [7:0] a [0:2][0:2];

int i,j,k;

constraint c1 {
foreach(a[i,j]) {
a.sum with (item.index(1) == i ? int’(item): 0) == 15; // rows
a.sum with (item.index(2) == j ? int’(item): 0) == 15; // cols
}
a.sum with (item.index(1) == item.index(2) ? int’(item) : 0) ==15; // diag1
a.sum with ((item.index(1) + item.index(2)==2) ? int’(item) : 0) ==15; // diag2
}

function void display ();
$display (“The value of array is %p” , a);
endfunction

endclass
module test;
matrixsum m1;

initial begin
repeat(3) begin
m1=new();
m1.randomize();
m1.display();
end
end

endmodule

Here in bold syntax. what’s the requirement? and how it will work? I want to know the logic behind that 4 syntaxes. but why another value other than 12 and 15 is not applicable to get the sum as that replaced value of 15 in this code.

here, whats use of item.index(1) == item.index(2) and (item.index(1) + item.index(2)==2 and

    a.sum with (***item.index(1) == i ? int'(item): 0***) == 15; // rows
    a.sum with (***item.index(2) == j ? int'(item): 0***) == 15; // cols

 a.sum with ( ***item.index(1) == item.index(2) ? int'(item) : 0***) ==15; // diag1
 a.sum with ( ***(item.index(1) + item.index(2)==2) ? int'(item) : 0***) ==15; // diag2

here, why only index(1) & index(2) is taken why not others else ? give me satisfactory answers of my questions.

In reply to Bansari Patel:

Because the matric is 2 dimensional. Here index(1) refers to row and index(2) refers to column

Hi prasadaddagarla,

When I extended for 4x4 matrix all satisfies except diag1

{'{'h5, 'h3, 'h3, 'h4}, '{'h0, 'h7, 'h5, 'h3}, '{'h5, 'h3, 'h1, 'h6}, '{'h5, 'h2, 'h6, 'h2}}

How can we generalise this for nxn matrix?

Thanks !!!

In reply to UVM_geek:

The previous solutions are wrong. See 2D array constraint randomization | Verification Academy

The correct solution is

class magicsquare;
  
  parameter int N = 4;
 
  rand bit [7:0] a [N][N];
  
  constraint c1 {
    foreach(a[i,j]) {
      a[i].sum(row) with (int'(row)) == 15; // rows
      a.sum(row) with (row.sum(col) with (col.index == j  ? int'(col) : 0))== 15; // cols
    }
      a.sum(row) with (row.sum(col) with (row.index==col.index ? int'(col) : 0 )) == 15; // diag1
    a.sum(row) with (row.sum(col) with (($size(a)-row.index-1)==col.index ? int'(col) : 0)) == 15; // diag2
  }
 
  function void display ();
    $display ("The value of array is");
    foreach(a[i]) $display("%p = ",a[i], a[i].sum(row) with (int'(row)));
    foreach(a[,j]) $write("%3d ",a.sum(row) with (row.sum(col) with (col.index == j  ? int'(col) : 0)));
    $display("\ndiag1 = ", a.sum(row) with (row.sum(col) with (row.index==col.index ? int'(col) : 0)));
    $display("diag2 = ",  a.sum(row) with (row.sum(col) with (($size(a)-row.index-1)==col.index ? int'(col) : 0)));
  endfunction
 
endclass
 
module test;
  magicsquare m1;
 
 
  initial begin
    m1=new();
    assert (m1.randomize());
    m1.display();
 
  end
 
endmodule

Thank you so much DAVE !!!

Hi Dave,

I tried your solution in simulator to understand: a.sum(row) with (row.sum(col)
and it give error saying col not defined.

Error-[IND] Identifier not declared
testbench.sv, 10
Identifier ‘col’ has not been declared yet. If this error is not expected,
please check if you have set `default_nettype to none.
Instance stack trace:
$unit /apps/vcsmx/vcs/S-2021.09//etc/uvm-1.2/src/uvm.sv, 1

Error-[IND] Identifier not declared
testbench.sv, 10
Identifier ‘col’ has not been declared yet. If this error is not expected,
please check if you have set `default_nettype to none.
Instance stack trace:
$unit /apps/vcsmx/vcs/S-2021.09//etc/uvm-1.2/src/uvm.sv, 1

In reply to curious_verifier:

Please see 2D array constraint randomization | Verification Academy

the above link is not working : " Oops! That page doesn’t exist or is private."

There was a bug in the forum software we are using that has been addressed. Please refresh this page before clicking on the link