2

私は単純な加算器を実装しています。ただし、少しユニークなひねりが必要です。

私が実装しているのは、コード セグメント (CS) レジスタと命令ポインタ (IP) レジスタにまたがる「ロール オーバー」機能です。したがって、+20 ずつ相対ジャンプすると、IP が 254 で、IP は 18 にロールオーバーし、CS は 1 増加します。

この部分は簡単で、難しい部分はその逆です。ジャンプが -20 で IP が 0 のときの借用を検出すると、CS を 1 減らし、IP を 236 にロールアンダーする必要があります。

これまでのところ、私のコードは

entity carryover is 
  port(
    DataIn: in std_logic_vector(7 downto 0);
    SegmentIn: in std_logic_vector(7 downto 0);
    Addend: in std_logic_vector(7 downto 0); --How much to increase DataIn by (as a signed number). Believe it or not, that's the actual word for what we need.
    DataOut: out std_logic_vector(7 downto 0);
    SegmentOut: out std_logic_vector(7 downto 0);
   );
end carryover;

architecture Behavioral of carryover is
  signal temp: std_logic_vector(8 downto 0);
begin
  --treat as unsigned because it doesn't actually matter for addition and just make carry and borrow correct
  temp <= std_logic_vector(unsigned("0" & DataIn) + (unsigned)Addend);
  DataOut <= temp(7 downto 0);
  SegmentOut <= unsigned(SegmentIn) + 1 when (not temp(8)) and (not Addend(7) 

end Behavioral;

しかし、借用を検出する方法がわかりません。これを行うためのきれいな方法はありますか?

アップデート

私の新しいコードはこれです:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use work.tinycpu.all;

entity carryover is 
  port(
    EnableCarry: in std_logic; --When disabled, SegmentIn goes to SegmentOut
    DataIn: in std_logic_vector(7 downto 0);
    SegmentIn: in std_logic_vector(7 downto 0);
    Addend: in std_logic_vector(7 downto 0); --How much to increase DataIn by (as a signed number). Believe it or not, that's the actual word for what we need.
    DataOut: out std_logic_vector(7 downto 0);
    SegmentOut: out std_logic_vector(7 downto 0)
--    Debug: out std_logic_vector(8 downto 0)
   );
end carryover;

architecture Behavioral of carryover is
  signal temp: std_logic_vector(8 downto 0);
begin
  --treat as unsigned because it doesn't actually matter for addition and just make carry and borrow correct
  process(DataIn, SegmentIn,Addend, EnableCarry)
  begin
    temp <= std_logic_vector(signed('0' & DataIn) + signed(Addend(7) & Addend)); 
    if (EnableCarry and ((not Addend(7)) and (DataIn(7)) and temp(8)))='1' then 
      SegmentOut <= std_logic_vector(unsigned(SegmentIn)+1);
    elsif (EnableCarry and (Addend(7) and (not DataIn(7)) and temp(8)))='1' then 
      SegmentOut <= std_logic_vector(unsigned(SegmentIn)-1);
    else
      SegmentOut <= SegmentIn;
    end if;
  end process;
  --Debug <= Temp;
  DataOut <= temp(7 downto 0);
end Behavioral;

符号付き数値の追加は計画どおりに機能し、Temp は現在常に正しい結果ですが、SegmentOut は常に SegmentIn と等しくなります。理由はわかりません。なぜなら、SegmentIn + 1Addend=0x04、DataIn=0xFE、SegmentIn=0x00、CarryEnable=1 の入力を実際に手で計算したのに、if ステートメントが等しい(1 and ((not 0) and 1 and 1))='1'にもかかわらず、SegmentOut が変化しないからです。これの実装方法に問題がある人はいますか?

4

1 に答える 1

0

オーバーフローは、加数の符号ビットが等しいが、和の符号ビットと等しくない場合に発生します。

A = + 12, B = + 4.            A = + 4, B = – 12
А = 0.1100                    A = 0.0100
В = 0.0100                    B = 1.0100
    ------                        ------   
C   1.0000                    C   1.1000
As = Bs, Cs = 1 – overflow    As != Bs - not overflow.

は常に正であるためDateIn、オーバーフローは桁上げでのみ発生する可能性があります (両方の正の数の場合)。したがって、ステートメントを次のように変更する必要があります(おそらくこれら2つを何らかの方法で結合します):

SegmentOut <= unsigned(SegmentIn) + 1 when (not Addend(7) and temp(7)); 
SegmentOut <= unsigned(SegmentIn) - 1 when (Addend(7) and temp(7));

ここに真理値表があります:

Addend(7) DataIn(7) temp(7)| Carry Borrow
0         0         0      | 0     0
0         0         1      | 1     0
1         0         0      | 0     0
1         0         1      | 0     1

編集:ポール・シーブが言ったように:

SegmentOut <= unsigned(signed(SegmentIn) + signed(Addend(7) & Addend(7) & Addend(7) & Addend(7) & Addend(7) & Addend(7) & Addend(7) & "1")) when (temp(7) and CarryFlag); 
于 2012-05-07T18:36:02.850 に答える