Constrain block to allocate dedicated non over-lapping address range space for 16 masters

Hi,

I am looking to generate non over-lapping 4K address range to each master.

For eg: say if the processor has 64KB of memory which should be assigned to different slaves. If I have 4 slaves each taking 4K addresses, I can assign 0 to 4K-1 for slave 1, 4k to 8k-1 to slave 2 and so on. But the address range 3k to 5k will be invalid because it is overlapping with slave 1.

The same way if I want to create 4K address range to 16 masters without overlapping, I am trying to write the constraint but so far I succeeded only getting a code below which generates unique addresses for each master as shown below.

class address;
  randc bit [3:0] addr;
  randc bit [3:0] N;
endclass


module allocation;
    initial begin
       address addr_handle;
       addr_handle = new();
      
      repeat(16) begin
        addr_handle.randomize();        
        $display("\t %4b address allocated for %0d master", addr_handle.addr, addr_handle.N);
        end
    end
endmodule

Can somebody please help me how to write the constraint to generate 4k address range for 16 masters.

Thanks,
Sruthi.

In reply to sruthikrapa:

Try this

class address;
   int N = 16;
   int memRange = 'h1000;
   int memLimit = 'h400_0000;
   rand bit [26:0] addrs[];
   function new;
      addrs = new[N];
   endfunction

   constraint c{
		foreach(addrs[S]) if (S != N-1)
		   addrs[S] + memRange < addrs[S+1];
		else
		   addrs[S] + memRange < memLimit;
		}
		
endclass

In reply to sruthikrapa:
For master to generate the different 4k address based on its Master number. You should use rand as variable instead of randc. You should also make sure that master address is aligned to its access boundary . In the below code its aligned 4 bytes boundary. You can change to your requirement. For 4K address space you ll need at least 12 bits.



class address;
  rand bit [15:0] addr;
  rand bit [3:0] N;
  
  constraint c_addr {
    (N ==0) -> (addr inside {[0:'h1000]} ) ;
    (N ==1) -> (addr inside {['h1001:'h2000]} );
    (N ==2) -> (addr inside {['h2001:'h3000]} );
    (N ==3) -> (addr inside {['h3001:'h4000]} );
    (N ==4) -> (addr inside {['h4001:'h5000]} );
    (N ==5) -> (addr inside {['h5001:'h6000]} );
    (N ==6) -> (addr inside {['h6001:'h7000]} );
    (N ==7) -> (addr inside {['h7001:'h8000]} );
    (N ==8) -> (addr inside {['h8001:'h9000]} );
    (N ==9) -> (addr inside {['h9001:'ha000]} );
    (N ==10) -> (addr inside {['ha001:'hb000]} );
    (N ==11) -> (addr inside {['hb001:'hc000]} );
    (N ==12) -> (addr inside {['hc001:'hd000]} );
    (N ==13) -> (addr inside {['hd001:'he000]} );
    (N ==14) -> (addr inside {['he001:'hf000]} );
    (N ==15) -> (addr inside {['hf001:'h10000]} );
    
    solve N before addr ;

  }
  
  constraint c_addr_aligned {
    addr%4 == 0 ;
  }
  
endclass
 
 
module allocation;
    initial begin
       address addr_handle;
       addr_handle = new();
 
      repeat(16) begin
        addr_handle.randomize();        
        $display("\t %4h address allocated for %0d master", addr_handle.addr, addr_handle.N);
        end
    end
endmodule

In reply to dave_59:

Thank you Dave!

In reply to kddholak:

Hi kddholak,

Thank you for the response.

But now since we have N limited to 16, we can allocate specific address range for each master as shown in your code. But, if N value increases more than 16, then wouldn’t it become hard to allocate each address range to N. Just wanted to know how can we do in that scenario.

Thanks,
Sruthi.