[팁] 테터툴즈에서 Verilog용 SyntaxHighlighter 사용하기

조만간 Verilog 강좌를 시작할 예정인데, 그에 앞서 블로그에 Verilog Syntax Highlighter를 설치하였습니다.

먼저 Syntax Highligher가 뭔지 보여드리면,

글을 쓸때 요렇게 입력하면,

요렇게 예쁘게 보여주는 것입니다.

SyntaxHighligher는 [이곳]에서 다운받으시면 됩니다. 저는 최신버젼인 3.0.83을 받았습니다.
여러가지 언어를 지원하지만 Verilog는 기본적으로 지원되는 언어가 아닙니다. 하지만, Tyreal이란 분이 친절히 [Verilog용 Brush]를 만들어놓았습니다. 모두 저장해둡니다.

FTP로 두 파일을 모두 블로그에 올려두고, Telnet/rlogin으로 블로그 계정이 접속하여 압축을 풉니다.
편의상 tt(테터툴즈 기본 디렉토리)/plugins/SyntaxHighlight 에 압축을 풉니다.

$ cd tt/plugins
$ unzip syntaxhighlighter_3.0.83.zip
$ mv syntaxhighlighter_3.0.83 SyntaxHighlight
$ cd SyntaxHighlight
$ ls
LGPL-LICENSE  MIT-LICENSE  compass  index.html  scripts  src  styles  tests

Verilog용 Brush파일 shBrushVerilog.js를 scripts 디렉토리에 저장합니다.

관리자로 접속하여 ‘스킨관리’메뉴에서 skin.html을 수정합니다.
</head> 바로 앞에다가 아래 내용을 추가합니다.

<!-- Include required JS files -->
<script type="text/javascript"
src="/tt/plugins/SyntaxHighlight/styles/shCore.js"></script>

<!--
  At least one brush, here we choose JS. You need to include a brush
for every
  language you want to highlight
-->
<script type="text/javascript"
src="/tt/plugins/SyntaxHighlight/scriptss/shBrushJScript.js"></script>

<!-- Include *at least* the core style and default theme -->
<link href="/tt/plugins/SyntaxHighlight/styles/shCore.css"
rel="stylesheet" type="text/css" />
<link href="/tt/plugins/SyntaxHighlight/styles/shThemeDefault.css"
rel="stylesheet" type="text/css" />

그리고 skin.html의 제일 아래부분 </body>바로 앞에 아래 내용을 추가합니다.

<!-- Finally, to actually run the highlighter, 
you need to include this JS on your page -->
<script type="text/javascript">
    SyntaxHighlighter.all()
</script>

그리고 글을 쓸때 Verilog 코드의 앞뒤에 <pre class=”brush:verilog”>와 </pre>를 입력하면 됩니다.

[Verilog] 새로 컴파일하지 않고 테스트 입력/조건을 바꾸는 방법

Compiled-code방식 Verilog 시뮬레이터는 크게 세단계로 동작합니다.

  1. Compile: Verilog Code의 문법을 체크하고, 해석하고(parse/analyze)하고 Compile한다.
  2. Elaboration: 계층구조(design hierarchy)를 구축하고 신호들을 연결하고 초기값을 계산한다.
  3. Simulation: 회로의 동작을 시뮬레이션한다.

복잡하게 나누어 생각하고 싶지 않은 분들도 계실텐데, C프로그램을 해보신 분들이라면 쉽게 이해할 수 있습니다.

  1. Compiler: C컴파일러를 이용해서 C 코드를 Object코드로 만드는 것과 유사합니다.
  2. Elaboration: Object코드를 Linker로 연결해서 실행화일(Executable)을 만드는 것과 유사합니다. C Code건, 어셈블리코드건 언어에 관계없이 Object코드는 동일한 것과 같이 Elaboration은 VHDL와 Verilog를 구분하지 않습니다.
  3. Simulation: 실행화일(Executable)을 실행하는 것과 같습니다.

여기서 주목할 부분은 프로그램을 실행할때 매번 새로 컴파일하지 않고 실행화일만 실행하듯이, 시뮬레이션도 컴파일 과정을 생략할 수가 있다는 것입니다.

