2008/08/22(金)[ISE] Verilog Simulation(ISim)

概要とか問題とか

今回,試行錯誤して遊んだメモなので,ワークフローではありません.いじくっているうちに慣れたり覚えたりしますよねぇ?.基礎知識が不足しているからこうして下積みを・・・(^^;

Post Route Simulationにて,配置配線で問題が生じたかを確認する.
Timing Constraintsの設定はClockしかしていない.設定不足か?
また,behavior simulationで得られた期待どおりの波形が見えない(出力信号).

ざっとまわして,いくつか出てきた.どれもこれもsetup time/hold time違反の模様.コレを見て,配置配線前にエラーが出ていなかったので,おかしいなぁと思いつつ,Warningのとり方を調べていた.

WARNING:Simulator:29 - at 6.000350773 ms: Warning:  Timing violation in
   /TST_BSC/uut/\TPU_1/TADD_buf_14 /  $setuphold<setup>( I:6.000350768 ms,
   CLK:6.000350773 ms,132.000 ps,48.000 ps)
WARNING:Simulator:29 - at 6.000350773 ms: Warning:  Timing violation in
   /TST_BSC/uut/\TPU_1/TADD_buf_15 /  $setuphold<setup>( I:6.000350736 ms,
   CLK:6.000350773 ms,132.000 ps,48.000 ps)
WARNING:Simulator:29 - at 6.000380773 ms: Warning:  Timing violation in
   /TST_BSC/uut/\RAM1K_1/RAMB16_S18_inst /  $setuphold<setup>( ADDR:6.000380571
   ms, CLK:6.000380773 ms,377.000 ps,131.000 ps)
WARNING:Simulator:29 - at 6.000380839 ms: Warning:  Timing violation in
   /TST_BSC/uut/\RAM1K_1/RAMB16_S18_inst /  $setuphold<hold>( CLK:6.000380773
   ms, ADDR:6.000380839 ms,377.000 ps,131.000 ps)

半日以上うろうろしていたけれども,最終的には問題ないという見解に落ち着く.おそらくskewにより,使用しない信号を拾うタイミングで発生していると思われる.ポートから受けたデータをDFFでラッチし,その次のサイクルで内部の所望のレジスタへと転送するように実装してある.ところが,今回の箇所は,ポートからラッチするタイミングでviolation警告が出る.DFFにラッチするタイミングがわずかに早くなり,その後段にあるDFFへと信号が先行してしまって,posedge CLKが入ったのではないだろうか.
裏づけを取るにはシミュレーション時に該当信号をモニタする必要があるわけだが,その手段についてもわからなかった(現在進行形).

とりあえず,検証モジュール(タスク)で,インスタンス名をドットでつないで内部信号をassignして観測しようとしています.が,なんだか調子悪いような・・・.DCMを使っているせいもあり,5mSec強の待ち時間を作りこんでしまった.当該回路を取り去ると挙動が変わる恐れもあり,実行していない.*1

Warningの意味

合成/シミュレーションデザイン ガイド

WARNING:Simulator:29 - at 6.000350773 ms: Warning:  Timing violation in
   /TST_BSC/uut/\TPU_1/TADD_buf_15 /  $setuphold<setup>( I:6.000350736 ms,
   CLK:6.000350773 ms,132.000 ps,48.000 ps)

clock skewによるwarningと判断する.SHからのWRアサート→ネゲートを検出して,データをラッチして,次のCLKでTPU moduleに書き込み要求を出す.(module向けのWRはネゲートされたまま.DFFの貫通が起きればその限りではない?が,次のCLKで書きにいくのでおk.bufferにしてあるから1clk間化けても大丈夫)



*1 : シミュレーション時間がかかりすぎるので,削るようにもしたほうがいいナ.

少し解決

シミュレーションに時間を要していた件,DCM出力が出てこないのは時間のせいと思い込んでいましたが,リセットがかかっていなかった模様.
リセット信号がnegedgeなのにt=0から0で100nSecおいて1にしてました.そりゃ非同期リセットかからない罠('A`.

次に,timing violation.下位モジュールで別クロックを作ってしまっていました.同じクロックと期待して表示させたのに0.7nSecもずれている.10nSec周期なので,7%誤差ですね.コレを削ればviolationも消えるかもしれませんし,そもそも非同期になっていては設計想定が崩れます.

DCMにするか,クロックバッファを通してやるのが無難でしょうかねぇ.DCMもったいないかな・・・?分周して同窓にあわせようとすれば,これしかないか.出力にDFFかましても位相ずれるには変わりないしねぇ.


ISE 10.1のmanual類

日本語版は,ここらへんに落ちてます.

http://japan.xilinx.com/support/software_manuals.htm

module

2008/08/20Verilog::文法import

module文(synthesizable/TestBench)

概要

階層化設計の一塊.入出力信号・パラメータを引数として、実体化する.
順序回路・組み合わせ回路の0個以上の組み合わせの回路ブロックを記述する.

書式

ANSI式*1を以下に示す.

module <module-name> (
   input foo,
   output bar,
   inout bus
  );
  // local signal/variable...
  begin
   // 式
  end
endmodule

それ以前の書式は以下のように記述する.

module <module-name> ;
   input foo,
   output bar,
   inout bus
// (略)
endmodule


*1 : ANSI-Cの関数記述相当.K&R時代は変数だけを並べて,型+変数名は後に記述した.Verilogでも、module名だけでセミコロンを打ち,信号名を並べてからbegin文を置く記述も可能.

moduleのパラメタ変更方法

パラメタの使い方を理解しておらず,つい最近に例を見かけて知ったので記載しておく.
defineとは違い、インスタンス化する際に値を変化させて利用することができる,と推測する.

  • defparam文
  • instance化する際に, 渡す.
     module-name #(
    		.paramete-name(value),
    		...
    	) instance-name (
    		.signal-name(symbol),
    		....
    	) ;
    

※インデントはxilinx webpack 10.1sp2の自動生成ツールの出力を真似た.

wait

2008/08/20Verilog::文法import

待ち処理(TestBench)

Test記述時に有効. 式の評価結果が TRUEになるまで待つ.
initial文でクロックに同期して処理をさせたい場合に使うとよさそう. @(posedge CLK)で十分です.

  always #20 CLK <= ~CLK;

  initial begin
   ...
   wait( CLK==0 );
   wait( CLK==1 );
→ @(posedge CLK);
  # 2  // CLK's posedge + 2 [nSec]
   hoge <= 1;
   ...
  end

wait(式?)

前述のとおり.


@ (式?)

式の状態を待つ?立ち上がり:posedge
立ち下り:negedge
などなど...と思う.調べてないけれども使ったものだけ記述.サイトではなく仕様書を見て転記してこないと、ですね.

task

2008/08/20Verilog::文法import

書式

task <name>;
	// input ; 値渡し. 呼び出しもとのreg等に影響を与えない.
	// output

	// process...
endtask

syntax

task_declaration ::= (From Annex A - A.2.7)
   task [ automatic ] task_identifier ;
     { task_item_declaration }
     statement
   endtask
 | task [ automatic ] task_identifier ( task_port_list ) ;
     { block_item_declaration }
     statement
   endtask

task_item_declaration ::=
  block_item_declaration
  | { attribute_instance } tf_input_declaration ;
  | { attribute_instance } tf_output_declaration ;
  | { attribute_instance } tf_inout_declaration ;

task_port_list ::=
  task_port_item { , task_port_item }

task_port_item ::=
  { attribute_instance } tf_input_declaration
  | { attribute_instance } tf_output_declaration
  | { attribute_instance } tf_inout_declaration

tf_input_declaration ::=
  input [ reg ] [ signed ] [ range ] list_of_port_identifiers
  | input [ task_port_type ] list_of_port_identifiers

tf_output_declaration ::=
  output [ reg ] [ signed ] [ range ] list_of_port_identifiers
  | output [ task_port_type ] list_of_port_identifiers

tf_inout_declaration ::=
  inout [ reg ] [ signed ] [ range ] list_of_port_identifiers
  | inout [ task_port_type ] list_of_port_identifiers

task_port_type ::=
  time | real | realtime | integer

block_item_declaration ::= (From Annex A - A.2.8)
  { attribute_instance } block_reg_declaration
  | { attribute_instance } event_declaration
  | { attribute_instance } integer_declaration
  | { attribute_instance } local_parameter_declaration
  | { attribute_instance } parameter_declaration
  | { attribute_instance } real_declaration
  | { attribute_instance } realtime_declaration
  | { attribute_instance } time_declaration

block_reg_declaration ::=
  reg [ signed ] [ range ]
  list_of_block_variable_identifiers ;

list_of_block_variable_identifiers ::=
  block_variable_type { , block_variable_type }

block_variable_type ::=
  variable_identifier
  | variable_identifier dimension { dimension }


概要

  • 記述はmoduleとほぼ同じ. 許容される型/process文が増える程度.
  • 引数は宣言した順に渡される.名前渡しも可能.(ドット+名前(信号))
  • input引数は値渡しになる.呼び出し元に影響はでない.
  • inout/outputは代入すると呼び元に値を返すことができる.[LRM 10.1]
  • 実回路としてsynthesize不可. simulation modelでのみ使用可能
  • "#値"による待ち処理を入れることができる. task呼び出し元は, task内で消費した時間の後に返ってくる.

その他メモ

if文を用いて、条件によって待ち時間を変化させることもできる.ex.

  if (t_AD > t_CS)  begin
    # (t_CS)
    CS_n <= 0;
    # (t_AD - t_CS)
    ADR <= ADR_buf;
  end
  else begin
    # (t_AD)
    ADR <= ADR_buf;
    # (t_CS - t_AD)
    CS_n <= 0;
  end

※CS_nとADRの変化時間が、パラメタt_ADとt_CSの大小関係により前後するため、分岐させた.後日,CPUバスの試験パターンを振るための例を示す.waveformを外部プログラムで吐いて,取り込んだほうが早かった気がするけれど。。。

2008/08/13(水)[ISE] Behavioral Simulation

Verilog Test Fixture新規作成

Sourcesウィンドウにて, 右クリック → 新規ファイル → Verilog Test Fixtureと選択すれば, テスト対象モジュールを指定することができます.
インスタンス名をuutとして, 自動的にテンプレートを作ってくれるので手を抜くには便利です.
とはいえ, テキストエディタで先にパターン作っていたので, 殆ど流用できずに終わりましたが...

記述

テストを行うmodule宣言では, 引数の宣言は不要です.

ex.
  module TST_BSC;

モジュールの入力に対しては regで変数を作成, 出力に対してはwireで変数を作成. bidirectionalについては, reg/wireを作ってassign文でtri-stateを作っておきます(これでいいんだよなぁ?)

 wire [15:0] D;
 reg SH_OE ;
 reg [15:0] SH_DATA_OUT ;	// OUT means from test-module to FPGA

 assign D = (SH_OE ? SH_DATA_OUT : 16'hZZZZ);

SH2-7144の外部バスタイミング

データシート(Rev.4.0 2008年3月27日, rjj09b0026_sh7144.pdf)を参照し, 26.3.4 バスタイミングのあたりを注視します.
ちなみに, どこぞのIF誌で外部SRAMのタイミング検討はアクセスサイクルが十分だからOKといった記述がありましたが,個人的には納得できません. RD/WR信号とデータ・アドレスのアサートタイミング、セットアップ・ホールドタイムについての検討が説明されていないからです.

動作クロックφ(CK)との関連が示されていますが, このクロックに同期させればOKというわけではなさそうです.
最大遅延25nSecとか28nSecとか, すでに1クロック過ぎているじゃありませんが... どう考えても1waitは必須です.
詳細は割愛しますが, とりあえず 1wait必須, 場合によっては連続アクセスウェイトも入れてやる必要がありそうです.
CSアサートの遅延機能は使用せずにすみそうですね.

さて, コレを元にWRITE時の試験データを作りましょう.イロイロと考えてパターンをふるべきですが, とりあえずイチバンきつそうなWRアサート期間の短いものを作ってみましょう.

条件

  • BUS wait cycle = 1
  • CSアサート期間拡張機能無効

このとき, テストはこんな感じになるハズ.. と, datasheetと睨めっこしていると 少し疑問が.悪いほう悪いほうに考えて居れば良いだろうナ.

	# 0							// CK upedgeとみなす.
		SH_OE  <= 0;

	# 25
		SH_ADR  <= 22'h000088; // "t_AD" ADR fixed Max.25nSec from 1st CK-up
		SH_DATA <= 16'h0008; // こっちはついで.

	# 3	//+28						// "t_CSD1" CS assert Max. 28nSec from 1st CK-up
		SH_nCS  <= 0;

	# 7 	//+35		// (SH_CLK/2) + Max.25	// "t_WSD" WR assert Max. from 1st CK-down + 25nSec
		SH_nWRH <= 0;
		SH_nWRL <= 0;

	# 5	//+40		// (SH_CLK/2) + Max.30	// "t_WDD" Data drive Max. from 1st CK-down + 30nSec
		SH_OE  <= 1;
	# 10	//+50,75	// WR disassert "t_WSD2"<25 => (1.5+1)*20 +0/+25 = 50-75 from 1st CLK-up T2終了までにdisassertされるのが普通? 75だと+15..
		SH_nWRH <= 1;
		SH_nWRL <= 1;
	# 5	//+55,80(Tidle挿入せよ)	// "t_WR" >5 CS disassert (FPGAでサンプリングできない?ケース)
		SH_nCS  <= 1;
	# 5	//+60, 3cycle終了
		SH_OE <= 0;		// T2終了時+0以上でdisassert

XSTのシミュレーションで確認すると, 下記のような結果を得ることができました.波形を出すまでに moduleの修正を行っていたので, 結構な時間を要しました...
途中で別の記事(書評/AA作成/LIVE FORMULA鑑賞)なんぞを平行していたせいもありますが.

XST_SH2BSC_01.PNG

配置配線後のまっとうな(?)シミュレーションではないので, あくまでも記述上問題がないという確認だったはず.
配置配線後のシミュレーションをやっておかないと, SetUp/Hold timeの不足がある場合は不定にしてくれたはず...ろくすっぽmanualも見ずにかなり昔の記憶で触っているのが酷いかな. XC9500シリーズで遊んでいた頃まで遡るわけで.

時間も時間なので, ひとまずここまで. 本当に手ぶらで行くことになりそうだなぁ. それは非常に負けた感がするな.



おちまくるXST-Sim

process explorerisimwavedata.xwvを探してみます. _pn.exeが掴んだままのようですね.
おk. 把握. 通常のタスクマネージャでも_pnを殺せばメモリも開放される模様です. 同じようにはまった方はコレで解決..

Process explorerダウンロード