Logic gates and bitwise operations with Scilab

In this article we are going to use Scilab to perform logic operations with Boolean variables and bitwise operation with integer variables. To get a basic understanding on the logic operations (logic gates) read the article Logical operations and boolean functions.

Scilab video tutorial

Scilab has three elementary functions defined for logical operations.

Keyword Name Description
~ Logical NOT operator Gives the element-wise negation of a Boolean variable
& Logical AND operator Gives the element-wise logical AND of two Boolean variables
| Logical OR operator Gives the element-wise logical OR of two Boolean variables

To use the elementary logical operators, let’s define two Boolean variables A and B.

-->A = %T;
-->B = %F;

Applying the logical NOT to the A variable gives:

-->~A

ans =
F

As expected, the negation of a true variable (%T) will output a false value (%F).

Applying the logical AND to the Boolean variables A and B, gives:

-->A & B

ans =
F

Applying the logical OR to the Boolean variables A and B, gives:

-->A | B

ans =
T

To exercise the complete truth tables for the basic logic operations (gates), we are going to define the Boolean variables A and B as vectors of logic states:

-->A = [%F; %F; %T; %T];
-->B = [%F; %T; %F; %T];

NOT gate

We are going to apply the NOT gate only to the variable A, as:

-->~A

ans =
T
T
F
F

AND gate

In Boolean algebra, the logic operation AND between two variables A and B, is represented as:

\[A \cdot B \tag{1}\]

The Scilab AND operation between A and B is:

-->A & B

ans =
F
F
F
T

OR gate

In Boolean algebra, the logic operation OR between two variables A and B, is represented as:

\[A + B \tag{2}\]

The Scilab OR operation between A and B is:

-->A | B

ans =
F
T
T
T

NAND gate

In Boolean algebra, the logic operation NAND between two variables A and B, is represented as:

\[\sim (A \cdot B) \tag{3}\]

The Scilab NAND operation between A and B is:

-->~(A & B)

ans =
T
T
T
F

NOR gate

In Boolean algebra, the logic operation NOR between two variables A and B, is represented as:

\[\sim (A + B) \tag{4}\]

The Scilab NOR operation between A and B is:

-->~(A | B)

ans =
T
F
F

XOR gate

In Boolean algebra, the logic operation XOR between two variables A and B, is represented as:

\[A \cdot\sim B +\sim A \cdot B \tag{5}\]

The Scilab XOR operation between A and B is:

-->(A & (~B)) | ((~A) & B)

ans =
F
T
T

XNOR gate

In Boolean algebra, the logic operation XNOR between two variables A and B, is represented as:

\[A \cdot B +\sim A \cdot\sim B  \tag{6}\]

The Scilab XNOR operation between A and B is:

-->(A & B) | ((~A) & (~B))

ans =
T
F
F

All the above operations can be summarized in a Scilab script file, as:

clc
A = [%F; %F; %T; %T];
B = [%F; %T; %F; %T];

Q_NOT = ~A;
Q_AND = A & B;
Q_OR = A | B;
Q_NAND = ~(A & B);
Q_NOR = ~(A | B);
Q_XOR = (A & (~B)) | ((~A) & B);
Q_XNOR = (A & B) | ((~A) & (~B));

disp("A B AND OR NAND NOR XOR XNOR")
disp([A B Q_AND Q_OR Q_NAND Q_NOR Q_XOR Q_XNOR])

Executing the script file (Scilab instructions) will output in the Scilab console:

A B AND OR NAND NOR XOR XNOR

F F F F T T F T
F T F T T F T F
T F F T T F T F
T T T T F F F T

Bitwise operations – predefined Scilab functions

In computer engineering, IT, embedded systems, control engineering, software engineering, bitwise operations are a common practice. Bitwise operations means performing logic operation on bits (0 and 1) rather than logic states true or false.

A decimal number can be converted to a binary number. For example, decimal 53 is 00110101 in binary. We can easily do the conversion with the Scilab function dec2bin().

