Main Content

HDL コード生成および SystemC コード生成のための MATLAB のビット演算

HDL Coder™ は、飽和および丸めロジックがなくても、HDL 特有および SystemC 特有の演算子を再現するビット シフト演算、ビット回転演算およびビット スライス演算をサポートします。

ビットのシフトと回転

次のコードは、固定小数点入力オペランドに対して選択した操作を (mode 引数に基づいて) 実行するバレル シフター/回転子を実装します。

function y   = fcn(u, mode)
% Multi Function Barrel Shifter/Rotator

% fixed width shift operation
fixed_width = uint8(3);

switch mode
    case 1
        % shift left logical
        y = bitsll(u, fixed_width);
    case 2
        % shift right logical
        y = bitsrl(u, fixed_width);
    case 3
        % shift right arithmetic
        y = bitsra(u, fixed_width);
    case 4
        % rotate left
        y = bitrol(u, fixed_width);
    case 5
        % rotate right
        y = bitror(u, fixed_width);
    otherwise
        % do nothing
        y = u;
end

次の表に、生成される VHDL、Verilog、および SystemC のコードを示します。

生成される VHDL コード生成される Verilog コード生成される SystemC コード

この関数用に生成された VHDL® コードで、シフト関数と回転関数は VHDL のシフト命令と回転命令に直接マッピングされます。

     CASE mode IS
            WHEN "00000001" =>
                -- shift left logical
                --'<S2>:1:8'
                cr := signed(u) sll 3;
                y <= std_logic_vector(cr);
            WHEN "00000010" =>
                -- shift right logical
                --'<S2>:1:11'
                b_cr := signed(u) srl 3;
                y <= std_logic_vector(b_cr);
            WHEN "00000011" =>
                -- shift right arithmetic
                --'<S2>:1:14'
                c_cr := SHIFT_RIGHT(signed(u) , 3);
                y <= std_logic_vector(c_cr);
            WHEN "00000100" =>
                -- rotate left
                --'<S2>:1:17'
                d_cr := signed(u) rol 3;
                y <= std_logic_vector(d_cr);
            WHEN "00000101" =>
                -- rotate right
                --'<S2>:1:20'
                e_cr := signed(u) ror 3;
                y <= std_logic_vector(e_cr);
            WHEN OTHERS => 
                -- do nothing
                --'<S2>:1:23'
                y <= u;
        END CASE;

対応する Verilog® コードも同様ですが、Verilog には回転命令にネイティブな演算子がありません。

             case ( mode)
                1 :
                    begin
                        // shift left logical
                        //'<S2>:1:8'
                        cr = u <<< 3;
                        y = cr;
                    end
                2 :
                    begin
                        // shift right logical
                        //'<S2>:1:11'
                        b_cr = u >> 3;
                        y = b_cr;
                    end
                3 :
                    begin
                        // shift right arithmetic
                        //'<S2>:1:14'
                        c_cr = u >>> 3;
                        y = c_cr;
                    end
                4 :
                    begin
                        // rotate left
                        //'<S2>:1:17'
                        d_cr = {u[12:0], u[15:13]};
                        y = d_cr;
                    end
                5 :
                    begin
                        // rotate right
                        //'<S2>:1:20'
                        e_cr = {u[2:0], u[15:3]};
                        y = e_cr;
                    end
                default :
                    begin
                        // do nothing
                        //'<S2>:1:23'
                        y = u;
                    end
            endcase

生成される SystemC コードでは、シフト演算の実行に C++ のネイティブのビット演算子が使用されます。回転演算はシフト演算子を使用して記述されます。

#pragma once 
 
#include "rtwtypes.hpp" 
 
