プロが教える店舗&オフィスのセキュリティ対策術

verilog初心者で、(2の補数形式)符号付加減乗算器を作成しています。

…が符号拡張のところで解決できずにいます f(--;)
もとの数a,bの最上位ビット(符号ビット)を16ビット分(乗算器に
あわせ)増やすことは理解できたのですが、それをどうverilog
記述すればいいのかわかりません。下記にある記述ではエラーと
なってしましました。
0拡張や、演算結果の最上位ビットだけを符号ビットにしてみたりし
たのですが、これではダメとのことで もうどうやったらいいのか
わからなくなってきました。(TT);

どなたか教えてください。
m(_ _)m
--------------------------------------------------------------
module kadai(a,b,c,q);
input [15:0] a,b;
input [2:0] c;
output [32:0] q;
wire [32:0] q;

assign q =(c == 3'b000)?{16{a[0]},a}+{16{b[0]},b}:
(c == 3'b001)?{16{a[0]},a}-{16{b[0]},b}:
     (c == 3'b010)?{16{a[0]},a}*{16{b[0]},b};
endmodule
----------------------------------------------------------------
{16{a[0]},a}や{16{a[0]},b}という表現がいけないようなのですが…
よろしくお願い致します。

A 回答 (3件)

1です。


ちょっと意地悪な物言いでしたね。ゴメンナサイ。
例えば4bitの符号を8bitに拡張するときは、結局のところ
{a[3],a[3],a[3],a[3],a[3],a[2],a[1],a[0]}と左側にどんどん一番左のbit(MSB)を加えていけばよいのです。
これを見やすく書いたのが { {4{a[3]}},a[3:0] }ということですよね。
加減算は符号拡張して左右のbit幅さえ合わせておけば問題なく演算できます。
q[32:0] = (aを33bitに符号拡張) + (bを33bitに符号拡張);
です。aもbもqも同じbit幅にするのです。これだと溢れるような気がするかもしれませんが、こうしないと符号付加減算はおかしな事になります。

乗算はもっと面倒で、
wire absa[bit幅は考えてね],absb[bit幅は考えてね];

absa = a[MSB] ? (~a[MSB以外])+1 : a[MSB以外];
absb = b[MSB] ? (~b[MSB以外])+1 : b[MSB以外];
として absa*absb を演算し、最後にaとbの符号に応じてまた符号反転してください。

こういう書き方だと、実際のハードウェアに即してない気がするかもしれませんが(実際のハードは大抵符号付乗算器マクロを持っているので)、
コンパイラは優秀なもので、ちゃんと判断してマクロを割り当ててくれます。

この回答への補足

ありがとうございます!bit拡張はうまく行きました!!
しかし乗算でかなり引っかかっていました(--;)1日つぶれです…
いまはわからず下記のように書いていますが上位ビットが計算さません。(TT)
----------------------------------------------------------------
assign q =(c == 3'b000)?{{16{a[15]}},a}+{{16{b[15]}},b}:
(c == 3'b001)?{{16{a[15]}},a}-{{16{b[15]}},b}:
(c == 3'b010)?{a[15]^b[15],((a[14:0])*(b[14:0]))}:
(c == 3'b011)?{{16{1'b1}},~a}:
(c == 3'b100)?{{16{1'b1}},~b}:
:
:
---------------------------------------------------------------
これの「 {{16{a[15]}} 」のところを33bitなので「 {{17{a[15]}} 」とすればいいわけですね。これはすぐにうまく行きそうです!!(^^)
乗算に関しては…
やはり時間がかかりそうです。いま2度読んでみましたが理解できません。
absについてあしたよく調べてみます!!
ありがとうございますm(_ _)m

補足日時:2008/01/24 18:15
    • good
    • 0

1です。


以前の質問に要求仕様がありますね。33bit幅の出力、というわけですね。

入出力にレジスタ、って書いてありますよ。レジスタっていうのは曖昧な表現でどうとでも取れるのですが、恐らくFFのことでしょう。
外側でFFつけてください。kadai点数もらえませんよ。

33bit出力というのが非常に意地悪なところですね。
手抜きをすればどうという事はありませんが、冗長になるので点数は下がります(要するにほとんど意味の無いbitがあります)。
現実には「コンパイラが最適化するので手抜きできるところは手抜きをする」が正解ですが、大学の課題じゃそうもいかないでしょう。

しかし、仕事といいながら kadai って・・・
    • good
    • 0
この回答へのお礼

早速のご回答ありがとうございます。
仕事で与えられた課題です^^;大学生じゃありません。
悪しからず
FFではないらしいです。記述の途中経過を見せたところ
assign文でいいようなので。

お礼日時:2008/01/24 13:13

{{16{a[0]}},a[15:0]}


のように、括弧を追加してください。
{16{a[0]}} というように、bitの繰り返し記述の外側が {}で囲まれてないと文法エラーです。たしか。
あと、どのようなものをお考えか判りませんが通常符号拡張はMSBです。
a[15]ではないですか?

それから拡張が16bit+16bitで32bitしかありません。1bit足りていませんね。

それよりも、乗算 * は、符号つきだと意図した演算にはならなと思います。たぶん。

絶対値をとって乗算し、符号付きに直す、というのが常道です。
符号同士の演算ははxorで判りますので。

あと、16bit signed x 16bit signed は 最大で31bit signedですね。
33bitも必要ないです。(要求仕様が33bitなのかもしれませんが)

以上はverilog1995まででの話です。2001は符号付きの型があります。

※頭で考えただけで確認はしておりません。勘違い等があればゴメンナサイ
    • good
    • 0
この回答へのお礼

{{16{a[0]}},a[15:0]}
なるほど、このように書けばいいわけですね!!
{}が足りていませんでしたか。
あと「a[15]ではないですか?」ですが
知りませんでした(^^)ありがとうございます

以下については半分理解できますが、書けるかどうか心配です
がんばってみます!!
環境はverilog1995だと思います。
そこまで気を使っていただいてありがとうございました
m(_ _)m

お礼日時:2008/01/24 13:17

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!