컴파일에 소요되는 시간이 전체 시뮬레이션에서 차지하는 시간이 크지 않은 경우도 많지만, 설계가 복잡하고 매우 다양한 경우에 대해서 시뮬레이션(regression)을 할 경우, 이 시간을 줄이는 것이 적지않은 효과가 있습니다.

물론 Verilog 소스코드가 변경된 경우라면 새로 컴파일을 해야합니다만, 사진이 바뀌고 모니터 해상도가 바뀌었다고 포토샵을 새로 컴파일하지 않듯이, 시뮬레이션 입력, 조건만 바뀌었을 경우엔 새로 컴파일 할 필요가 없습니다.

Cadence NC-Verilog를 기준으로 설명해보겠습니다.
NC-Verilog는 두가지 방법으로 실행이 가능한 데 single-step으로 실행하는 command인 ncverilog과 3-step으로 실행하는 command인 ncvlog, ncelab, ncsim이 있습니다.

3-step으로 실행하는 경우엔 마지막 단계인 ncsim만 반복적으로 실행하면 됩니다.

$ ncvlog subblock1.v subblock2.v topmodule.v
$ ncelab topmodule
$ ncsim topmodule
$ ncsim topmodule (재실행)

ncverilog를 사용하는 경우엔 ncverilog -R 옵션을 이용하면 마지막 simulation단계만 실행하게 됩니다.
3-step으로 실행하는 경우엔 마지막 단계인 ncsim만 반복적으로 실행하면 됩니다.

$ ncverilog subblock1.v subblock2.v topmodule.v
$ ncverilog -R (재실행)

이렇게 컴파일을 하지 않고 시뮬레이션만 다시 실행하면서 입력을 바꾸는 방법은 다음과 같습니다.
1. 외부파일을 사용하는 방법
Image processing을 하는 회로라고 가정하면 입력은 주로 사진 데이터입니다. 시뮬레이션 중에 사진 파일을 읽어서 사용하도록 만들면, 사진 파일만 바꿔주면 컴파일과정없이 시뮬레이션을 할 수 있습니다. 대신 외부파일을 읽어들이는 부분(parser)를 Verilog나 C언어로 구현해야합니다.

Verilog로 구현하는 경우엔 C언어와 유사한 $fopen, $fscanf을 이용하면 됩니다. 단, 텍스트파일만 읽을 수 있으므로 PPM과 같은 ASCII 데이터의 파일 format을 사용해야합니다.

C언어를 이용하는 경우 원하는대로 프로그램을 작성하여 decoding이 필요없는 BMP를 비롯, 다양한 입력을 읽어들일 수 있습니다. Verilog의 PLI(Programing Language Interface)나 SystemVerilog의 DPI(Direct Programming Interface)를 이용하면 됩니다.

2. $test$plusargs, $value$plusargs 를 이용하는 방법

$test$plusargs()는 Verilog-1995에도 존재했던 기능이고, $value$plusargs()는 Verilog-2001에서 확장된 기능입니다.

간단한 예로 시뮬레이션 결과를 waveform으로 저장하면 시뮬레이션 속도가 상당히 느려지고, 저장공간을 많이 차지할 수 있습니다. 따라서 필요한 경우에만 signal dump를 받게 되는데 이를 위해 대개 사용하는 방법은 다음과 같습니다.,

1. Verilog코드를 수정해서 $dumpvars와 같은 구문을 주석으로 처리한 뒤 새로 컴파일합니다.

initial
begin
      // $dumpvars;
end

2. `ifdef / `ifndef 를 이용하는 방법. command line에서 설정이 가능하므로 보다 깔끔한 방법이지만, 이 방법 역시 새로 컴파일을 해야합니다.

initial
begin
     `ifndef nodump
            $dumpvars;
     `endif
end

$ncverilog +define+nodump …..

이런 경우 $test$plusargs를 이용하면 됩니다. +define을 사용하는 것과 유사하지만 새로이 컴파일을 할 필요가 없습니다. (-R 옵션에 주목)

initial
begin
      if(!$test$plusargs(“nodump”))
             $dumpvars;
end

$ ncverilog -R  (dump파일 생성)
$ ncverilog -R +nodump (dump파일 생성 안함)

