Statements are the Arx language elements that are found in a
component description or a function declaration
between the keywords begin
and end
. In this section, the
different type of statements are presented.
The assignment statement is used to specify a new value for a signal, where a signal is either a register or variable (see the page on declarations). An assignment has the following syntax:
<signal> = <expression>
So, the equal sign (=
) indicates that the expression specified
at its right-hand side should become the new value of the signal
specified at its left-hand side. Here are some examples of assignment
statements:
sum = left + right storage = storage + convert(T_narrow, data_in)
The left-hand side is either a variable signal or a register signal. Variable signals need to be assigned first before they can be used in an expression. So, as far as variable assignment is concerned, Arx behaves as a sequential language.
Register signals can be used without restrictions. An assignment specifies the value of that signal in the next clock cycle.
In the presentation about Arx data types, examples can be found of assignments involving individual bits in a vector, ranges of bits and array elements.
An if
statement is used to specify conditional computations. The
value of a Boolean condition determines
which one of the two provided computations should be chosen. An if
statement corresponds to a multiplexer in hardware. The syntax of an
if
statement is as follows:
if <condition> <statements> *{ elif <condition> <statements> }* -{ else <statements> }- end
Here is a fragment of Arx code that uses an if
statement.
if data_in > 10 newval = data_in - 10 elif data_in > 20 newval = data_in - 15 else newval = data_in end
The fragment below illustrates that Arx is not a strict
single-assignment language. A variable may be assigned twice an
expression. A coding style where
the assignment is first performed unconditionally and
later inside an if
statement without else
branch, can save
many lines of code in complex situations with many nested conditional
statements.
It is, however, preferable to write single-assignment
code to stay as closely as possible to the semantics of hardware where
a wire cannot be both an input and an output of some computation
without creating an algebraic loop.
newval = data_in if newval > 10 newval = newval - 10 end
Whereas if
statements are appropriate to model conditional
computations where the outcome of some expression has a Boolean value,
the case
statement is used to model situations where the outcome
of some expression has usually more than the two values that determine
the flow of computation. Typical uses of case
statements are found
in the descriptions of finite state machines or truth-table-style
specifications.
The case
statement has the following syntax.
case <expression> +{ when <value> <statement> }+ -{ else <statement> }- end
The expressed behavior states that <expression> should be evaluated
first. The when
clause the <value> of which matches the result of
the evaluation is then selected and its associated <statement> is then
performed. It may be that none of the when
clauses matches in
which case the <statement> belonging to the else
clause is
executed, if present.
The example below shows a typical next-state computation
in a finite-state machine. The register signal output_state
is of
enumeration type out_state
.
case output_state when out_state.start if start_of_processing output_state = out_state.processing end when out_state.processing if end_of_processing output_state = out_state.ready end else # default case; no action end
The next fragment of code shows a case
statement to model a
truth-table style in which a number num_in
is mapped onto a number num_out
:
case num_in when 0 num_out = 3 when 1 num_out = 2 when 2 num_out = 0 else num_out = 1 end
A for
statement is used to indicate regularity in some
computation. It implies repetition in space as opposed to
repetition in time that is normally designated in traditional
imperative programming languages. All computations in a for
statement
take place within a single clock cycle, the same way that
any component body is computed in one clock cycle. The for
statement has the following syntax:
for <index variable> in <lower bound> : <upper bound> +{ <statement> }+ end
The <index variable> is an integer that does not need to be declared.
The statements specified in the body of the for
statement are
supposed to be executed as many times as there are integers between
the given lower and upper bounds (inclusive). The bounds should be
manifest or data independent, which means that they may be
either constants or expressions the values of which can be computed at
compile time. An example of a for
statement is given below:
for i in 1:half_size delay_group[i] = delay_line[half_size-i] + delay_line[half_size+i] end