日曜日, 7月 29, 2007

アドレスデコーダ

ここでの"デコーダ"とは、アドレスをデコードしてチップセレクト信号を生成するようないわゆるアドレスデコーダです。

Verilogでの一般的な記述は次のようなものでしょうか?

case(address)
2'd0: chipSelect = 4'b0001;
2'd1: chipSelect = 4'b0010;
2'd2: chipSelect = 4'b0100;
2'd3: chipSelect = 4'b1000;
endcase

この場合、再利用性が少々乏しくなります。
次のような記述方法もあります。

parameter AD_WIDTH = 2;
parameter CS_WIDTH = 4;

input [AD_WIDTH-1:0] address;
output [CS_WIDTH-1:0] chipSelect;

assign chipSelect = 1 << address;

これならパラメータの変更のみで再利用可能です。

ちなみにCSR(コントロールステータスレジスタ)を記述するような場合、
私はアドレスデコーダを明確に記述することはしません。
だいたいこのような感じです。

always @(posedge ICLK or posedge IRST) begin
if (IRST) begin
regControl <= 0;
end else begin
if ((WE)&&(address==ADR_CONTROL))
regControl <= writeData;
end
end

これをデコーダを書いて、セレクト信号を生成して・・・とやると
デコーダ分の記述が増えるだけでなく
次のような記述を見て

always @(posedge ICLK or posedge IRST) begin
if (IRST) begin
regControl <= 0;
end else begin
if ((WE)&&(sel[4]))
regControl <= writeData;
end
end

はたして、セレクト信号のbit4はこのレジスタのものだっただろうか?
とデコーダの記述を見に行く必要もなくなります。

これも抽象化の一例ですね。



しかし、このブログはコードが書きづらい。
preタグと"<<"を一緒に使うと崩れてしまう。
いい方法無いのかなぁ。

火曜日, 7月 24, 2007

組み合わせ回路

verilogで組み合わせ回路を記述する場合、alwaysかfunctionを使うことになると思います。

alwaysを使うとこんな感じでしょうか。


always @* begin: ReadDataMux
case(address)
ADDR_REG_A: readData = regA;
ADDR_REG_B: readData = regB;
ADDR_REG_C: readData = regC;
ADDR_REG_D: readData = regD;
default : readData = 0;
endcase
end


functionを使うならばこんな感じ。


function [7:0] BarrelShift (
input [7:0] dataIn,
input [2:0] shift
);
reg [15:0] rtData;
begin
rtData = {dataIn, dataIn} << shift;
BarrelShif = rtData[15:8];
end
endfunction

ともにVerilog2001を対象に書いています。

alwaysは"@*"が使えるので入力の種類が多いときなどに便利です。
短所は出力をregで宣伝しなければならないこと。

レジスタにならないものをregで宣言しなければならないことは
初心者を十分混乱させてくれます。

また、当初は簡単な組み合わせ回路だからとおもって

assign control = (signal==RED) ? STOP : GO;

と書いていたら、やっぱり安全第一ということで


always @* begin: DriveControl
case(signal)
RED : control = STOP;
YELLOW : control = ATTENTION; // STOP is better.
BLUE : control = GO;
default: control = STOP;
endcase
end


このように変更した場合に、
わざわざcontrolの宣言をwireからregに変えなければならないというのも面倒です。

functionの場合は、function内のみのスコープをもつ変数を使えるところが利点です。
Cでプログラムを書く人などはこちらのスタイルの方が好みかもしれません。

注意点は、ポートリストに入っていなくても同一モジュール内の信号を参照できてしまうことです。
この場合、シミュレーション時にラッチを生成しているような動作をしてしまい、検証の際に非常に痛い目に会うかもしれません。

例えば次のような場合、


function [7:0] FuncOut (input a, input b);
begin
FuncOut = a & b & c; // cはfunction外で宣言
end
endfunction


シミュレーションでは、
入力a,bに変化があった場合は出力も変化しますが
cが変化した時点では出力は変化しません。