참고로, 간단히 설명하기 위해 dumpvars를 사용했는데, vcd형식보다 shm이나 fsdb형식을 사용하면 속도,용량에 개선 효과가 있습니다.

$value$plusargs 를 이용하면 command line에서 10진수, 16진수, 2진수, 실수 등 보다 상세한 입력이 가능합니다.

$value$plusargs (string, variable)
%b – binary conversion
%d – decimal conversion
%e – real exponential conversion
%f – real decimal conversion
%g – real decimal or exponential conversion
%h – hexadecimal conversion
%o – octal conversion
%s – string (no conversion)
%x – (undergound equivalent for %h)

예제로 클럭 주파수를 바꾸는 경우를 살펴봅시다.

filename: test.v

module test;

reg     clock = 0;
real    clock_h_period;
always #clock_h_period
       clock = !clock;
initial begin
       if(!$value$plusargs(“clock_h=%F”, clock_h_period)) begin
               clock_h_period = 10;
       end
       $monitor(“%t %b”, $time, clock);
       #100 $finish;
end
endmodule

$ ncverilog test.v +nocopyright
Loading snapshot worklib.test:v ……………….. Done
ncsim> source …/tools/inca/files/ncsimrc
ncsim> run
                  0 1
                 10 0
                 20 1
                 30 0
                 40 1
                 50 0
                 60 1
                 70 0
                 80 1
                 90 0
Simulation complete via $finish(1) at time 100 NS + 0
./test.v:15     #100 $finish;
ncsim> exit
$ ncverilog -R +clock_h=20 +nocopyright
Loading snapshot worklib.test:v ……………….. Done
ncsim> source …/tools/inca/files/ncsimrc
ncsim> run
                  0 1
                 20 0
                 40 1
                 60 0
                 80 1
Simulation complete via $finish(1) at time 100 NS + 0
./test.v:15     #100 $finish;
ncsim> exit

반복 회수를 입력하거나, Random 값 생성에 사용할 seed입력(@KyonghoKim의 코멘트)하거나 다양한 환경적인 변수에 대한 반복적인 시뮬레이션(regression)을 수행할 때 유용할 것입니다.

무료 Verilog Simulator – Icarus

gEDAGPL을 따르는 EDA툴킷 개발 프로젝트로 2002년에 시작되어 지금까지 꾸준히 업데이트가 되고 있으며 오픈소스프로그램으로는 높은 완성도를 갖고 있다.

http://www.gpleda.org/

이중에서도 Icarus Verilog Simulator는 무료로 사용할 수 있는 시뮬레이터 중에 가장 유명하다. gEDA 프로젝트도 Stephen William이 개발한 Icarus로 부터 시작되었다.

오픈소스프로그램들은 직접 컴파일을 해서 사용하는 번거로움이 있지만 다행히 Icarus와 gtkwave(waveform view)를 간단히 설치할 수 있는 intall package가 있으며 아래링크에서 받을 수 있다.

iverilog-0.9.1_setup.exe [5.33MB]

설치과정
1. iverilog-0.9.1_setup.exe실행, Next

2. License Agreement에 동의(필수), Next

3. 설치위치 변경(선택). 기본 값인 “C:\Program Files\Icarus Verilog” 대신 “C:\Icarus”입력.
변경하지 않을 경우 환경변수의 PATH값을 “c:\progra~1\icarus~1\bin”으로 변경해야함.
(환경변수 변경 방법은 10번 과정 참조)

4. waveform view인 GTKWave설치 (필수)

5. 시작메뉴폴더 생성 (선택)

6. 바탕화면 아이콘 추가 (선택)

7. 설치준비완료

8. 설치

9. 설치 완료. 환경변수 추가 선택(필수)

10. 환경 변수 설정. 3번과정대로 설치위치를 변경하지 않고 긴 이름의 디렉토리를 사용할 경우는 아래와 같이 직접 환경변수를 설정해주어야 정상적으로 사용이 가능하다.
“C:\Program Files\Icarus Verilog Simulator\bin” 부분을 “C:\progra~1\icarus~1\bin”과 같이 변경하여 저장한다.

11. Command창 실행. ‘시작->실행’ 메뉴 실행후 ‘cmd’, 확인

