Professional Documents
Culture Documents
Different arithmetic operators of a system are selected from the built-in blocks
of the system generator toolbox, such as Add/Sub and multiplier blocks with zero
latency, and configured using 32/16-bit fixed point settings according to the IEEE
754 standard.
Related terms:
Arithmetic Operators
Arithmetic operators are used in mathematical expressions. Table 3.3 gives a list
of the arithmetic operators. All these operators, except the autoincrement and
autodecrement, require at least two operands. Autoincrement and autodecrement
operators are unary as they require only one operand.
Operator Operation
+ Addition
− Subtraction
Multiplication
/ Division
% Remainder (integer division only)
++ Autoincrement
−− Autodecrement
The arithmetic operators “+, −, , and /” are obvious and require no explanation.
Operator “%” gives the remainder after an integer division is performed. Some
examples are given below:
12 % 5 gives 2 (remainder is 2)
(7.3)
Here a, b, and c are column vectors with three elements. For addition and subtrac-
tion, element-by-element and usual matrix operations are the same. Other useful
matrix operators are: A2 = A.*A, A−1 = inv(A), determinant as det(A), and transpose as
A .
MATLAB Fundamentals
Brian H. Hahn, Daniel T. Valentine, in Essential MATLAB for Engineers and Scien-
tists (Sixth Edition), 2017
a = [2 4 5];b = [6 2 2];a .* ba ./ b
MATLAB has four additional arithmetic operators, as shown in Table 2.3 that work
on corresponding elements of arrays with equal dimensions. They are sometimes
called array or element-by-element operations because they are performed element
by element. For example, a .* b results in the following vector (sometimes called the
array product):
Operator Description
.* Multiplication
./ Right division
.\ Left division
.̂ Power
[a(1)*b(1) a(2)*b(2) a(3)*b(3)]
You will have seen that a ./ b gives element-by-element division. Now try [2 3 4] .^ [4
3 1]. The ith element of the first vector is raised to the power of the ith element of the
second vector. The period (dot) is necessary for the array operations of multiplication,
division, and exponentiation because these operations are defined differently for
matrices; they are then called matrix operations (see Chapter 6). With a and b as
defined above, try a + b and a - b. For addition and subtraction, array operations and
matrix operations are the same, so we don't need the period to distinguish them.
When array operations are applied to two vectors, both vectors must be the same
size!
Array operations also apply between a scalar and a nonscalar. Check this with 3
.* a and a .^ 2. This property is called scalar expansion. Multiplication and division
operations between scalars and nonscalars can be written with or without the period
(i.e., if a is a vector, 3 .* a is the same as 3 * a).
The MATLAB function sum(z) finds the sum of the elements of the vector z, so the
statement sum(a .* b) will find the scalar product of a and b (30 for a and b defined
above).
Exercises
One thing to watch out for is the distinction between type qualification and type
conversion. The former simply states the type of a value, whereas the latter changes
the value, possibly to a different type. One way to remember this distinction is to
think of “quote for qualification.”
real(123) integer(3.6)
One thing to watch out for is the distinction between type qualification and type
conversion. The former simply states the type of a value, whereas the latter changes
the value, possibly to a different type. One way to remember this distinction is to
think of “quote for qualification.”
A VHDL Primer
Peter Wilson, in Design Recipes for FPGAs (Second Edition), 2016
# fk(·)
1 Vl+1,2n−1
2 Vl+1,2n
3 Vl+1,2n−1 + Vl+1,2n
4 Vl+1,2n−1 − Vl+1,2n
5 Vl+1,2n−1 × Vl+1,2n
6 Vl+1,2n−1 ÷ Vl+1,2n
7 Vl+1,2n−1 ^ Vl+1,2n
The nodal value can be represented by the inclusion of bivariate operations weighted
by binary parameters, by the combination of both the left offspring Vl+1,2n−1 and right
offspring Vl+1,2n as input:
(1)
This equation will be the same as the one presented generally in the next section,
with the latter being the more general description.
package_body
package_body_declarative_item
The items declared in a package body must include the full declarations of all
subprograms defined in the corresponding package declaration. These full decla-
rations must include the subprogram headers exactly as they are written in the
package declaration, to ensure that the implementation conforms with the interface.
This means that the names, types, modes and default values of each of the formal
parameters must be repeated exactly. There are only two variations allowed. First, a
numeric literal may be written differently, for example, in a different base, provided
it has the same value. Second, a simple name consisting just of an identifier may
be replaced by a selected name, provided it refers to the same item. While this
conformance requirement might seem an imposition at first, in practice it is not.
Any reasonable text editor used to create a VHDL model allows the header to be
copied from the package declaration with little difficulty. Similarly, a deferred
constant defined in a package declaration must have its value specified by repeating
the declaration in the package body, this time filling in the initialization expression
as in a full constant declaration.
In addition to the full declarations of items deferred from the package declaration, a
package body may include declarations of additional types, subtypes, constants and
subprograms. These items are used to implement the subprograms defined in the
package declaration. Note that the items declared in the package declaration cannot
be declared again in the body (apart from subprograms and deferred constants, as
described above), since they are automatically visible in the body. Furthermore, the
package body cannot include declarations of additional signals. Signal declarations
may only be included in the interface declaration of a package.
package bit_vector_signed_arithmetic is
return bit_vector;
return bit_vector;
return bit_vector;
…
The package body contains the full function bodies. It also includes a function,
mult_unsigned, not defined in the package declaration. It is used internally in the
package body to implement the signed multiplication operator.
return bit_vector is …
return bit_vector is …
return bit_vector is
…
begin
…
return bit_vector is
begin
else
end if;
…
One further point to mention on the topic of packages relates to the order of analysis.
We mentioned before that a package is usually a separate design unit that is analyzed
separately from other design units, such as entity declarations and architecture
bodies. (We will return to the case of a package not being a design unit shortly.)
In most cases, a package declaration and its corresponding package body are each
separate design units; hence they may be analyzed separately. A package declaration
is a primary design unit, and a package body is a secondary design unit. The package
body depends on information defined in the package declaration, so the declaration
must be analyzed first. Furthermore, the declaration must be analyzed before any
other design unit that refers to an item defined by the package. Once the declaration
has been analyzed, it does not matter when the body is analyzed in relation to units
that use the package, provided it is analyzed before the model is elaborated. In a
large suite of models, the dependency relationships can get quite complex, and a
correct order of analysis can be difficult to find. A good VHDL tool suite will
provide some degree of automating this process by working out the dependency
relationships and analyzing those units needed to build a particular target unit to
simulate or synthesize.
VHDL-87
The keywords package body may not be included at the end of a package body in
VHDL-87.
stim_gen : process is
package ID_manager is
begin
result := next_ID;
next_ID := next_ID + 1;
return result;
…
…
ID : natural;
end record test_case;
begin
…
next_test_case.ID := ID_manager.get_ID;
…
The variable next_ID is declared in the package body, and so is not visible outside
the package. The only way to access it is using the get_ID function provided by
the package declaration. This is shown in the first assignment statement within
the process body. The package name is used as a prefix in the selected name for
the function. The second assignment statement is illegal, since the variable is not
visible at that point. The package provides a measure of safety against inadvertent
corruption of the data state.
By writing the package locally within the process, it is only available in the process.
Thus, we have achieved greater separation of concerns than if we had written the
package as a design unit, making it globally visible. Moreover, since the package is
local to a process, there can be no concurrent access by multiple processes. Thus,
the encapsulated variable can be an ordinary non-shared variable. If the package
were declared as a global design unit, there could be concurrent calls to the get_ID
function. As a consequence, the variable would have to be declared as a shared
variable, which would significantly complicate the design. (We describe shared
variables in Chapter 23.)
We can also declare a local package within an enclosing package declaration, whether
that enclosing package be a design unit or itself a local package. If the nested package
is to be accessible outside the enclosing package, the nested package declaration
must occur within the enclosing package declaration. The nested package body, if
required, must then occur within the body of the enclosing package. As an example,
the following outline shows an enclosing package outer with a nested package inner
that declares a function f:
package outer is
…
package inner is
…
…
…
…
end function f;
…
Outside the packages, we can refer to the function f with the name outer.inner.f.
If the enclosing package only requires a local package for private use, we can write
both the nested package declaration and nested package body in the body of the
enclosing package. The outline is:
package outer is
…
…
package inner is
…
…
…
end package body outer;
In this case, items in the nested package are only accessible within the enclosing
package body. While this scheme would not commonly arise in practice, it does
serve to illustrate the consistency and general applicability of the visibility rules we
introduced in Section 6.6.
4.5.17 Operators in C
Operators are applied to variables and other objects in expressions, and they cause
some conditions or some computations to occur.
• Arithmetic operators
• Logical operators
• Bitwise operators
• Conditional operators
• Assignment operators
• Relational operators
• Preprocessor operators
Arithmetic Operators
Arithmetic operators are used in arithmetic computations. Arithmetic operators
associate from left to right, and they return numerical results. A list of the C18
arithmetic operators is given in Table 4.3.
Table 4.3. C18 arithmetic operators
Operators Operations
+ Addition
− Subtraction
* Multiplication
/ Division
% Remainder (integer division)
++ Autoincrement
−− Autodecrement
5 + 12 // equals 17
10 − 15 // equals −5
5 / 3 // equals 1
12 / 3 // equals 4
3 * 12 // equals 36
7 % 3 // equals 1
/* Post-increment operator */
j = 4;
k = j++; // k = 4, j = 5
/* Pre-increment operator */
j = 4;
k = ++j; // k = 5, j = 5
/* Post-decrement operator */
j = 12;
k = j−−; // k = 12, j = 11
/* Pre-decrement operator */
j = 12;
k = −−j; // k = 11, j = 11
Relational Operators
Relational operators are used in comparisons. If the expression evaluates to TRUE,
1 is returned otherwise 0 is returned.
All relational operators associate from left to right, and a list of mikroC relational
operators is given in Table 4.4.
Operators Operations
== Equal to
!= Not equal to
> Greater than
< Less than
>= Greater than or equal to
<= Less than or equal to
x = 10
x == 10 // returns 1
x != 10 // returns 0
Operators Operations
&& AND
|| OR
! NOT
x = 7;
Bitwise Operators
Bitwise operators are used to modify the bits of a variable. A list of the C18 bitwise
operators is given in Table 4.6.
Operators Operations
& Bitwise AND
| Bitwise OR
^ Bitwise EXOR
~ Bitwise complement
<< Shift left
>> Shift right
-----------------
-----------------
-----------------
~ : 0101 0101
-----------------
-----------------
-----------------
vii. 0x235A << 1 returns 0x46B4 (shift left 0x235A left by 1 digit)
-------------------------------------
---------------------
Assignment Operators
In C language, there are two types of assignments: simple assignments and com-
pound assignments. In simple assignments, an expression is simply assigned to
another expression or an operation is performed using an expression and the result
is assigned to another expression:
Expression1 = Expression2
or
Temp = 10;
Here, the specified operation is performed on Expression1 and the result is stored
in Result. For example,
also,
Conditional Operator
The syntax of the conditional operator is
Preprocessor Operators
The preprocessor allows a programmer to
• Compile a program conditionally such that parts of the code are not compiled
The preprocessor operator is the (“#”) character, and any line of code with a leading
(“#”) is assumed to be a preprocessor command. Semicolon character (“;”) is not
needed to terminate a preprocessor command.
#define #undef
#if #elif #endif
#ifdef #ifndef
#error
#line
#pragma
An identifier that has already been defined cannot be defined again unless both
definitions have the same values. One way to get round this problem is to remove
the Macro definition:
#undef MAX
#ifndef MAX
#endif
Note that the #define preprocessor command does not occupy any space in memory.
#define ADD(a, b) (a + b)
When this Macro is used in a program, (a,b) will be replaced with (a + b) as shown
below:
#define SQUARE(a) (a * a)
#include
The preprocessor directive #include is used to include a source file in our program.
Usually, header files with extension “.h” are used with #include. There are two
formats for using the #include:
#include <file>
and
#include “file”
In the first option, the file is searched in the C18 installation directory first and then
in the user search paths. In the second option, the specified file is searched in the
C18 project folder, then in the C18 installation folder, and then in the user search
paths. It is also possible to specify a complete directory path as
#include “C:\temp\last.h”
The above preprocessor commands are used for conditional compilation where
parts of the source code can be compiled only if certain conditions are met. In the
following example, the code section where variables A and B are cleared to zero is
compiled if M has a nonzero value, otherwise the code section where A and B are
both set to 1 is compiled. Notice that the #if must be terminated with #endif:
#if M
A = 0;
B = 0;
#else
A = 1;
B = 1;
#endif
We can also use the #elif condition that tests for a new condition if the earlier
condition was false:
#if M
A = 0;
B = 0;
#elif N
A = 1;
B = 1;
#else
A = 2;
B = 2;
#endif
#pragma
• #pragma code
• #pragma romdata
• #pragma idata
• #pragma config
• #pragma interrupt
• #pragma interruptflow
• #pragma varlocate
Oscillator Selection
OSC = LP LP
OSC = XT XT
OSC = HS HS
OSC = RC RC
OSC = EC EC and OSC2 as clock out
OSC = ECIO EC and OSC2 as port RA6
OSC = HSPLL HS–PLL enabled
OSC = RCIO RC and OSC2 as port RA6
Power-up Timer
PWRT = ON Timer enabled
PWRT = OFF Timer disabled
Watchdog Timer
WDT = OFF Watchdog disabled
WDT = ON Watchdog enabled
Watchdog Postscaler
WDTPS = 1 1:1
WDTPS = 2 1:2
WDTPS = 4 1:4
WDTPS = 8 1:8
WDTPS = 16 1:16
WDTPS = 32 1:32
WDTPS = 64 1:64
WDTPS = 128 1:128