両方使い分けれるようになれば、verilog初心者は卒業かな?
それだけで判断できるようことでもないですが。

しかし、verilogはいまだに中途半端な仕様です。

土曜日, 7月 21, 2007

バレルシフト その2

前回の続き

さて、バレルシフタをverilogでどう記述するかというとこんな感じでしょうか?


parameter DATA_WIDTH = 8;
parameter SHIFT_WIDTH = 3;

input [DATA_WIDTH-1:0] iDATA_IN;
input [SHIFT_WIDTH-1:0] iSHIFT;

output [DATA_WIDTH-1:0] oDATA_OUT;

wire [(DATA_WIDTH*2)-1:0] shiftedData;

assign shiftedData = {iDATA_IN,iDATA_IN} << iSHIFT;
assign oDATA_OUT = shiftedData[(DATA_WIDTH*2)-1:DATA_WIDTH];

つまり入力がabcdefghと与えられた場合、まずそれを2つ並べて
{abcdefgh,abcdefgh}

それをシフト。たとえば3つシフトするなら

{defghabcdefgh,xxx}

最後に上位半分だけとって

defghabc

でバレルシフト完成。

ただ、これってどのような回路になっているのか簡単にはわからないですよね。
恐らく、この記述の合成結果は次のようになっていると思います。

wire [DATA_WIDTH-1:0] shift1stDATA;
wire [DATA_WIDTH-1:0] shift2ndDATA;

assign shift1stDATA = (iSHIFT[0]) ?
{iDATA_IN[DATA_WIDTH-2:0],iDATA_IN[DATA_WIDTH-1]} :
iDATA_IN;

assign shift2ndDATA = (iSHIFT[1]) ?
{shift1stDATA[DATA_WIDTH-3:0],
shift1stDATA[DATA_WIDTH-1:DATA_WIDTH-2]} :
shift1stDATA;

assign oDATA_OUT = (iSHIFT[2]) ?
{shift2ndDATA[DATA_WIDTH-5:0],
shift2ndDATA[DATA_WIDTH-1:DATA_WIDTH-4]} :
shift2ndDATA;

つまり、

シフトのビット0で1回シフトするかどうかを判断、

シフトのビット1で2回シフトするかどうかを判断、

シフトのビット2で4回シフトするかどうかを判断、

以上をカスケードに接続してバレルシフトが完了という感じです。

しかし、このように合成してくれるかどうかはツール次第なので
心配だったら後者の記述を直接書いてもいいと思います。

再利用性を考えると前者の方が楽ですね。

火曜日, 7月 17, 2007

バレルシフト その1

食わず嫌いはいけないなと思って、最近はソフトウェア関係の書籍も意識的に読むように心がけています。

その中で"配列の要素の回転"というものがあって、例えば次のような配列があった場合

abcdefgh

これを3要素回転させると結果は

defghabc

となります。

ソフトの場合、エレガントなアルゴリズムがあって
i要素分回転させたい場合、まず配列をはじめのi個と残りのn-i個にわけます。

abc, defgh

次に分割したそれぞれにおいて、要素の並びを逆転します。

cba, hgfed

分割した配列を再び1つにまとめて、

cbahgfed

最後にこの配列全部の並びを逆転させます。

defghabc

すると、見事回転が完成しているというもの。


私のような凡人にとってはこれでちゃんとできているという事実だけでもスゴイと思ってしまうのですが
実行時間やメモリの消費量及びコードのシンプルさという観点からもこのアルゴリズムは優れているとの事です。

で、これをハードウェアにそのまま応用できるか?
というとそううまく行かないのが悲しいところです。

このような操作は、ハードでは"バレルシフタ"と呼ばれるものに相当します。

次回はHDLによるバレルシフタの記述と実装について書いてみたいと思います。

金曜日, 7月 13, 2007

サクッと書いてサクッと検証?

「サクッと書いてサクッと検証」,富士通九州が米Cadenceの形式検証を評価