class fcnClass 
{ 
 public: 
  sc_ufixed<16,6> f(sc_ufixed<16,6> u, int8_T mode) 
  { 
    sc_ufixed<16,6> y; 
    sc_ufixed<16,6> c; 
    sc_ufixed<16,6> c_0; 
    sc_ufixed<16,6> c_1; 
    sc_ufixed<16,6> c_2; 
    c = sc_ufixed<16,6>(0.0); 
    c_0 = sc_ufixed<16,6>(0.0); 
    c_1 = sc_ufixed<16,6>(0.0); 
    c_2 = sc_ufixed<16,6>(0.0); 
 
    /*  Multi Function Barrel Shifter/Rotator */ 
    /*  fixed width shift operation */ 
    switch (mode) { 
     case 1: 
      /*  shift left logical */ 
      y = u << 3; 
      break; 
 
     case 2: 
      /*  shift right logical */ 
      c_1 = u >> 3; 
      y = c_1; 
      break; 
 
     case 3: 
      /*  shift right arithmetic */ 
      c_2 = u >> 3; 
      y = c_2; 
      break; 
 
     case 4: 
      /*  rotate left */ 
      c = (sc_ufixed<16,6>)(u << 3) | (sc_ufixed<16,6>)(u >> 13); 
      y = c; 
      break; 
 
     case 5: 
      /*  rotate right */ 
      c_0 = (sc_ufixed<16,6>)(u >> 3) | (sc_ufixed<16,6>)(u << 13); 
      y = c_0;
      break;

     default: 
      /*  do nothing */ 
      y = u;
      break;
    }

    return y;
  }
};

ビット スライスとビットの連結

関数 bitsliceget と関数 bitconcat は、VHDL と Verilog の両方でスライス演算子と連結演算子に直接マッピングされます。

関数 bitsliceget と関数 bitconcat を使用して、固定小数点または整数のワードのビット スライス (フィールド) にアクセスして操作できます。たとえば、8 ビットのバイトの上位 4 ビットのニブルと下位 4 ビットのニブルを入れ替える操作を考えてみます。次の例では、従来のマスクとシフト方式に依存せずにこの処理を行っています。

function y = fcn(u)
% NIBBLE SWAP 
y = bitconcat( …
      bitsliceget(u, 4, 1), 
      bitsliceget(u, 8, 5));

次の表に、生成される VHDL、Verilog、および SystemC のコードを示します。

生成される VHDL コード生成される Verilog コード生成される SystemC コード

次のリストは、対応する生成済み VHDL コードを示しています。

ENTITY fcn IS
    PORT (
        clk : IN std_logic; 
        clk_enable : IN std_logic; 
        reset : IN std_logic;
        u : IN std_logic_vector(7 DOWNTO 0);
        y : OUT std_logic_vector(7 DOWNTO 0));
END nibble_swap_7b;


ARCHITECTURE fsm_SFHDL OF fcn IS


BEGIN
    -- NIBBLE SWAP
    y <= u(3 DOWNTO 0) & u(7 DOWNTO 4);
END fsm_SFHDL;

次のリストは、対応する生成済み Verilog コードを示しています。

module fcn (clk, clk_enable, reset, u, y );
    input clk;
    input clk_enable;
    input reset;
    input [7:0] u;
    output [7:0] y;

    // NIBBLE SWAP
    assign y = {u[3:0], u[7:4]};

endmodule

次のリストは、対応する生成済み SystemC コードを示しています。

#pragma once 
 
#include "rtwtypes.hpp" 
 
class fcnClass 
{ 
 public: 
  sc_uint<8> f(sc_ufixed<16,6> u) 
  { 
    sc_uint<8> y; 
    sc_uint<16> tmp; 
    sc_uint<16> tmp_0; 
 
    /*  NIBBLE SWAP  */ 
    tmp = u(); 
    tmp_0 = u(); 
    y = (sc_uint<8>)(sc_uint<4>)((sc_uint<16>)tmp & sc_uint<16>(15.0)) << 4 | 
      (sc_uint<8>)(sc_uint<4>)((sc_uint<16>)(tmp_0 >> 4) & sc_uint<16>(15.0)); 
    return y; 
  } 
};

参考

|

関連するトピック