Showing posts with label verification. Show all posts
Showing posts with label verification. Show all posts

Tuesday, August 12, 2025

Single Linked List in System Verilog

 Lets code a simple singly Linked List which traverse from head to tail in one direction.

Requirement is simple, you will have a Node which contains two main elements, data and pointer to next node.

On adding a new node, the new node should create a handle of the old node and assign the pointer to the new one.


CODE:

class Node;
  int id;
  int data;
  Node next_node;
  
  function new ( int i );
    id = i;
    next_node = null;
  endfunction: new
  
  function void load_data ( int val );
    data = val;
  endfunction: load_data

  function void add_node ( Node node );
    node.next_node  = new(id);
    node.next_node  = this;
  endfunction: add_node
  
 endclass: Node
  
  module top;
    Node n[10];
    
    initial begin
      foreach ( n[i] ) begin
        n[i]      = new(i);
        n[i].data = $urandom_range(10,100);
        if(i>0) n[i].add_node(n[i-1]);           
      end 
      
      foreach ( n[i] ) begin        
        if(i==9) 
          $display ( "NODE ID:%0d Data:%0d NEXT_PTR:NULL", n[i].id,n[i].data );
        else 
          $display ( "NODE ID:%0d Data:%0d NEXT_PTR:%0d", n[i].id,n[i].data,n[i].next_node.id );
      end
    end        
  endmodule: top



RESULT:

Compiler version U-2023.03-SP2_Full64; Runtime version U-2023.03-SP2_Full64; Aug 12 10:17 2025
NODE ID:0 Data:54 NEXT_PTR:1
NODE ID:1 Data:62 NEXT_PTR:2
NODE ID:2 Data:68 NEXT_PTR:3
NODE ID:3 Data:44 NEXT_PTR:4
NODE ID:4 Data:75 NEXT_PTR:5
NODE ID:5 Data:88 NEXT_PTR:6
NODE ID:6 Data:89 NEXT_PTR:7
NODE ID:7 Data:72 NEXT_PTR:8
NODE ID:8 Data:62 NEXT_PTR:9
NODE ID:9 Data:53 NEXT_PTR:NULL
V C S S i m u l a t i o n R e p o r t

Saturday, July 19, 2025

Generating AXI Strobe based on SIZE, DATA WIDTH

AXI write strobe is generated based on the axi size and data width supported. For example, if the axi interface you are using has 64 bit wide data bus, you can have strobe of 64/8 = 8 Let us take the same data width as an example to produce axi write strobe.

In this case, the strobe is set starting at address offset and continues till the size of the transfer is met.

For example, 
ADDR = 0x3
SIZE    = 0x2 (32 bits)
LEN     = 0x2 (3 beats)

For the first beat, ADDR = 0x3, STRB = 0xF8
For the second beat, ADDR = 0x7, STRB = 0x80
For the third beat, ADDR = 0xB, STRB = 0xF8

 
module top;
  parameter int DATA_WIDTH = 64;
  bit [2:0] aw_size;
  bit [7:0] aw_len;
  bit [31:0] aw_addr;
  bit [7:0] w_strb[$];
  bit [31:0] addr_align;
  
  function automatic bit [7:0] gen_strb ( input bit [31:0] addr, input bit [2:0] aw_size );
    bit [7:0] strb;
    int size_in_bytes = 2**aw_size;
    addr_align = addr % (DATA_WIDTH/8);
    
    
    for( int i=0;i<DATA_WIDTH/8;i++) begin
      if ( i inside {[addr_align:addr_align+size_in_bytes-1]}) strb[i] = 1;
      else strb[i] = 0;
    end
    //$display("ADDR_A:%0h BY:%0d STRB:%0h",addr_align,size_in_bytes,strb);
    return strb;
  endfunction
  
  function automatic void load_strb ( );
    bit [31:0] addr_l;
    for ( int i=0;i<aw_len+1;i++) begin
      addr_l = aw_addr + (i << aw_size);
      w_strb.push_back(gen_strb(addr_l,aw_size));
      $display("ADDR:%0d STRB:%0h",addr_l,w_strb[i]);
    end    
  endfunction
  
  initial begin
    aw_addr = 'h3;
    aw_len  = 'h2;
    aw_size = 'h2;
    load_strb();
  end
  endmodule

