Consider the following practical examples typically encountered during actual projects.

Memory block randomization

Assume we have a 2KB SRAM in the design intended to store some data. Let's say that we need to find a block of addresses within the 2KB RAM space that can be used for some particular purpose.

block allocation in memory
 
class MemoryBlock;
 
  bit [31:0]     m_ram_start;       // Start address of RAM
  bit [31:0]     m_ram_end;         // End address of RAM
 
  rand bit [31:0]   m_start_addr;       // Pointer to start address of block
  rand bit [31:0]   m_end_addr;       // Pointer to last addr of block
  rand int       m_block_size;       // Block size in KB
 
  constraint c_addr { m_start_addr >= m_ram_start;   // Block addr should be more than RAM start 
                      m_start_addr < m_ram_end;   // Block addr should be less than RAM end 
                      m_start_addr % 4 == 0;      // Block addr should be aligned to 4-byte boundary
                      m_end_addr == m_start_addr + m_block_size - 1; };
 
  constraint c_blk_size { m_block_size inside {64, 128, 512 }; };   // Block's size should be either 64/128/512 bytes
 
  function void display();
    $display ("------ Memory Block --------");
    $display ("RAM StartAddr   = 0x%0h", m_ram_start);
    $display ("RAM EndAddr     = 0x%0h", m_ram_end);
  $display ("Block StartAddr = 0x%0h", m_start_addr);
    $display ("Block EndAddr   = 0x%0h", m_end_addr);
    $display ("Block Size      = %0d bytes", m_block_size);
  endfunction
endclass
 
module tb;
  initial begin
    MemoryBlock mb = new;
    mb.m_ram_start = 32'h0;
    mb.m_ram_end   = 32'h7FF;     // 2KB RAM
    mb.randomize();
    mb.display();
  end
endmodule
 

In the example above, we have assumed the RAM to start from 0x0 and end at 0x7FF. The constraint example aims to allocate a block of memory space between this range with a size that is randomly chosen from 64 or 128 or 512 bytes. The start address of the block is randomized to be 0x714 and hence the end addr is 0x753.

Simulation Log
ncsim> run
------ Memory Block --------
RAM StartAddr   = 0x0
RAM EndAddr     = 0x7ff
Block StartAddr = 0x714
Block EndAddr   = 0x753
Block Size      = 64 bytes
ncsim: *W,RNQUIE: Simulation is complete.

Click to try this example in a simulator!   

Equal partitions of memory

In this example, we'll try to partition the 2KB SRAM into N partitions with each parititon having equal size.

memory partitions with equal sizes
 
class MemoryBlock;
 
  bit [31:0]     m_ram_start;       // Start address of RAM
  bit [31:0]     m_ram_end;         // End address of RAM
 
  rand int      m_num_part;       // Number of partitions  
  rand bit [31:0]   m_part_start [];     // Partition start array
  rand int       m_part_size;        // Size of each partition
  rand int      m_tmp;
 
  // Constrain number of partitions RAM has to be divided into
  constraint c_parts { m_num_part > 4; m_num_part < 10; }
 
  // Constraint size of each partition
  constraint c_size { m_part_size == (m_ram_end - m_ram_start)/m_num_part; }
 
  // Constrain start addr of each partition
  constraint c_part { m_part_start.size() == m_num_part;
                      foreach (m_part_start[i]) {
                        if (i) 
                          m_part_start[i] == m_part_start[i-1] + m_part_size;
                        else
                          m_part_start[i] == m_ram_start;
                      }
                    }                      
 
  function void display();
    $display ("------ Memory Block --------");
    $display ("RAM StartAddr   = 0x%0h", m_ram_start);
    $display ("RAM EndAddr     = 0x%0h", m_ram_end);
    $display ("# Partitions = %0d", m_num_part);
    $display ("Partition Size = %0d bytes", m_part_size);
    $display ("------ Partitions --------");
    foreach (m_part_start[i]) 
      $display ("Partition %0d start = 0x%0h", i, m_part_start[i]);
  endfunction
endclass
 
module tb;
  initial begin
    MemoryBlock mb = new;
    mb.m_ram_start = 32'h0;
    mb.m_ram_end   = 32'h7FF;     // 2KB RAM
    mb.randomize();
    mb.display();
  end
endmodule
 
Simulation Log
ncsim> run
------ Memory Block --------
RAM StartAddr   = 0x0
RAM EndAddr     = 0x7ff
# Partitions = 9
Partition Size = 227 bytes
------ Partitions --------
Partition 0 start = 0x0
Partition 1 start = 0xe3
Partition 2 start = 0x1c6
Partition 3 start = 0x2a9
Partition 4 start = 0x38c
Partition 5 start = 0x46f
Partition 6 start = 0x552
Partition 7 start = 0x635
Partition 8 start = 0x718
ncsim: *W,RNQUIE: Simulation is complete.

Click to try this example in a simulator!   

Variable memory partitions

memory partitions with variable sizes
 
