msbitの実行ビットは、それ自体が符号なしでカバーされていると思います。符号付きの場合は、msbitへのキャリーインとキャリーアウトが異なるかどうかを確認してください。
結果が使用可能なビット数に適合するため、5-0はオーバーフローしません。15-1が符号付き数値の4ビットシステムをオーバーフローしないのと同じ方法
5-0 = 0101 + 1111 + 1
1
0101
+1111
=====
11111
0101
+1111
=====
0101
したがって、5-0は確かに1を実行します。これは、オーバーフローではない減算であるためです。
15-1 = 1111 +〜1、キャリーインセット
1
1111
1110
====
11111
1111
1110
====
1110
あなたが述べたように、1アウトの減算は符号なしオーバーフローではありません
同様に、キャリーインビットが設定されている場合は-1 --1 = 1111 +〜1
11111
1111
1110
====
1110
最後のビットへのキャリーインは1であり、キャリーアウトはそれらが一致する1であり、符号付きオーバーフローはありません。
キャリーインクリアで8+8 = 1000 + 1000
0
1000
+1000
=====
10000
1000
+1000
=====
0000
符号なしオーバーフロー。
うーん4+4
0
0100
+0100
=====
01000
0100
+0100
=====
1000
unsignedadd実行は0です。これはunsignedオーバーフローではありません。ただし、msbitへのキャリーインと実行が異なるため、これは符号付きオーバーフローです。+4 + +4 = +8、4ビットの符号付きシステムでは+8を表すことができないため、符号付きオーバーフローは正確です。
ビット数に関係なく、奇妙な数はすべてゼロと1であり、残りはゼロです。4ビットシステムの場合は0と8または-8です。
2、3、または4ビットの数字をすべて組み合わせてグラフを作成し、それらすべてを手動で調べて、意味があることを確認します。幅がいくつあってもスケーリングするものは何でも、100ビット加算器は10ビット加算器のように機能します...
add C V unsigned signed
00 + 00 = 000 0 0 0 + 0 = 0 0 + 0 = 0
00 + 01 = 001 0 0 0 + 1 = 1 0 + 1 = 1
00 + 10 = 010 0 0 0 + 2 = 2 0 + -2 = -2
00 + 11 = 011 0 0 0 + 3 = 3 0 + -1 = -1
01 + 00 = 001 0 0 1 + 0 = 1 1 + 0 = 1
01 + 01 = 010 0 1 1 + 1 = 2 1 + 1 = 2 signed cannot represent a +2
01 + 10 = 011 0 0 1 + 2 = 3 1 + -2 = -1
01 + 11 = 100 1 0 1 + 3 = 4 1 + -1 = 0 unsigned cannot represent +4
10 + 00 = 010 0 0 2 + 0 = 2 -2 + 0 = -2
10 + 01 = 011 0 0 2 + 1 = 3 -2 + 1 = -1
10 + 10 = 100 1 1 2 + 2 = 4 -2 + -2 = -4 neither +4 nor -4 will fit in 2 bits
10 + 11 = 101 1 1 2 + 3 = 5 -2 + -1 = -3 neither +4 nor -3 will fit in 2 bits
11 + 00 = 011 0 0 3 + 0 = 3 -1 + 0 = -1
11 + 01 = 100 1 0 3 + 1 = 4 -1 + 1 = -2 +4 does not fit in 2 bits
11 + 10 = 101 1 1 3 + 2 = 5 -1 + -2 = -3 neither +5 nor -3 fit in 2 bits
11 + 11 = 110 1 0 3 + 3 = 6 -1 + -1 = -2 6 does not fit in 2 bits
sub
00 - 00 = 100 0 0
00 - 01 = 011 1 0 0 - 1 = -1 -1 does not fit in an unsigned result
00 - 10 = 010 1 1 0 - 2 = -2 0 - -2 = +2
00 - 11 = 001 1 0 0 - 3 = -3
01 - 00 = 101 0 0
01 - 01 = 100 0 0
01 - 10 = 011 1 1 1 - 2 = -1 1 - -2 = 3
01 - 11 = 010 1 1 1 - 3 = -2 1 - -1 = 2
10 - 00 = 110 0 0
10 - 01 = 101 0 1 -2 - 1 = -3
10 - 10 = 100 0 0
10 - 11 = 011 1 0 2 - 3 = -1
11 - 00 = 111 0 0
11 - 01 = 110 0 0
11 - 10 = 101 0 0
11 - 11 = 100 0 0
上記を生成したコード
printf("add\n");
for(ra=0;ra<4;ra++)
{
for(rb=0;rb<4;rb++)
{
rd=(ra&1)+(rb&1);
rc=ra+rb;
rd=(rd>>1)&1;
re=(rc>>2)&1;
if(re) c=1; else c=0;
if(rd!=re) v=1; else v=0;
if(ra&2) printf("1"); else printf("0");
if(ra&1) printf("1"); else printf("0");
printf(" + ");
if(rb&2) printf("1"); else printf("0");
if(rb&1) printf("1"); else printf("0");
printf(" = ");
if(rc&4) printf("1"); else printf("0");
if(rc&2) printf("1"); else printf("0");
if(rc&1) printf("1"); else printf("0");
printf(" %u %u\n",c,v);
}
}
printf("sub\n");
for(ra=0;ra<4;ra++)
{
for(rb=0;rb<4;rb++)
{
rd=(ra&1)+((~rb)&1)+1;
rc=ra+((~rb)&3)+1;
rd=(rd>>1)&1;
re=(rc>>2)&1;
if(re) c=0; else c=1;
if(rd!=re) v=1; else v=0;
if(ra&2) printf("1"); else printf("0");
if(ra&1) printf("1"); else printf("0");
printf(" - ");
if(rb&2) printf("1"); else printf("0");
if(rb&1) printf("1"); else printf("0");
printf(" = ");
if(rc&4) printf("1"); else printf("0");
if(rc&2) printf("1"); else printf("0");
if(rc&1) printf("1"); else printf("0");
printf(" %u %u\n",c,v);
}
}
さて、あなたの質問は符号なしの数字について話していましたね?したがって、Vビットや右半分(符号付きの半分)は気にしないかもしれません。
これが私が実装した小さな16ビットプロセッサ用のHDL/RTLです:
case 4b0000:
{
//0000 add rd,rs
op_a = bundle(1b0,reg[bundle(2b0,inst[4;8])].value);
op_b = bundle(1b0,reg[bundle(2b0,inst[4;4])].value);
op_res = op_a + op_b;
reg[1].value[CBIT] <= op_res[16];
reg[1].value[NBIT] <= op_res[15];
if(op_res[16;0] == 16h0000)
{
reg[1].value[ZBIT] <= 1b1;
}
else
{
reg[1].value[ZBIT] <= 1b0;
}
if((op_a[15] == op_b[15]) && (op_res[15] != op_b[15] ) )
{
reg[1].value[VBIT] <= 1b1;
}
else
{
reg[1].value[VBIT] <= 1b0;
}
reg[bundle(2b0,inst[4;8])].value <= op_res[16;0];
}
case 4b0001:
{
//0001 sub rd,rs
op_a = bundle(1b0,reg[bundle(2b0,inst[4;8])].value);
op_b = bundle(1b0,reg[bundle(2b0,inst[4;4])].value);
op_res = op_a - op_b;
reg[1].value[CBIT] <= (~op_res[16]);
reg[1].value[NBIT] <= op_res[15];
if(op_res[16;0] == 16h0000)
{
reg[1].value[ZBIT] <= 1b1;
}
else
{
reg[1].value[ZBIT] <= 1b0;
}
if((op_a[15] != op_b[15]) && (op_res[15] == op_b[15] ) )
{
reg[1].value[VBIT] <= 1b1;
}
else
{
reg[1].value[VBIT] <= 1b0;
}
reg[bundle(2b0,inst[4;8])].value <= op_res[16;0];
}
他のロジックで符号付きオーバーフローのmsbitを確認したことがありますが、直接分析で考えられるすべての組み合わせを試したときに、キャリーインとキャリーアウトの方法が一致しないケースを見つけることができませんでした。
私が答えで船外に出た場合、最初にそれを切り取ってもかまいません。5-0は1のキャリーアウトとして1を持っていることを示しています。これは、減算の場合はオーバーフローではありません。長い答えは、符号付きと符号なし、および加算器が一般的にロジックでどのように機能するかについて頭を悩ませるのが難しい場合があるためです。加算器は符号付きまたは符号なしを認識または考慮しません。加算と減算を考慮します。減算を使用すると、2番目のオペランドを反転し、キャリーインをlsbitに反転し、キャリーをmsbitから実行します(加算、キャリー付き加算について考えてください)。 、subおよびsub withキャリー)。符号付きvs符号なしは、それ自体が問題になります(2の補数の美しさ)。上記を符号なしのみの議論に還元すると、符号付きオーバーフローが(符号なしオーバーフローとして)カジュアルなオブザーバーには明白ではないため、半分以上単純になります。
デバッグされたHDLを切り取って貼り付けたところ、そうしなかった場合に多くの応答/修正が得られることを願っています...上記のすべてを納得させ、アクセスした他のプロセッサの結果と比較して、数日を費やしました。うまくいけば、これはあなたに数日を節約します。