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;
}
}; |