Saturday, July 26, 2025

TCAM

TCAM stands for Ternary Content Addressable Memory.

In this, instead of data, the search returns address and number of entries that match the search key.

What the code does:

  • TCAM is 16 locations deep.
  • TCAM class contains 3 methods.
    • load_tcam ( )     - It takes data and address as inputs and loads the TCAM memory
    • search_tcam ( ) - Lets dive more into this method, this is where things are handled differently when compared with the normal SRAM's. The inputs contain key and mask. Key is used to search all the entries and find the matching addresses. If there is a single hit, output bit match is set to 1. For multiple entries, match_entries field corresponding to the hit index is set to 1. Mask is what differentiates a normal CAM with TCAM. When MASK field is set to 1, the entry is always treated as matched irrespective of the contents of the entry. Finally address ( output ), this can be set as per the priority order set. In this case, I choose last match as the highest priority.
    • clear_tcam() - To clear all contents of the TCAM memory.

class tcam;
  logic [31:0] tcam_mem[16];
  
  virtual task clear_tcam ( );
    foreach (tcam_mem[i]) tcam_mem[i] = 0;
  endtask: clear_tcam
  
  virtual task load_tcam ( input logic [31:0] data , input logic [31:0] addr ); 
    tcam_mem[addr] = data;
  endtask: load_tcam
  
  virtual task search_tcam ( 
    input logic [31:0] key, 
    input logic [31:0] mask, 
    output bit match, 
    output bit [15:0] match_entries, 
    output bit [31:0] address );
for ( int i=0;i<16;i++ ) begin //{ // mask[i] == 1, don't care, always matches irrespective of key if(tcam_mem[i] == key || mask[i]) begin //{ match = 1; match_entries[i] = 1; address = i; // You can choose any priority, I choose priority of Last match address end //} end //} endtask: search_tcam endclass: tcam module top; tcam t; initial begin logic match; logic [31:0] match_entries; logic [31:0] match_address; t = new; t.load_tcam(10,0); t.load_tcam(20,1); t.load_tcam(25,2); t.load_tcam(30,3); t.load_tcam(20,4); t.search_tcam(20,0,match,match_entries,match_address); $display ("Match:%0d Entries:%0b Address:%0d",match, match_entries,match_address ); end endmodule: top

OUTPUT:

Compiler version U-2023.03-SP2_Full64; Runtime version U-2023.03-SP2_Full64; Jul 26 13:19 2025
Match:1 Entries:10010 Address:4
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.530 seconds; Data structure size: 0.0Mb
Sat Jul 26 13:19:05 2025
Done



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

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...