Bitwise Operations in MATLAB for HDL and HLS Code Generation
HDL Coder™ supports bit shift, bit rotate, bit slice operations that mimic HDL-specific operators without saturation and rounding logic.
Bit Shifting and Rotation
The following code implements a barrel shifter/rotator that performs a selected
operation (based on the mode
argument) on a fixed-point input
operand.
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
This table shows the generated VHDL, Verilog and, HLS code.
Generated VHDL code | Generated Verilog code | Generated HLS code |
---|---|---|
In VHDL® code generated for this function, the shift and rotate functions map directly to shift and rotate instructions in 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; | The corresponding Verilog® code is similar, except that Verilog does not have native operators for rotate instructions. 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 | The generated HLS code uses the native C++ bitwise operators to accomplish the shift operations. The rotate operations are written using shift operators. #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; } }; |
Bit Slicing and Bit Concatenation
The bitsliceget
and bitconcat
functions
map directly to slice and concatenate operators in both VHDL and Verilog.
You can use the functions bitsliceget
and
bitconcat
to access and manipulate bit slices (fields) in a
fixed-point or integer word. As an example, consider the operation of swapping the
upper and lower 4-bit nibbles of an 8-bit byte. The following example accomplishes
this task without resorting to traditional mask-and-shift techniques.
function y = fcn(u) % NIBBLE SWAP y = bitconcat( … bitsliceget(u, 4, 1), bitsliceget(u, 8, 5));
This table shows the generated VHDL, Verilog and, HLS code.
Generated VHDL code | Generated Verilog code | Generated HLS code |
---|---|---|
The following listing shows the corresponding generated VHDL code. 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; | The following listing shows the corresponding generated Verilog code. 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 | The following listing shows the corresponding generated HLS code. #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; } }; |