Tech-On!の記事より。

現場の人が本当にそう思っているかどうかはちょっと疑問ですが。

この自動チェック機能は設計者に評判がよく,リピータが出たほどと由利氏は述べた。
一方で,プロパティを書くことには,大半の設計者が難色を示していると同氏は述べている。

実際のところこのあたりがネックになってくるんだろう。

設計者をどのように教育していくか?

最終的には自分を助けることにもつながるので、プロパティ記述は設計者も積極的に取り入れたほうが良いと思う。
取り入れることができる環境にあるならばの話だけど。

ただ、状態爆発を起こさないレベルの大きさのモジュール単位でフォーマル検証を使って確実に抑えておくという考え方は確かに正しい。

発見される問題は突き詰めてみると単一のモジュールで閉じてしまっているということがほとんどだからだ。

そこさえ押さえておけば、あとはインタフェースを標準化(規格でもいいし、社内独自のものでもいいだろう)することで生産性はかなり上がると思う。

フォーマル検証が使えなくても、数百行程度のモジュールレベルのRTLであればそれほど時間をかけずに徹底的に動的な検証することもできるだろう。

ただし、設計段階で各モジュールに的確な機能分けを行なって、モジュール間の依存関係をできるだけ小さくしておかないと上記の方法もあまり意味が無くなってしまう。

デザインによって、検証労力も雲泥の差が出てくる。

水曜日, 7月 11, 2007

Code Complete 第2版

Code Complete 第2版 上 ― 完全なプログラミングを目指して

Code Complete 第2版 下 ― 完全なプログラミングを目指して

@ITのプレビュー

ソフトウェアのコンストラクション(詳細設計からコーディング、開発者によるテスト・デバッグあたり)に焦点を当てた内容。

豊富な知識と経験に基づいた実践的な内容となっているので、明日使えるものばかりですね。

ソフトウェア技術者向けに書かれていますが、もちろんHDLを主体とするハードウェア技術者にもほとんどあてはまります。

上下巻でかなりのボリュームですが、文章は読みやすいので苦にはならないと思います。
それでもやはり、全て読むのには時間がかかりますが。

"言語の中へのプログラミング"という考え方はちょっと新鮮でした。

「この言語(環境)は不便だ」とあきらめるのではなく、自分の工夫によって状況を改善する。
確かにそれほど難しいわけでもなく、有益な方法だ。

"コンストラクション"に焦点を当てた書籍というのはあまり見かけないので、1度目を通してはいかがでしょうか?

しかし、なんで車の代表が「ポンティアック」なんだろう?

金曜日, 7月 06, 2007

フリーのコードカバレッジツール

Covered

フリー(GPL)のコードカバレッジツールです。
verilogのみ対応。

cygwinにインストールしてみたのでそのメモ。

必要なもの


  • gcc (Version 2.96 or higher)
  • flex (Version 2.5.4 or higher)
  • bison (Version 1.28 or higher)
  • GNU make (Version 3.27.1 or higher)
  • GNU gperf (Version 2.7.2 or higher)
  • tcl and tk (Versions 8.4 or higher) <-この場合は必要ないかも

"covered-0.5.tar.gz"をダウンロードしてきて、以下を実行。
$ gzip -dc covered-0.5.tar.gz | tar xvf -
・・・
$ cd covered-0.5
$ ./configure
・・・
$ make
・・・
$ make install
・・・

以上


サンプルを作って テスト。
適当な場所に展開して、展開後のディレクトリをカレントとしてください。
(VCDファイルはModelSimXEで作成)
$ covered score -t top -v top.v -v decimal_counter.v -vcd top.vcd

Covered covered-0.5 -- Verilog Code Coverage Utility
Written by Trevor Williams (trevorw@charter.net)
Freely distributable under the GPL license

Reading design...
Parsing file 'top.v'
Parsing file 'top.v'
Parsing file 'decimal_counter.v'

