Statements

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.

Assignment

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.

If statement

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

Case statement

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

For statement

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
 
arx/statements.txt · Last modified: 2023/07/17 22:40 by 127.0.0.1