-->dec2bin(53,8)

ans =
00110101

Let’s consider a second decimal number, 92, converted in binary will give 01011100.

-->dec2bin(92,8)

ans =
01011100

Performing a bitwise operation between 53 and 92 means performing a logic operation between their binary representation. For example a bitwise OR will give:

53 0 0 1 1 0 1 0 1
OR |
92 0 1 0 1 1 1 0 0
125 0 1 1 1 1 1 0 1

The bitwise OR means performing an OR operation between corresponding bits, from bit 0 to bit 7. The result will be 01111101, which converter in decimal is 125. We can easily verify the result with a Scilab operation:

-->uint8(53) | uint8(92)

ans =
125

-->dec2bin(125,8)

ans =
01111101

Notice that the decimal numbers were defined as 8 bit integers, using the Scilab function uint8().

There are some Scilab predefined functions for bitwise operations:

  • bitand() – performs bitwise AND
  • bitor() – performs bitwise OR
  • bitxor() – performs bitwise XOR

The way to use them is by defining the decimal numbers as vectors of integer binary values. For example, decimal variable A, equal with 53, and decimal variable B, equal with 92, will be written as:

-->A = [0 0 1 1 0 1 0 1];
-->B = [0 1 0 1 1 1 0 0];

To perform a bitwise OR, with the result stored in a variable Q, we have to execute in the Scilab console:

-->Q = bitor(A,B)

Q =
0. 1. 1. 1. 1. 1. 0. 1.

The main disadvantages of using the predefined Scilab functions for bitwise operations are that:

  • we need to define the “binary” value as a vector of 0 and 1
  • we need to use string processing function to convert back to a decimal value

For example, to get the decimal value from the Q variable, we have to use:

-->bin2dec(strcat(string(Q)))

ans =
125.

This is good but we can do better.

Bitwise operations – custom Scilab functions

We are going to define a custom Scilab function, which has to fulfill the following requirements:

  • it has to perform the following bitwise operations: AND, OR, NAND, NOR, XOR, XNOR
  • between two unsigned integer decimal variables defined on either 8, 16, 32 or 64 bits

The function is going to be called bitwise(), with the following source code:

function y = bitwise(A,B,gateType)
    dataType_A = typeof(A);
    dataType_B = typeof(B);
    if (dataType_A ~= dataType_B) then
        error("ERROR: The input variables do not have the same data type!")
    end
    if and(gateType ~= ["AND" "OR" "NAND" "NOR" "XOR" "XNOR"]) then
        error("ERROR: The gate type must be either: AND, OR, NAND, NOR, XOR or XNOR");
    end 
    select dataType_A
    case "uint8"
        bitNo = 8;
    case "uint16"
        bitNo = 16;
    case "uint32"
        bitNo = 32;
    case "uint64"
        bitNo = 64;
    else
        error("ERROR: The input variables must be either: uint8, uint16, uint32 or uint64");
    end
    select gateType
    case "AND"
        Q = dec2bin(A & B, bitNo);
    case "OR"
        Q = dec2bin(A | B, bitNo);
    case "NAND"
        Q = dec2bin(~(A & B), bitNo);
    case "NOR"
        Q = dec2bin(~(A | B), bitNo);
    case "XOR"
        Q = dec2bin((A & (~B)) | ((~A) & B), bitNo);
    case "XNOR"
        Q = dec2bin((A & B) | ((~A) & (~B)), bitNo);
    end
    y = Q;
endfunction

To define and load the function in Scilab, open a new file in SciNotes, copy the above source code, save the file as bitwise.sci and execute it. If everything is successful, you’ll see in the Scilab console a message similar with:

-->exec('some_folder_path/bitwise.sci', -1)

Let’s go through the function step by step.

The function expects three arguments:

  • A – unsigned integer decimal value; minimum value is 0, maximum is 252.
  • B – unsigned integer decimal value; minimum value is 0, maximum is 252.
  • gateType – string defining which bitwise operation will be performed; it can take only the following values: AND, OR, NAND, NOR, XOR, XNOR.

