[FPGA]

효율적인 verilog coding을 위한 tip

Neo Park 2012. 8. 10. 12:15

1. define을 쓰지 말고 parameter를 써라
-------------------------------------------------------------------
parameter가 rvalue로 쓸때는 parameter 값에 width까지 정의한다.
안그러면 아래와 같은 warning이 난다.
-> Parameter range specification is new feature of Verilog 2001
Synthesis and non-Verilog 2001 compatible simulation may have different result
(VER-311)

parameter integer x 이렇게 하면 signed표현이므로 아래처럼 한다.
parameter P = 3'd0;
안그러면 아래와 같은 warning을 받을 수 있다.
-> signed to unsigned assignment occurs. (VER-318)


Starting with the 200.11-1 release, the Presto Verilog reader treats Verilog 'integer' types as signed; .. (VER-314)

 

2. assignment시 intra-assignment delay for nonblocking assignment are ignored 를 쓰지 마라.
-------------------------------------------------------------------
o_r1 <= #1 1'b1;  (warning VER-130)

intra-assignment delay for nonblocking assignment are ignored (VER-130)

추천: 시뮬레이션시에는 delay가 있어야 더 현실적이다. 따라서 define으로 정의하는게 좋을듯하다.
o_r1 <= `DFF 1'b1;

 

3. 반드시 width를 정해라.
--------------------------------------------
1'b0, 2'd0 이렇게 써라.

 

4. TOP 모듈로 들어오는 input에 대해선 무조건 reg로 1 clock 채줘야 한다.
바로 전 module에서 combinational logic으로 만들어 주면 그만큼 시간을 잡아먹기 때문이다.
--------------------------------------------------------------------

 

5. 해당 모듈이 실제 사용하는 비트range만 입력으로 받는다.
-------------------------------------------------------------------
module A;
input [9:0] i;

x = i[4:0];
모듈 A가 10비트를 받지만 실제 내부에서는 5비트만 쓰고 있다 따라서 module A는 4:0만 받도록 해야 한다.

is not connected to any nets. (LINT-28) 워닝 남.

 

6. 가능하면 모듈에서 출력은 한번 reg로 받아서 보낸다.
-------------------------------------------------------------------

reg o_out;
always @ (posedge clk or negedge rstn )
if( !rstn )
  o_out <= 0;
else
if( A != X )
  o_out <= A;

보다는 아래처럼 하면 o_out의 setup timing을 좋게 한다.
always @ (posedge clk or negedge rstn )
if( !rstn )
  next_out <= 0;
else
if( A != X )
  next_out <= A;

always @ (posedge clk or negedge rstn )
if( !rstn )
  next_out <= 0;
else
  o_out <= next_out;


7. reset은 각 clock마다 마련해라.
-----------------------------------------------------------------
먼저 system_global_reset을 system_clk으로 synchronizer한다음, 몇 clk delay를 준다.
그 다음 해당 delay_reset을 각 clk에 맞게 synchronizer를 돌려서 clk별 reset을 만든다.


8. Asnychronous FIFO 관련
-----------------------------------------------------------------
8.1 각 lane별로 Async FIFO가 있을 경우 가능하다면 각 FIFO의 read신호는 동시에 마련해서 읽도록 하라. 안 그러면 각 FIFO마다 CDC 및 읽어가는 타이밍 상 각 lane별로 다를 수 있어 이에 따른 side effect로 문제가 생길 수 있다.
8.2 만일 Async FIFO가 stream으로 들어오는 것과 나가는것이 일정한 rate를 갖을때 보다 문제없도록 동작하게 하려면 처음에는 FIFO에 몇개 정도 차도록 하고 그 때부터 하나라도 있다면 일어갈 수 있도록 동작시키는것이 좋다.


STA (Static Timing analysis) 방법
----------------------------------------------------------------
먼저 simulation test가 되면 synthesis를 해보고 prime time을 사용하여 sta를 한다.

sta/reports/func.vdltx_top.allviol.rpt.ver에서 type: max 인것들(setup타임 violation)만 보면 됨.

나중에 hold violation은 p&r에서 skew 컨트롤하면서 buffer를 넣어주면된다.


1. 만일 combinational logic이 FF간에 너무 많다면 적절히 끊어서 reg로 만든다.
 - 이때 타이밍이 맞아야 하는 다른 병렬적인 data/control_path에 대해서도 reg버퍼링으로 타이밍을 맞춰줘야 한다.

2. even/odd 방식으로 병렬화

3. 만일 어떤 reg를 여러곳에서 쓴다면 fan out이 커져서 synthesis할때 버퍼(BUF, INV)가 많이 달리게 된다. 이를 방지하기 위해서는 reg와 동일한 쌍둥이 reg를 만든 후 rvalue로 사용될때 적절히 분배하도록 하면 된다. (생각보다 큰 효과를 볼 순 없음, 버퍼를 줄이는 효과)

3. 만일 어떤 모듈을 여러 모듈에서 사용해도 해당 모듈의 출력의 fan out이 커질 수 있음 이때도 각 모듈마다 해당 모듈을 각자 생성해서 사용하도록 할 수 있다.
예) multi lane tx link를 설계 시 counter 모듈을 lane별로 생성해서 사용.

4. fifo는 word width를 줄이면 좋다. 40bit width라면 20bit width 두개의 병렬 fifo를 마련해도 동작엔 아무런 상관이 없다.


DFT scan test를 위한 코드
------------------------------------------------------------------
Spyglass_DFT를 사용할 수있다.
scan test는 PNR과정에서 모든 route path가 잘동작하는지 확인하기 위하여 디자인내의 모든
dff reg의 데이터 출력 Q를 체인으로 데이터 입력에 연결하여 scan test시 제일 처음 dff에게
값을 주고 clock을 발생시켜 모든 dff reg에 원하는 값이 들어가 있는지 확인하는 test이다.
만일 clock domain이 다르면 각 domain별로 scan test를 해야 한다.

1. 가능한한 주어진 ref clk을 사용하여 모든 dff를 다루어라.
  - 만일 ref_clk의 div2_clk를 사용해야 한다면 ref_clk로 2분주된 div2_clk을
    always @ (posedge div2_clk로 쓰지말고
    always @ (posedge ref_clk .. ) if( div2_clk == 1 ) 인 경우로 사용하라.
    그러지 않으면 향후 scan test를 하는데 div2_clk를 사용하는 dff는 scan_test모드일 경우
    ref_clk를 받도록 mux하는 코드를 작성해야하는 불편함이 있다.
    안그러면 scan test가 div2_clk를 사용하는 dff는 scan test가 제대로 되지 않는다.
2. sw reset을 하는 경우 scan_test_mode및 scan_reset이 필요하다.
  - sw reset은 sw reset dff reg를 1로 만들면 내부적인 reset신호를 생성하는데 이 sw_reset
    dff가 scan test시 1이 되면 이와 관련된 sw_reset을 받는 모듈의 dff들이 reset이 되어
    제대로 scan test를 할 수 없다. 따라서 scan_test_mode가 1인 경우 sw_reset dff가 active
    되지 않도록 mux out해주어야 한다.
3. 만일 reset이 없는 dff reg는 scan_test_mode가 1일때 scan_resetn을 사용토록하게 하라.
  - scan test를 빨리하기 위해서 scan test시 reset을 하게 되는데 이 dff reg는 reset을 갖지
    못하므로 이 dff reg를 reset하려면 모두 연결된 scan chain만큼 scan clk을 먹여 초기화해야
    하므로 시간이 많이 걸리므로 scan test모드일 때는 이 reset이 없는 dff reg는
    regscan_resetn을 받도록 한다.


Test/Debug를 위한 코드
------------------------------------------------------------------
1. 가능하면 I2C나 APB의 SFR에 각 모듈별 enable, disable config하는 reg를 많이 두어라.
 - 다양한 모드를 지원한다는 개념이 아닌 chip debugging시 안되면 최악의 경우 다른 path로
   동작되는 최소한의 기능이라도 뚫수 있도록 하는 차원에서 만들어야 한다.
2. SFR에 최대한 많은 현재 모듈 내의 status를 볼 수 있는 내용을 넣어두어라.
 - chip test시 버그 발생시 어떤 상태인지라도 조금더 확인해 볼 수 있는 여지가 있다.


Timing Budget계산
------------------------------------------------------------------
100MHz라면 1clk이 10ns이다. 이 때 D-FF의 setup time, hold time을 감안하여 60%를 사용가능한 타이밍구간이라고 보게 되면, 6ns를 사용 가능한것이고, 기본 2 input-nand 하나의 지연이 1ns이라면 최대 6 level을 사용 가능하게 된다.

 

 

 

 

참조: http://neri.cafe24.com/menu/bbs/view.php?id=kb&page=1&sn1=&divpage=1&sn=off&ss=on&sc=on&select_arrange=hit&desc=asc&no=579&PHPSESSID=f3c745d763b45bc79d532acb58c52a34