web-dev-qa-db-ja.com

nビットのstd_logic_vectorを右または左にシフトします

ベクトルsignal tmp : std_logic_vector(15 downto 0)があります

Nビットの左または右にシフトする必要があります。この操作をどのように実現できますか。連結操作を考えましたが、どのように使用するのかわかりませんでした。

19
Mazzy

ieee.numeric_stdライブラリと、作業中の数値に適したベクトル型(unsignedまたはsigned)を使用します。

演算子は、算術シフトの場合はsla/sra(右シフトの場合は符号ビットで、左シフトの場合はlsbで埋める)およびsll/srl論理シフト(つまり、「0」で埋める)。

演算子にパラメーターを渡し、シフトするビット数を定義します。

A <= B srl 2; -- logical shift right 2 bits

更新:

上に何を書いているのかわかりません(指摘してくれたValに感謝します!)

もちろん、signedおよびunsigned型をシフトする正しい方法は、shift_leftで定義されているshift_rightおよびieee.numeric_std関数を使用することです。

シフトおよび回転演算子sllrorなど booleanbit、またはstd_ulogicのベクトル用興味深いことに予期しない振る舞い を持つことができます。左にシフトしても算術シフトが終了ビットを複製します。

さらに多くの歴史はここで見つけることができます:

http://jdebp.eu./FGA/bit-shifts-in-vhdl.html

しかし、元の質問への答えはまだです

sig <= tmp sll number_of_bits;
25
Martin Thompson

これを実現する方法は2つあります。連結、およびシフト/回転機能。

  • 連結は、物事を行う「手動の」方法です。元の信号のどの部分を「維持」するかを指定してから、データを一端または他端に連結します。例:tmp <= tmp(14 downto 0)& '0';

  • シフト関数(論理、算術):これらは、さまざまな方法でベクトルをシフトまたは回転できる汎用関数です。機能は次のとおりです。sll(左に論理シフト)、srl(右に論理シフト)。論理シフトはゼロを挿入します。算術シフト(sra/sla)は、左端または右端のビットを挿入しますが、論理シフトと同じように機能します。 これらのすべての操作に対して、シフトする対象(tmp)と、シフトを実行する回数(nビット)

  • 回転機能:rol(左回転)、ror(右回転)。回転するだけで、MSBがLSBになり、すべてが左にシフト(rol)するか、逆にrorになります。

便利なリファレンス を見つけました(最初のページを参照)。

16
Josh

個人的には、連結がより良い解決策だと思います。一般的な実装は次のようになります

entity shifter is
    generic (
        REGSIZE  : integer := 8);
    port(
        clk      : in  str_logic;
        Data_in  : in  std_logic;
        Data_out : out std_logic(REGSIZE-1 downto 0);
end shifter ;

architecture bhv of shifter is
    signal shift_reg : std_logic_vector(REGSIZE-1 downto 0) := (others<='0');
begin
    process (clk) begin
        if rising_Edge(clk) then
            shift_reg <= shift_reg(REGSIZE-2 downto 0) & Data_in;
        end if;
    end process;
end bhv;
Data_out <= shift_reg;

両方ともシフトレジスタとして実装されます。リソースを使用するよりも多くのシフトレジスタが必要な場合(たとえば、1000の数値を4で割る)、値を格納するためにBRAMを使用し、「インデックス」を含む単一のシフトレジスタを使用することを検討してください。すべての数字の正しいシフト。

6
Paul Seeb

not std_logic_vectorでsllまたはsrlを使用することをお勧めします。

シミュレーション中にsllがこれらのビットに「U」値を与えました。

shift_left()shift_right()関数を使用します。

例えば:

OP1 : in std_logic_vector(7 downto 0); signal accum: std_logic_vector(7 downto 0);

accum <= std_logic_vector(shift_left(unsigned(accum), to_integer(unsigned(OP1)))); accum <= std_logic_vector(shift_right(unsigned(accum), to_integer(unsigned(OP1))));

4

これは通常、ベクターから適切なビットを選択してから0を追加することにより、手動で行われます。

たとえば、ベクトルを8ビットシフトするには

variable tmp : std_logic_vector(15 downto 0)
...
tmp := x"00" & tmp(15 downto 8);

この単純な答えが誰かに役立つことを願っています

2
iyop45
_add_Pbl <= to_stdlogicvector(to_bitvector(dato_cu(25 downto 2)) sll 1);
add_Pbl is a std_logic_vector of 24 bit
dato_cu is a std_logic_vector of 32 bit
_

Sllステートメントは論理1ビットと0ビットで機能するため、最初に_std_logic_vector_をto_bitvector()関数で変換する必要があります。

0
Pablito