電気回路/HDL/Verilogメモ の変更点
更新- 追加された行はこの色です。
- 削除された行はこの色です。
- 電気回路/HDL/Verilogメモ へ行く。
- 電気回路/HDL/Verilogメモ の差分を削除
[[電気回路/HDL]]
#contents
* 内部信号線を pullup / pulldown できないのでその対処法 [#sdffefa8]
以下は Xilinx ISE 14.2 で試した結果です。
** pullup/pulldown の基本 [#c4a046bf]
Verilog ではバス信号線などを pullup / pulldown
で引っ張ることにより、すべてのドライバが highZ
の時の値を 1 または 0 に決められることになっています。
通常そのようなトライステートなバスは
FPGA 外部に出て行く信号線を記述するときに使います。
外部ピンをトライステートにする場合とは対照的に、~
FPGA 内部のネットを疑似トライステート的に記述した場合には、
その回路は論理合成時に マルチプレクサ/and/or などの論理回路に置き換えられて、
「結果的にトライステートの場合と同様の動作をするよう」取りはからってもらえます。
たとえばこんな回路。
LANG:verilog
wire oe1, oe2, oe3;
wire [BUS_BITS-1:0] data1, data2, data3;
wire [BUS_BITS-1:0] bus;
assign bus = oe1 ? data1 : {BUS_BITS{1'bz}};
assign bus = oe2 ? data2 : {BUS_BITS{1'bz}};
assign bus = oe3 ? data3 : {BUS_BITS{1'bz}};
これは次のような警告を出しつつ問題なく論理合成できて、
LANG:console
WARNING:Xst:2042 - Unit main: 8 internal tristates are replaced by logic (pull-up yes): bus<0>, bus<2>, bus<3>, bus<4>, bus<5>, bus<6>, bus<7>.
デフォルトでは pullup されているかのごとく highZ 時の値は 1 になります。
これを明示的に pulldown するには、Verilog 文法的には
LANG:verilog
// bus 信号線を pulldown して、何も出力されないときは 0 とする
generate
genvar bus_pull_i;
for(bus_pull_i=0; bus_pull_i<BUS_BITS; bus_pull_i=bus_pull_i+1) begin: bus_pull
pulldown(bus[bus_pull_i]);
end
endgenerate
を付け足せば良いことになるのですが・・・実は後述の通りこのコードは論理合成できません。
もちろん 3 つの assign と pulldown をまとめて
LANG:verilog
assign bus = oe1 ? data1 :
oe2 ? data2 :
oe3 ? data3 :
{BUS_BITS{1'b0}};
と書いてしまえば論理合成可能で、得られる結果も同じなのですが、
data1, data2, data3 をバスに繋ぐコードは通常
あちこちのモジュールに分散しているので、
pulldown で「それ以外」の場合を一度に書けたらうれしいと。
** 内部信号線に付けた pullup/pulldown は論理合成できない [#fb524492]
上記のコードを論理合成しようとすると、
Synthesize でエラーになります。
LANG:console
ERROR:Xst:850 - "main.v" line 40: Unsupported gate instantiation.
Verilog のゲートプリミティブ記述 pulldown の代わりに PULLDOWN モジュールを使って
LANG:verilog
generate
genvar bus_pull_i;
for(bus_pull_i=0; bus_pull_i<BUS_BITS; bus_pull_i=bus_pull_i+1) begin: bus_pull
PULLDOWN bus_pd(.O(bus[bus_pull_i]));
end
endgenerate
のように PULLDOWN してやると、Synthesize は通るようになります。
でも Translate で
LANG:console
ERROR:Xst:2617 - Data Corruption(Timing): Arrival time traversal failed on Ugate element
となってやはり論理合成できない。
どうやら PULLDOWN/PULLUP モジュールは IOB に対するプルアップ・プルダウン制約に
特化した記述なようで、内部信号線には使えないみたいです。
** そこで対処法 [#bbe7f2de]
すみません。
2012/11/06 まで、うまくいかない対処法が書かれていました。
結局よく調べてみると Verilog レベルでできる対処は無いようでした。
仕方がないので Xilinx ISE 固有の対処法になってしまうのですが、
http://forums.xilinx.com/t5/Synthesis/problem-of-quot-INOUT-quot-use-quot-internal-tristates-are/td-p/122342
によれば、
- Xilinx ISE ではトライステートバスを論理回路に直す時、
デフォルトでは pull up が指定されるため、pull up
で構わなければ明示的な指定は必要ない
- これを pull down にするためにはネットにtristate2logic_pullup属性を指定すれば良い
- tristate2logic_pullup属性はあくまで論理合成時にしか働かないので、
シミュレーション用には明示的に pull up/pull down を書く必要がある
ということのようです。
LANG:verilog
(* tristate2logic_pullup = "yes" *)
wire [BUS_BITS-1:0] bus_pulled_up; // 論理合成時には暗黙で pullup される
(* tristate2logic_pullup = "no" *)
wire [BUS_BITS-1:0] bus_pulled_down; // 論理合成時には暗黙で pulldown される
`ifdef XILINX_ISIM
// シミュレーション用には明示的に pull しておく必要がある
generate
genvar bus_pull_i;
for(bus_pull_i=0; bus_pull_i<BUS_BITS; bus_pull_i=bus_pull_i+1) begin: bus_pull
pullup(bus_pull_up[bus_pull_i]);
pulldown(bus_pull_down[bus_pull_i]);
end
endgenerate
`endif // XILINX_ISIM
どなたか、普通ならこうするよ、とか、もっと良い方法があるよ、とかあれば教えて下さい。
* コメント [#i0f2cd0c]
#article_kcaptcha
**PLtojPYggWzE [#l6a17b2f]
>[Farruco] (2013-01-06 (日) 20:25:37)~
~
Ppl like you get all the brains. I just get to say tahkns for he answer.~
//
#comment_kcaptcha
Counter: 27423 (from 2010/06/03),
today: 3,
yesterday: 5