RESULT:

Compiler version U-2023.03-SP2_Full64; Runtime version U-2023.03-SP2_Full64; Oct 16 02:13 2025
ADDR:3 STRB:78
ADDR:7 STRB:80
ADDR:11 STRB:78
V C S S i m u l a t i o n R e p o r t

Thursday, January 26, 2023

SELECTING NON-OVERLAPPING MEMORY BANKS FROM A MEMORY

 PROBLEM STATEMENT:

  • Suppose you have a memory of depth = 100, you are tasked to generate 4 memory banks of size =10.
  • Condition, memory banks must be non-overlapping.

ANALYSIS:

  1. The trick here is not get carried by the simplicity of the question and start coding away.
  2. The question though sounds easy at first, will get complicated when you start coding the constraints.
  3. We should first start with marking boundary for the banks
  4. In this case we started with first bank and made sure that the start address is always between 0-60
  5. why 60 ? The answer is simple, memory depth is 100, number of banks are 4, and size of each bank is 10. Therefore if the start address of first bank is <= 60, we can have rest of the banks in the other remaining locations. There won't be an overflow.
  6. Once the start address of first bank is generated, it is easy to mark the end address, start_address+bank_size-1
  7. The start address for the second bank must be greater than the end address of first bank and the range must be between 0:70. Reason? Similar to point (5).
  8. The other 2 banks follow the suite.
  9. Now comes the question of limiting the position of each bank, first bank always occupy the lower locations and last one will occupy higher locations.
  10. This can be solved by simply shuffling the queue/array in which we store the start_address during post_randomization().
  11. There can be many other ways to write the constraint, but I found this quite simple and will not stress of the constraint solver.


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
class mem_banks;
  parameter MEMORY      = 100;
  parameter BANK_SIZE   = 10;
  parameter NO_OF_BANKS = 4;
  
  rand bit [31:0] addr_min[NO_OF_BANKS];
  rand bit [31:0] addr_max[NO_OF_BANKS];
  int total_mem = BANK_SIZE * NO_OF_BANKS;
  
  constraint a_addr { 
    foreach (addr_min[i]) { 
      if(i==0) addr_min[i] inside {[0:(MEMORY-total_mem)]};
      else { 
        addr_min[i] inside {[0:(MEMORY-total_mem)+(BANK_SIZE*i)]};
        addr_min[i] > addr_max[i-1];
      }
      addr_max[i] == addr_min[i]+BANK_SIZE-1;  
    }
        
  }
      
  function void post_randomize();
    addr_min.shuffle();
    foreach(addr_min[i])
      $display("ADDR_MIN:%d ADDR_MAX:%d",addr_min[i],addr_min[i]+BANK_SIZE-1);
  endfunction: post_randomize
    
    
  
endclass: mem_banks

module top;
  mem_banks m;  
  initial begin
    
    m = new;
    repeat(2) begin
      void'(m.randomize());
      $display("======================================");
    end

  end
endmodule: top

RESULTS:

Chronologic VCS simulator copyright 1991-2021
Contains Synopsys proprietary information.
Compiler version S-2021.09; Runtime version S-2021.09; Jan 26 09:47 2023
ADDR_MIN: 5 ADDR_MAX: 14
ADDR_MIN: 69 ADDR_MAX: 78
ADDR_MIN: 39 ADDR_MAX: 48
ADDR_MIN: 15 ADDR_MAX: 24
======================================
ADDR_MIN: 90 ADDR_MAX: 99
ADDR_MIN: 40 ADDR_MAX: 49
ADDR_MIN: 63 ADDR_MAX: 72
ADDR_MIN: 13 ADDR_MAX: 22
======================================
V C S S i m u l a t i o n R e p o r t
Time: 0 ns
CPU Time: 0.480 seconds; Data structure size: 0.0Mb
Thu Jan 26 09:47:17 2023

Generating prime numbers between 1 to 100

  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 class test ; int prime_q[$]; function voi...