ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [SystemVerilog] 랜덤변수 1
    개발/SystemVerilog 2022. 1. 25. 22:16

    시스템베릴로그의 강력한 기능인 constriant randomize 를 알아본다.

     

    베릴로그에는 랜덤값을 생성하는 시스템태스크가 있다.

    하지만 어떤 제약조건에 맞는 범위의 랜덤변수를 생성하려면 번거롭게 코딩을 해야한다.

    시스템베릴로그는 랜덤변수에 제약조건과 확률분포, 조건부 확률을 지원하여 사용자의 입맛대로 자유롭게 랜덤변수를 생성 할 수 있다.

     

    시뮬레이터는 트루랜덤이 아니라 pseudo 랜덤값을 생성하는데 이는 테스트의 일관성과 반복적 디버깅을 위해서 그런것이다. 시드가 같으면 랜덤값의 시퀀스도 같다.

     

     

    랜덤변수를 선언할 때 rand / randc 키워드를 붙이면 된다.

    rand 는 균일한 확률분포를 갖는 랜덤변수를 정의한다.

    randc는 랜덤값이 순환하는 하도록 정의한다.

    랜덤값을 주려면 randomize() 메서드를 쓰면 된다.

    module tb;
      
      class packet;
          rand bit [2:0] data;
          randc bit [2:0] addr;
      endclass
    
      initial begin
          packet pkt = new();
          repeat (16) begin
              pkt.randomize();
              $display("data = %d, addr = %d", pkt.data, pkt.addr);
          end
      end
    endmodule

    테스트 결과를 보면 차이를 바로 알 수 있다.

    rand로 선언한 변수는 무작위로 값이 나온다.

    randc 는 무작위이긴 하지만 값을 갖을수 있는 범위(0~7) 안에 있는 값들이 한번씩 나온다.

     

    randomize() 메서드를 이용하여 랜덤값을 부여한다. 

    rand / randc 키워드는 기본적인 데이터 타입에는 모두 사용할 수 있다. (int, bit, array, queue 등등)

     

     

     

    이제 랜덤값을 만드는건 알았지만 그렇다고 아무값이나 막 줄수는 없다.

    따라서 랜덤값에도 일정한 범위를 한정해야한다.

    constraint 구문을 사용하여 랜덤값 생성에 범위와 조건을 지정할 수 있다.

    constraint valid_addr {addr [1:0] == 2'b00;
    			addr <= 32'h1111_ffff;
                            addr >= 32'h0000_1111};
                            
    constraint fast_burst {burst >= 3;
    			len >= 64;
               	 	size >= 128};
                    
    constraint empty {};
    
    
    constraint error {0 < min < typ < max < 128};	// invalid
    
    // valid expression
    constraint valid {0 < min;
    		min < typ;
                	typ < max;
                	max < 128};

    contraint name {condition1; condition2; ...}; 형식으로 제약조건을 지정한다.

    만약 서로 상충되는 조건이 있을 경우엔 런타임에러가 발생한다.

    한 문장에 하나의 조건씩 기술해야한다.

     

     

     

    module tb;
      class packet;
        rand bit [3:0] mode;;
        
        constraint c1 {mode > 2;
                     mode < 6;}; 
      endclass
    
      initial begin
          packet pkt = new();
        repeat (10) begin
              pkt.randomize();
            $display("mode = %d", pkt.mode);
          end
      end
    endmodule

    constraint 를 추가하고 랜덤값을 준 결과.   3 ~ 5 값이 생성된다.

     

     

     

    extern 키워드를 사용하면 constraint 구문을 클래스 밖에서 기술할 수 있다.

    extern task / function 정의하는것과 똑같다.

    module tb;
      class packet;
    	rand bit [3:0] mode;
        exturn constraint c1;
      endclass
    
        contraint c1 {mode >2 ; mode < 6};

     

    constraint 구문을 작성할 때 inside operator가 유용하다.

    대괄호 안에 정수 범위를 지정할 수 있다.

    inside는 파이썬에서 in 연산자와 동일한 기능을 한다.

    constraint range {typ >= 32; typ <= 256;};
    
    // 32 to 256
    constraint range {typ inside {[32:256]};};
    
    
    // 32, 64, 128 중에 하나
    constraint range {typ inside {32, 64, 128};};
    
    
    // 32, 64, 128 제외한 나머지
    constraint range {!(typ inside {32, 64, 128});};

     

Designed by Tistory.