Main Content

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

See Also

|

Related Topics