At the beginning, the function extracts the data type of the input decimal values, using the Scilab function typeof(). After, a data consistency check is performed, both decimal values have to have the same data type. Otherwise an error message is displayed.

Another check is for the gateType. It makes sure that the user has entered only a supported bitwise function, otherwise an error message is displayed.

The next instructions are checking the data type of the variable A (which is the same with variable B) and assigns the right number of bits using the local variable bitNo. This variable is going to be used further in the bitwise operations. In case of a wrong data type, an error message is displayed.

Function of the gateType, the corresponding bitwise operation is executed.

The result is stored in the local variable Q, which is passed to the function output y as a string.

Let’s test out function, first by triggering the wrong data type check.

-->bitwise(53,92,'OR')

!--error 10000
ERROR: The input variables must be either: uint8, uint16, uint32 or uint64
at line 20 of function bitwise called by :
bitwise(53,92,'OR')

As expected, the user is informed that the data type of the input variables is not the expected one. In our example they are Double by default and the function expects unsigned integers (8, 16, 32 or 64 bit).

Let’s try now different data types for the input variables:

-->bitwise(uint8(53),uint16(92),'OR')

!--error 10000
ERROR: The input variables do not have the same data type!
at line 5 of function bitwise called by :
bitwise(uint8(53),uint16(92),'OR')

As expected, the user is informed that the input variables don’t have the same data type. Variable A (53) is uint8, while variable B (92) is uint16.

The last check is for an undefined or misspelled bitwise operation.

-->bitwise(uint8(53),uint8(92),'OT')

!--error 10000
ERROR: The gate type must be either: AND, OR, NAND, NOR, XOR or XNOR
at line 8 of function bitwise called by :
bitwise(uint8(53),uint8(92),'OT')

Let’s enter the function arguments in the right format, for the same decimal values and bitwise function used in the previous example:

-->bitwise(uint8(53),uint8(92),'OR')

ans =
01111101

To get the decimal value we can apply the bin2dec() function to the ans variable

-->bin2dec(ans)

ans =
125.

or use the whole instruction as an argument for the bin2dec() function.

-->bin2dec(bitwise(uint8(53),uint8(92),'OR'))

ans =
125.

We can also input, as bitwise() function arguments, the corresponding binary string of our decimal variable as arguments for the bin2dec() function.

-->bitwise(uint8(bin2dec("00110101")),uint8(bin2dec("01011100")),'OR')

ans =
01111101

Let’s use the function for a 32 bit input variables and a bitwise XOR logic operation:

-->bitwise(uint32(127635243),uint32(273825354),'XOR')

ans =
00010111110010011011000101100001

For a better understanding of logic gates and bitwise operations, let’s call our bitwise() function in a Scilab script, which goes through all the defined bitwise operations, for a given set of input variables.

clc
A = uint32(127635243);
B = uint32(273825354);
logicGates = ["AND" "OR" "NAND" "NOR" "XOR" "XNOR"];
printf("\nA\t=\t%s",dec2bin(A,32));
printf("\nB\t=\t%s",dec2bin(B,32));
for i=1:max(size(logicGates))
    Q = bitwise(A,B,logicGates(i));
    printf("\n%s\t=\t%s",logicGates(i),Q);
end

Running the Scilab intructions above, will give the following output in the Scilab console:

A    = 00000111100110111000111100101011
B    = 00010000010100100011111001001010
AND  = 00000000000100100000111000001010
OR   = 00010111110110111011111101101011
NAND = 11111111111011011111000111110101
NOR  = 11101000001001000100000010010100
XOR  = 00010111110010011011000101100001
XNOR = 11101000001101100100111010011110

For any questions or observations regarding this tutorial please use the comment form below.

Don’t forget to Like, Share and Subscribe!

Leave a Reply

Ad Blocker Detected

Dear user, Our website provides free and high quality content by displaying ads to our visitors. Please support us by disabling your Ad blocker for our site. Thank you!

Refresh