class MemoryBlock;
 
  bit [31:0]     m_ram_start;       // Start address of RAM
  bit [31:0]     m_ram_end;         // End address of RAM
 
  rand int      m_num_part;       // Number of partitions  
  rand bit [31:0]   m_part_start [];     // Partition start array
  rand int       m_part_size [];       // Size of each partition
  rand int      m_tmp;
 
  // Constrain number of partitions RAM has to be divided into
  constraint c_parts { m_num_part > 4; m_num_part < 10; }
 
  // Constraint size of each partition
  constraint c_size { m_part_size.size() == m_num_part;
                     m_part_size.sum() == m_ram_end - m_ram_start + 1; 
                     foreach (m_part_size[i]) 
                       m_part_size[i] inside {16, 32, 64, 128, 512, 1024};
                    }
 
  // Constrain start addr of each partition
  constraint c_part { m_part_start.size() == m_num_part;
                      foreach (m_part_start[i]) {
                        if (i) 
                          m_part_start[i] == m_part_start[i-1] + m_part_size[i-1];
                        else
                          m_part_start[i] == m_ram_start;
                      }
                    }                      
 
  function void display();
    $display ("------ Memory Block --------");
    $display ("RAM StartAddr   = 0x%0h", m_ram_start);
    $display ("RAM EndAddr     = 0x%0h", m_ram_end);
    $display ("# Partitions = %0d", m_num_part);
    $display ("------ Partitions --------");
    foreach (m_part_start[i]) 
      $display ("Partition %0d start = 0x%0h, size = %0d bytes", i, m_part_start[i], m_part_size[i]);
  endfunction
endclass
 
module tb;
  initial begin
    MemoryBlock mb = new;
    mb.m_ram_start = 32'h0;
    mb.m_ram_end   = 32'h7FF;     // 2KB RAM
    mb.randomize();
    mb.display();
  end
endmodule
 
Simulation Log
ncsim> run
------ Memory Block --------
RAM StartAddr   = 0x0
RAM EndAddr     = 0x7ff
# Partitions = 7
------ Partitions --------
Partition 0 start = 0x0, size = 512 bytes
Partition 1 start = 0x200, size = 128 bytes
Partition 2 start = 0x280, size = 64 bytes
Partition 3 start = 0x2c0, size = 1024 bytes
Partition 4 start = 0x6c0, size = 128 bytes
Partition 5 start = 0x740, size = 128 bytes
Partition 6 start = 0x7c0, size = 64 bytes
ncsim: *W,RNQUIE: Simulation is complete.

Click to try this example in a simulator!   

Variable memory partitions with space in between

memory partitions with space in between
 
class MemoryBlock;
 
  bit [31:0]     m_ram_start;       // Start address of RAM
  bit [31:0]     m_ram_end;         // End address of RAM
 
  rand int      m_num_part;       // Number of partitions  
  rand bit [31:0]   m_part_start [];     // Partition start array
  rand int       m_part_size [];       // Size of each partition
  rand int       m_space[];          // Space between each partition
  rand int      m_tmp;
 
  // Constrain number of partitions RAM has to be divided into
  constraint c_parts { m_num_part > 4; m_num_part < 10; }
 
  // Constraint size of each partition
  constraint c_size { m_part_size.size() == m_num_part;
                     m_space.size() == m_num_part - 1;
                     m_space.sum() + m_part_size.sum() == m_ram_end - m_ram_start + 1;
                     foreach (m_part_size[i]) {
                       m_part_size[i] inside {16, 32, 64, 128, 512, 1024};
                       if (i < m_space.size())
                          m_space[i] inside {0, 16, 32, 64, 128, 512, 1024};
                     }
                    }
 
  // Constrain start addr of each partition
  constraint c_part { m_part_start.size() == m_num_part;
                      foreach (m_part_start[i]) {
                        if (i) 
                          m_part_start[i] == m_part_start[i-1] + m_part_size[i-1] +  m_space[i-1];
                        else
                          m_part_start[i] == m_ram_start;
                      }
                    }                      
 
  function void display();
    $display ("------ Memory Block --------");
    $display ("RAM StartAddr   = 0x%0h", m_ram_start);
    $display ("RAM EndAddr     = 0x%0h", m_ram_end);
    $display ("# Partitions = %0d", m_num_part);
    $display ("------ Partitions --------");
    foreach (m_part_start[i]) 
      $display ("Partition %0d start = 0x%0h, size = %0d bytes, space = %0d bytes", i, m_part_start[i], m_part_size[i], m_space[i]);
  endfunction
endclass
 
module tb;
  initial begin
    MemoryBlock mb = new;
    mb.m_ram_start = 32'h0;
    mb.m_ram_end   = 32'h7FF;     // 2KB RAM
    mb.randomize();
    mb.display();
  end
endmodule
 
Simulation Log
ncsim> run
------ Memory Block --------
RAM StartAddr   = 0x0
RAM EndAddr     = 0x7ff
# Partitions = 5
------ Partitions --------
Partition 0 start = 0x0, size = 128 bytes, space = 64 bytes
Partition 1 start = 0xc0, size = 32 bytes, space = 128 bytes
Partition 2 start = 0x160, size = 32 bytes, space = 0 bytes
Partition 3 start = 0x180, size = 1024 bytes, space = 512 bytes
Partition 4 start = 0x780, size = 128 bytes, space = 0 bytes
ncsim: *W,RNQUIE: Simulation is complete.

Click to try this example in a simulator!   

You may also like:

You consent to our cookies if you continue to use our website. To know more about cookies, see our privacy policy. I accept cookies from this site.

Agree