HDL コード生成および HLS コード生成のための MATLAB のビット演算
HDL Coder™ は、飽和および丸めロジックがなくても、HDL 特有の演算子を再現するビット シフト演算、ビット回転演算およびビット スライス演算をサポートします。
ビットのシフトと回転
次のコードは、固定小数点入力オペランドに対して選択した操作を (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、および HLS のコードを示します。
生成される VHDL コード | 生成される Verilog コード | 生成される HLS コード |
---|---|---|
この関数用に生成された 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 | 生成される HLS コードでは、シフト演算の実行に 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、および HLS のコードを示します。
生成される VHDL コード | 生成される Verilog コード | 生成される HLS コード |
---|---|---|
次のリストは、対応する生成済み 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 | 次のリストは、対応する生成済み HLS コードを示しています。 #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; } }; |