Checking for race conditions...

Scoring VCD dumpfile top.vcd...

*** Scoring completed successfully! ***

Dynamic memory allocated: 53710 bytes


$ covered report -d v -m ltcfram -o coverage.rpt cov.cdd

Covered covered-0.5 -- Verilog Code Coverage Utility
Written by Trevor Williams (trevorw@charter.net)
Freely distributable under the GPL license

以上
カレントディレクトリにできた"coverage.rpt"がレポートファイル。
一応、無事に動作している模様。

ただ、"COMBINATIONAL LOGIC COVERAGE RESULTS"で指摘されている部分がなぜ指摘されているか不明。

マニュアルはここ です。

VPIを使ってシミュレーションを実行しながらカバレッジ情報を見たり、GUIでインタラクティブに結果を閲覧したりといったこともできるようですが、上記のインストールでは多分できません。

詳しくはマニュアルをご覧ください。

木曜日, 7月 05, 2007

SystemCのインストール

これから少しずつSystemCの勉強もしてみようかと思い、cygwinにインストールしてみたのでそのメモ。

本当はLinux(OpenSUSE 10.2)に入れようかと思ったのだけれども、うまくいかなかったので。

gccのバージョンが悪かったのだろうか?

ちなみにcygwinのgccは3.4.4だった。

まず、OSCI からsystemc-2.1.v1.tgzをダウンロードする。

適当なディレクトリで以下のコマンドを実行。


$ tar xvzf systemc-2.1.v1.tgz

・・・

$ cd systemc-2.1.v1

$ mkdir objdir

$ cd objdir

$ mkdir /usr/local/systemc-2.1

$ export CXX=g++

$ ../configure --prefix=/usr/local/systemc-2.1

・・・

$ make pthreads

・・・

$ make install

・・・


以上。


実行するには以下のコマンド

$ export SYSTEMC=/usr/local/systemc-2.1
$ g++ -I. -I$SYSTEMC/include -L. -L$SYSTEMC/lib-cygwin -o sim hello.cpp -lsystemc -lm
$ ./sim

"Hello World."が表示されればOK。

サンプルのプログラムはこちらのサイトのものを使わせていただきました。

*$make の部分を $make pthreads に修正しました。
 なつたんさんのブログを参照

水曜日, 7月 04, 2007

リセットの論理を切り替える方法

会社によって、またはプロジェクトによってリセットの論理は正論理か負論理に分かれます。

モジュールの再利用性を考えると不便ですよね。

そこで次のような方法をとりましょう。

`define RESET_EDGE posedge
`define RESET_ON 1'b1

always @(posedge clk or `RESET_EDGE reset) begin
if (reset==`RESET_ON)
Q <= 1'b0;
else
Q <= D;
end

これが正論理の場合。

負論理に変更したい場合は、

`define RESET_EDGE negedge
`define RESET_ON 1'b0


とする。

もちろん、プロジェクト内でリセットの論理が統一されていることが前提です。

火曜日, 7月 03, 2007

Verilog Mode

エディタは何をお使いですか?

ソフトの言語に比べてHDLに対応しているエディタって少ないですよね。

私は普段Windows上で作業をしていますが、エディタはMeadowを使っています。

これは以前、VHDLをメインで使っていたときにEmacsだとデフォルトでvhdl-modeが付いていたのでそれがきっかけで使い始めました。

Verilogに対応するverilog-modeは標準では付いていませんが、こちらから入手できます。

インデントやカラーリングだけでも便利ですが、/*AUTOARG*/などで自動的にポートを挿入してくれる機能などは面倒な作業を削減してくれます。

インストール方法と使い方は以下のサイトが詳しいです。

Verilog modeのインストール

Verilog modeの機能

良い道具を選択するのもエンジニアの能力のひとつです。
楽できるところは積極的に楽をしましょう。

数年前にいた会社では、Windowsのメモ帳でAHDL(Altera Hardware Description Language)を書いていた人がいましたorz