12. 디렉토리 변경후 Icarus실행.
icarus가 설치된 디렉토리로 이동 (cd c:\icarus) 후
예제파일인 lfsr16.v실행
iverilog lfsr16.v <enter>
vvp a.out <enter>
gtkwave <enter>

13. waveform확인 (결과파일’dump.vcd’ 로드)

14. waveform확인 (신호선택)

(Verilog) Setting a Net to a Logic Value

The $deposit system task allows you to set a net to a particular value and then to simulate
with the net set to that new value. The value change is propagated throughout the nets and
registers being driven by the variable that has been set. The syntax is as follows:

$deposit(variable, value);

The $deposit task can be used within any Verilog-XL procedural block. You can define the time at which the net is to be given a new value using the standard procedural constructs. The task can also be used on the interactive command line.

Use this system task as a debugging or design initialization aid. You should not use it as a
representation of actual circuitry.

Common uses for the $deposit system task include the following:

  • To initialize large portions or all of a circuit either at the beginning of or during a simulation. You can select the nodes to be deposited to yourself, or use PLI code to extract the node names.
  • To stop the simulator during a debugging session and to use the command on the interactive command line to set a new value.
  • To reset a circuit to a known state after simulation in order to retry a different debug route.
  • To set parts of a circuit to analyze intricate circuit details (common for switch level simulation).
  • To break feedback loops to set them to a known state.

In the syntax, variable is the name of the net or register whose value is being changed. The variable can be a net or register type but not a parameter, and it can be a vector or scalar object that can be expanded or compacted.

The second parameter, value, is a numerical or logical value in standard Verilog-XL notation. Bit and part selects are not allowed.

If the width of the value is smaller than the range of the variable, an error message is generated. If the width of the value is larger than the range of the variable, the MSBs are truncated and a warning is issued.

X and Z states can also be deposited.

Here are some examples of using $deposit:
$deposit(sig, 1);
$deposit(bus, ’hA2);
$deposit(bus4, ’bZ01x);

p.s. 좋은 Tip알려준 yangk에게 감사.. ^^

Synopsys Design Compiler Reference Methodoloty

요새 Tape-Out을 앞두고 있다보니 주로 Synthesis나 Back-end에 대한 글을 많이 쓰게 되네요.

Logic Deginer들이 가장 의존적인 Tool은 Synthesizer가 아닐까 합니다.
그중에서도 Synopsys의 Design Compiler가 Golden Rererence라고 할 수 있겠습니다.

하지만, Design Compiler도 버젼마다 명령이나 constraint가 추가되기고 없어지기도 하는데, 더 좋은 기능이 만들어진 이유이긴 하겠지만 잘 사용하던 기능들이 없어지면 당혹스럽지요.

제품을 만드는 입장에서는 최신기술보다는 안정적인(stable)기술을 더 선호하게되기 때문에 안쓰던 기능을 처음 쓰기는 쉽지않습니다.

Design Compiler는 일년에 두어차레 upgrade가 되는데 최근 버젼보다는 SP(Service Pack)이 한두번 나온 한세대 이전 version을 쓰는게 좋다고 봅니다.

아무튼 최근 version이 나오면 그때마나 reference manual을 보고 새로 추가된 기능을 확인할 수는 없는 것이기에 Synopsys에서는 Reference Methodology라는 것을 제공합니다.
쉽게말하자면 version별로 제거된 기능과 추가된 기능을 반영한 script sample이라고 할 수 있습니다.

아래 주소에서 download하실 수 있습니다. (SolvNet ID가 필요합니다)

디지털 IP 코딩 가이드라인

디지털 IP 코딩 가이드라인[download] – 시스템센트로이드(ipean)

오늘 이선임이 Google에서 찾아 보내준 자료인데 설계에 유용한 여러내용들을 잘 정리하고 있다.

보려고 맘만 먹고 못보고 있는 Reuse Methodology Manual 에서도 Naming Convention에 대한 내용을 발췌하여 담고 있고, 합성을 위한 Coding방법, Clock사용법등을 쉽게 설명하고 있다.

이자료를 만든 곳은 시스템센트로이드(ipean)라는 곳인데, ETRI에서 spin-off한 벤쳐회사이다. 이곳에서 설계교육에 사용하는 자료인 것 같다. 또, 대학교 3-4학년들을 위해 디지털 설계자료를 무상으로 제공하고 있는데 그 중 일부가 아닐까 한다. (관련정보: 디지털 설계교육 자료를 공개합니다.)

Verilog Coding Style for Synthesis

Verilog Coding Style for Synthesis[download]

“full_case parallel_case”, the Evil Twins of Verilog Synthesis와 마찬가지로 C. E. Cummings씨가 SNUG99에 publish한 것이다.

빠듯한 일정속에서 RTL simulation을 마치고 합성 후 gate-level simulation을 했을 때, waveform view에 unknown value들이 빨간색으로 화면 가득채우고 있다면? OTL….

이 문서는 그런상황이 최소화되도록하기 위한 Verilog Coding방법을 설명하고 있다. 그러나, 몇가지 내용은 글쎄…

1. Incomplete sensitivity list
always블록의 sensitivity list에 입력 signal을 빠뜨려 latch가 발생된 경우는 칩 설계경험이 있다면 알만한 내용이다.

2. Complete sensitivity list with mis-ordered assignment
always블록 내에서 assignment의 순서가 뒤바뀐 경우. 즉, assignment들의 순서에 따라 결과가 달라지는 경우를 설명. 먼저 기술된 assignment의 결과가 나중 기술된 assignment에 사용되지않도록 순서를 정하라고하는데, 이것은 Non-blocking assignment를 사용하면 근본적으로 해결된다.

Donny’s Guideline: always블록내의 모든 assignment는 non-blocking assignment를 사용한다.

즉, ‘=’ 가 아니라 ‘<=’를 사용하라는 의미이다. Concurrent한 동작이 일어나는 hardware을 sequential하게 기술하는 것 자체가 말이 안되기 때문이다.

3. Functions
Function을 잘못기술하면 latch가 발생된다는 내용. 그러나, 합성할 회로에 굳이 function을 사용할 필요가 있을까? 합성후 function은 말그대로 기능블록이 되어야하므로 차라리 별도의 module로 만드는 것이 구조적인 이해나 analisys가 쉽다고 생각한다.
Donny’s Guideline: Synthesis할 부분에 대해서는 function을 사용하지 않는다.

4. Full Case / Parallel Case
“full_case parallel_case”, the Evil Twins of Verilog Synthesis에 기술된 내용의 요약판.
Donny’s Guideline: synopsys full_case나 parallel case directive를 사용하지 말자.

5. casex, casez
casex 대신 casez를 사용하라. casex의 경우 입력이 unknown(‘x’)일 때도 정상적으로 동작하는 경우가 존재한다는 내용이다. casez의 경우에도 입력이 floating (‘z’)인 경우는 동작하지만 이런 경우는 덜 빈번하므로 casez를 쓰는 것이 좋다고 하는데… 과연??
RTL simulation만 할 경우에는 입력이 unknown상태가 될 가능성이 없으므로, RTL과 gate-level을 혼합하여 simulation하는 경우만 해당되는 내용이다.
반대로 casez를 사용하려면 don’t care를 표기하기위해 ‘x’대신 ‘?’를 사용해야하는데, 복잡한 case문을 즐겨사용하는 내 경우엔 ‘?’사이에 섞여있는 ’0′을 발견하기란 쉽지 않기 때문에 casex를 더 선호한다.

6. Assigning ‘x’
‘x’값을 입력시키면 simulator에선 ‘unkown’으로 인식되고, synthesizer에서는 ‘don’t care’로 인식한다. 특별한 경우가 아니라면 일부러 ‘x’를 입력하는 일은 안하는게 상책.

7. translate_off/translate_on
이 directive를 사용하면 synthesizer에서 해당부분을 읽지(translate)도 않으므로 당연히 주의해서 사용해야한다. 주로 debugging과 관련된 code나 simulation model을 사용할 때 사용되는데, 가급적 debugging code는 testbench쪽으로 옮기면 위 directive를 사용할 일이 매우 적다.
Donny’s Guideline: 합성할 code와 시뷸레이션할 code를 분리하여 가급적 translate_off / translate_on를 쓰지 말자.

8. Timing Delays
합성시 모든 timing 정보는 무시된다. (두말 하면 잔소리)
Donny’s Guideline: Timing정보를 합성에 반영하고 싶다면 dc_script_begin/dc_script_end를 이용하여 code상에 constraint를 함께 기술하는 방법도 있다.

정리하자면 복잡하거나 특별해보이는 기능을 사용하여 설계하면 그만큼 문제가 발생할 소지가 크다는 것이다. 이러한 guideline을 준수하여 code를 작성한다면 시행착오를 어느정도 줄일 수 있다.

하지만, 아무리 HDL이란 언어를 잘 사용하더라도 회로를 설계하는 것은 C프로그램을 작성하는 것은 차이가 많기 때문에 언어이외에 회로에 대한 개념을 숙지하는 것이 필수적이다.

이러한 복잡한 Guideline보다도 더 강력한 방법이 있는데 Synopsys의 HDL Compiler를 사용하는 것이다. Design Compiler에서 Verilog코드를 읽어들이면 화면에 글씨들이 잔뜩지나가는데 처음에는 대개 이 내용을 무시한다. 하지만, 그 내용이 HDL Compiler의 합성결과이고 합성시 문제가 될만 한부분을 미리 다 알려준다. 즉, case statement가 full case인가 parallel한가 latch가 생성되는가 flipflop이 생성되는가 모든 정보를 알 수 있다.

따라서, 이 내용을 무시하고 합성후 gate-level simulation을 하는 것은 미리 알 수 있는 문제를 확인사살하는 시간 낭비일 뿐이고, 주의깊게 결과를 확인하지않으면 문제를 방치한채로 Tape-out하는 최악의 상황에 이를 수 있다.

의도치 않게 latch가 생성되었는데 이 latch의 입력을 testbench에서 바꾸어보지 않는다면, latch의 영향이 나타나지 않는다. Code Coverage를 확인하여 문제를 찾는 방법도 있겠지만, 처음부터 RTL 코드 작성을 잘하고 합성시 HDL Compiler결과만 확인한다면 근본적으로 문제를 해결할 수 있다.
Donny’s Guideline: HDL Compiler결과를 꼼꼼히 확인하자

사악한 쌍둥이 full_case와 parallel_case

원제은 “full_case parallel_case”, the Evil Twins of Verilog Synthesis 이다. [download]

RTL 시뮬레이션과 gate-level 시뮬레이션 결과가 달라지는 이유가 무엇일까? 그 중 한가지는 case문의 잘못된 사용때문이다. 이것이 얼마나 중요한 것인가는 저 페이퍼의 제목만 봐도 알 수 있다. 오죽하면 ‘사악한 쌍둥이’라고 했겠는가? 또 이 페이퍼는 SNUG-1999에서 Best Paper로 선정된 것을 봐도 짐작할 수 있다.

Verilog를 잘 다루는 설계자라면 분명 if-else문보다는 case문을 선호할 것이다.
Design Compiler에서 합성을 해보면 초기 HDL Compile단계에서 각 case문에 대하여 아래와 같은 내용을 출력한다.

Verilog합성을 하면서 이 내용을 그동안 눈여겨보지 않았다면 앞으로는 꼭 확인하길 바란다.
case문은 잘 사용하면 매우 강력한 능력을 발휘한다. 하지만 잘못사용하면 그만큼 애를 먹이는 존재이다. 근본적으로는 RTL 기술을 잘하면 문제가 없지만, 이를 돕기 위해서 Synopsys는 “//synopsys full_case parallel_case” 와 같이 RTL내에 directive를 사용할 수 있도록 하였다.

문제는 이 directive들을 어떻게 사용함에 따라 같은 RTL코드라도 합성결과가 달라진다. 설계자를 돕기위한 이 기능이 ‘사악한 쌍둥이’가 된 이유는 시뮬레이션시에는 이 directive들이 반영되지 않기 때문에 gate-level시뮬레이션과 차이를 만들기 때문일 것이다.

더 자세한 설명은 다음 기회로 미루고, 쉽게 설명되어있는 내용이므로 직접 읽어보길 권한다.  [download]