Esterel EDA>Services>User Technical Faq
Esterel Studio Technical FAQ
- Esterel Language
- Can computations mix signed and unsigned numbers?
- How to get an unsigned operation when mixing signed and unsigned numbers?
- How to perform a signed operation with unsigned numbers?
- What is the difference between s0 : bool[4] and s1[4] : bool?
- What is the difference between t0 : value bool[4] and t1[4] : value bool?
- Can I use dynamic slices?
- Why is it forbidden to use a generic type for host functions and host procedures?
- Esterel Compilation
- HDL Generation
- Is the generated VHDL code compliant with VHDL'87 or VHDL'93?
- Is the generated Verilog code compliant with standard Verilog?
- My VHDL tool (simulator, synthesis tool, etc.) does not accept the VHDL’93 code (such as instantiations that are generated by Esterel Studio). What can I do?
- Where can I find the "HDL libraries" included in every generated HDL code?
- How can I reuse a legacy HDL module as one of my submodules?
- How can I generate purely combinational modules?
- What can I do to increase DFT compliance of the HDL modules generated by Esterel Studio?
- What is the Boot_0_0 register that is generated in the HDL code?
- What hardware will be generated from the Esterel arithmetic operators?
- Why are there two sequential processes in the generated HDL code, one with reset and one without?
- My design has all registered outputs. But when using optimization, some outputs have logic between the register and the pin. How can I get real registered outputs?
- The generated VHDL code uses IEEE.numeric_std library and unsigned/signed types to represent numbers. Is that synthesizable?
- My VHDL testbench works fine for RTL simulation, but not for post-synthesis simulation, because of incompatible types. How to fix that?
- When I instrument the generated HDL code for signal record, the HDL design is not exactly the same as the one being synthesized. How to ensure the two are functionally equivalent?
- My main unit is a multiclock. How does the signal record work?
- I am designing a multiclock model and its testbench with Esterel. My testbench generates the clock, but only after the reset. Thus my registers are not reset. How can I fix that?
- How can one know where registers have been inserted in the design?
- Sequential equivalence with legacy RTL: Can we transform HDL to Esterel?
- Formal Verification
- Can I use an assertion to define environment constraints?
- What do I do when my automatic assertions only hold when my environment constraints are respected?
- What can I do when verification returns "contradiction error"?
- How can I check that my constraints are consistent?
- How can I change the settings of the constraint consistency check?
- How does formal verification treat uninitialized and undefined values?
- How can I ensure the functional behavior of my design does not depend on uninitialized and undefined values?
- How can I give default values to uninitialized and undefined values?
- How can I see the values used for uninitialized and undefined values when generating counter-examples?
- System C Generation
Can computations mix signed and unsigned numbers?
Yes. When an arithmetic operator has both signed and unsigned arguments, unsigned arguments are converted into the corresponding signed numbers, and a signed operation is performed.
For instance, assuming x unsigned<[16]> = unsigned<2**16> and y signed<[8]> = signed<2**7>, in x+y, x is converted into signed<[17]> (one more bit for the sign), a signed addition is performed and the result is of type signed<2**16+2**7>.

How to get an unsigned operation when mixing signed and unsigned numbers?
When an unsigned operation is desired, then the abs operator or the assert_unsigned operator must be used to convert signed arguments into unsigned.
The abs operator takes the absolute value of the argument, whereas assert_unsigned is used when one knows that the argument is always positive.
The hardware generated with assert_unsigned is more efficient than with abs: assert_unsigned generates no gate, whereas abs does.
For example, consider x unsigned<[16]> = unsigned<2**16> and y signed<[8]> = signed<2**7>. x + y is by default a signed addition. To perform an unsigned addition, y needs be converted into an unsigned number:
- Using abs: x + abs(y) is of type: unsigned<2**16> + unsigned<2**7+1> returning unsigned<2**16+2**7>.
- Using assert_unsigned: x + assert_unsigned<[7]>(y) ) is of type: unsigned<2**16>, unsigned<2**7> returning unsigned<2**16+2**7-1>.

How to perform a signed operation with unsigned numbers?
When all the arguments of an arithmetic operator are unsigned, an unsigned operation is performed by default. To apply a signed operation, you just need to use an explicit '+' before one of the arguments. Thus, this argument becomes of signed type, then all arguments are converted into signed and a signed operation is performed.
For example, given x and y unsigned<[32]>, to perform a signed subtraction, one can write +x-y, or x-(+y), or +x-(+y). As x and y are both unsigned, x-y is an unsigned addition by default, and will trigger a run-time error if x < y. If the result of x-y is possibly negative, then '+' must be used before x or y to perform a signed subtraction.

What is the difference between s0 : bool[4] and s1[4] : bool?
In Esterel, a signal is composed of a status and a value. Signals s0 and s1 carry the same value, which is of type bool[4]. However, the status of s0 is a scalar, associated to the whole array value, whereas the status of s1 is an array of size 4: each value cell has its own status.
For example:
emit
for i < 4 do
if t[i] then {
?s0[i] <= '0,
?s1[i] <= '1
} end if
end for
Here, s0 is present when ?s0[0] or ?s1[1] or ?s1[2] or ?s1[3] is updated, whereas s1[i] is present when ?s1[i] is updated. Thus, by testing the status of s0, one can detect if any cell of ?s0 is updated, whereas the update of ?s1 can be detected cell per cell by testing each status cell.

What is the difference between t0 : value bool[4] and t1[4] : value bool?
The difference is subtle. Indeed, signals are manipulated in the same way in the Esterel program, since their statuses cannot be tested.
However, the Esterel compiler keeps internal status wires for t0 and t1 that can be used in dependencies, then the generated hardware might be slightly different for t0 and t1.
Also notice that, since t1 is a signal array, t1[.] can be used to bind submodule inputs and outputs in run statements, whereas t0[.] cannot.
For example:
module M:
input a : value bool;
...
for i < 8 dopar
run M [ t1[i]/a ] // t0[i]/a would be illegal

Can I use dynamic slices?
No. In Esterel, slices boundaries, like array sizes, signed sizes and unsigned sizes are required to be statically evaluable. Then dynamic slices must be expanded at Esterel level using u2onehot and for.dopar constructs.
For example:
sustain o[?start_idx?..start_idx+4]
<= i[?start_idx..?start_idx+4]
This is rejected; one should write:
signal start_idx_oh[n-4] in
sustain {
start_idx_oh <= u2onehot(?start_idx),
for i < n-4 do
for j < 5 do
o0[i+j] <= i0[i+j] if start_idx_oh[i]
end for
end for
}
end signal
In the same way:
sustain o[?first_idx..?last_idx] <= i[?first_idx..?last_idx]
This is rejected; one should write:
signal first_idx_oh[n], last_idx_oh[n], propagate[n] in
sustain {
first_idx_oh <= u2onehot(?first_idx),
last_idx_oh <= u2onehot(?last_idx),
seq {
o1[0] <= i1[0] if first_idx_oh[0],
propagate[0] <= first_idx_oh[0],
for i < n-1 doup
o1[i+1] <= i1[i+1]
if first_idx_oh[i+1] or propagate[i],
propagate[i+1] <= first_idx_oh[i+1] or
(propagate[i] and
not(last_idx_oh[i+1]))
end for
}
}
end signal

Why is it forbidden to use a generic type for host functions and host procedures?
A host function or a host procedure corresponds to an object in the host language. However generic data objects (including generic types) cannot currently "go outside" Esterel: all data objects must be instantiated from the main module point of view. Then host function and host procedures cannot have generic types.
A common mistake is to declare a host function with a generic type, because the function will be instantiated with a non-generic host function. In this case, this means that the function is not host, simply generic: one just needs to remove the host keyword in the declaration of the function.
Example:
main module m:
.
host function sum (unsigned, unsigned) : unsigned;
.
run sub [type unsigned/t; function sum/fct]
.
module sub:
generic type t;
host function fct (t, t) : t ;
Here function fct should not be declared host.

Why my Esterel program is found cyclic in non-expanded mode, but not in expanded mode?
This occurs when dependencies exist between the cells of an array signal. For example:
module rise:
constant n : unsigned<> = 8;
input a[n];
output x[n];
sustain {
x[0] <= a[0],
for i < n-1 dopar
x[i+1] <= x[i] or a[i+1]
end for
}
end module
In non-expanded mode, the compiler processes dependencies globally at the signal level: the program above is found cyclic because the signal x depends on itself. In expanded mode, the compiler expands signal arrays and then processes dependencies at the cell level: the program above is accepted because the dependencies between the cells of x are not cyclic. Sequenced signal equations allow compiling such programs in non-expanded mode:
module rise:
constant n : unsigned<> = 8;
input a[n];
output x[n];
sustain {
seq {
x[0] <= a[0],
for i < n-1 dopar
x[i+1] <= x[i] or a[i+1]
end for
}
}
end module
In a seq block, array signal self dependencies are ignored, and the signal equations are executed in the order specified by the program. The user shall write the equations in a correct order, which is checked when doing 'Check Model' in Esterel Studio. He should also take care that there is no cycle in cell dependencies, which is only checked by the compiler in expanded mode.

Is the generated Verilog code compliant with standard Verilog?
The generated Verilog code of Esterel Studio 5.3 is compliant with Verilog standard 1364-1995.
The generated Verilog code of Esterel Studio 5.4 by default is compliant with Verilog standard 1364-2001 and with the -vlog95compat option it is compliant with Verilog standard 1364-1995.

My VHDL tool (simulator, synthesis tool, etc.) does not accept the VHDL’93 code (such as instantiations that are generated by Esterel Studio). What can I do?
The generated VHDL code can be transformed so that instantiations are VHDL'87 compliant.
To do so, run the script ESHOME/lib/perl/to_vhdl87.prl, giving as input all the generated VHDL files as arguments.
This will generate new files, with the extension .87.vhd, and these will contain VHDL'87 instantiations.

Where can I find the "HDL libraries" included in every generated HDL code?
All the files are located in ESHOME/src/HDL.
Refer to the User Manual, Chapter "Generation Non-modular Hardware Description Language", to learn which of these files must be compiled with your design, depending on the selected options.

How can I reuse a legacy HDL module as one of my submodules?
Follow these steps:
- Be sure the Esterel HDL generator is in Modular HDL generation mode.
- Tag the module to be replaced as "toplevel module".
- Check the "do not generate code" checkbox of this module.
- Generate and execute Makefile.
This will produce a file containing only the interface of the module. You can either complete it with your HDL code or completely replace the file with the one containing your legacy code.

How can I generate purely combinational modules?
Follow these steps:
- Make sure the corresponding Esterel module does not contain any pause statements.
- Tag all signals and variables as "temp".
- Tag the module as "toplevel module", then generate modular HDL code.
- Select the "sweep" optimization for this module. Deselect the clock and reset options, to avoid declaring useless clock and reset pins at the boundary.

What can I do to increase DFT compliance of the HDL modules generated by Esterel Studio?
Although DFT compliance can be very different from one organization to another, there are two useful options that can help:
- The -Lhdl:-extra_interface option allows you to declare additional pins, such as "test_enable" and "test_data". Be sure to insert this option into the advanced options box of the module configuration.
- To ensure all registers have a reset, and to get statistically the same number of 0 and 1 reset registers, select "all_altern" in the "reset of data registers" item of the module configuration.

What is the Boot_0_0 register that is generated in the HDL code?
The boot register embodies the initial state of the implicit state machine that is described by the Esterel design. It is at 1 at the first clock cycle and then 0 at all the following clock cycles. Unformally speaking, it is used to boot the design after the reset, hence its name. Notice that this register is not useful for combinational designs and for purely datapath designs. For such designs, it will be generated by default in the HDL code, but it will be removed by the synthesis tool since it is not be connected to the design. If you wish to remove the boot register from the generated HDL code, please use the Esterel optimization (just in sweep mode).
What hardware will be generated from the Esterel arithmetic operators?
In general, the HDL generator replaces Esterel arithmetic operators by function calls. These functions are defined in the "Esterel HDL libraries" and are based on standard VHDL libraries or built-in Verilog operators. Some operators (such as multiplication, division, modulo, and power) are converted into shifts and masks when this is possible.
To ease the identification of the HDL code generated from a specific Esterel operator call, add a label on the operator, such as emit ?a <= ?b +@MyAdder ?c. The generated code will contain "MyAdder" as a comment next to the HDL code generated for the addition.

Why are there two sequential processes in the generated HDL code, one with reset and one without?
In circuits generated from Esterel, all control registers have a fixed reset value. The first sequential process infers these registers. The data registers have a reset value only when they are generated from top-level signals and variables having an initial value. The first sequential process also infers them. The other data registers have no reset value, so the second process infers them.
It is usually better for synthesis to group all registers with reset in one process and all those without a reset in another process.

My design has all registered outputs. But when using optimization, some outputs have logic between the register and the pin. How can I get real registered outputs?
The sequential optimization function of Esterel Studio has full freedom to re-encode the states. Usually, equivalent registers are merged, and exclusive registers are shared, thereby adding inverters. Thus if, for example, two registered outputs are always opposite, the optimization will keep only one register and rebuild the second output using an inverter.
The advanced option, -keep_output_reg, of the Esterel compiler can be used to force optimization to keep the registers driving outputs directly. Be aware, however, that using this option may result in a slightly less efficient optimization.

The generated VHDL code uses IEEE.numeric_std library and unsigned/signed types to represent numbers. Is that synthesizable?
This library, and unsigned/signed types, may not be accepted by your synthesis tool. IEEE.std_logic_arith and the std_logic_vector type may be needed for synthesis. You can select this library and type in the configuration panel of your project. Refer to the User Manual, Chapter "Generating Non-modular Hardware Description Language", for more details.

My VHDL testbench works fine for RTL simulation, but not for post-synthesis simulation, because of incompatible types. How to fix that?
Some synthesis tools generate a netlist where interface signals do not have the same types as in the RTL. For example array ranges have type INTEGER instead of NATURAL. This can be corrected by removing the definitions of types generated by the synthesizer in the netlist, and reusing the data package generated by Esterel Studio.

When I instrument the generated HDL code for signal record, the HDL design is not exactly the same as the one being synthesized. How to ensure the two are functionally equivalent?
The instrumentation for signal record is enclosed into pragmas understood by most synthesis tools. Thus the same HDL code can be used for simulation with signal record, and for synthesis.
Another approach consists in enabling the "Split signal record" option. That way, two HDL files are generated. One contains the design, usable for both simulation and synthesis. The other contains an extra module performing the signal record, to be used for simulation only.

My main unit is a multiclock. How does the signal record work?
The signal record for multiclock modules dumps all input signals on every positive clock edge of all input clocks. It dumps however only the clock that triggered the event. This creates a re-sampled scenario where every tick represents a clock event. The chronological order is kept but the simulation in Esterel Studio will display a different time scale since all clock edge changes are triggered by a tick. The simulation time with its corresponding tick number can be found in the .eso simulation dump file, as comment behind every ";". This helps debugging special sequences in the scenario.

I am designing a multiclock model and its testbench with Esterel. My testbench generates the clock, but only after the reset. Thus my registers are not reset. How can I fix that?
This happens because the reset has been declared synchronous, which is the default. In this case, reset occurs before the clock is active and so is not taken into account. To reset registers at proper reset time, declare the reset as asynchronous in the module configuration panel.

How can one know where registers have been inserted in the design?
Hdl registers are all generated by a small number of constructs in the Esterel code: pause statement or derivatives (await, sustain, every, etc.) and status pre or next for control registers. Signals and variables not declared temp generate data registers. The Model Info tool of ES lists all these registers for your design.

Sequential equivalence with legacy RTL: Can we transform HDL to Esterel?
Not directly but you can do one the following:
- Reuse legacy HDL code into an Esterel design. Use modular HDL generation and replace some sub-modules by the legacy HDL code.
- A straightforward traduction of Verilog netlists into Esterel code is possible. The generated Esterel model will be at the bit level. This allows for example to check the equivalence between original HDL and new Esterel code.

Can I use an assertion to define environment constraints?
Yes, an assertion can be selected as constraint for formal verification. When an assertion "A" is selected as constraint the formal verification constrains the verification to input sequences for which "A" always holds and hence ignores any input sequence that violates "A".

What do I do when my automatic assertions only hold when my environment constraints are respected?
Automatic assertions are assertions just like user-assertions except that they are automatically extracted from your design. Hence you can use environment constraints in the same way as for any verification goal.

What can I do when verification returns "contradiction error"?
When formal verification returns the error "Contradiction" it means that your environment constraints are too restrictive and must be relaxed. In fact, it means that no combination of inputs is possible at a certain sequential depth without violating at least one of your environment constraints.
To correct the problem you must relax your environment constraints. Environment constraints are defined using input relations, input constraints, assertion constraints and external constraints.
To help track-down the constraints that are contradictory or inconsistent, the Design Verifier implements a dedicated consistency check, see "How can I check that my constraints are consistent?"

How can I check that my constraints are consistent?
The Design Verifier implements a dedicated consistency check for constraints. The consistency check is available directly from IDE in the selected-constraints panels of assertion verification and equivalence checking.
Environment constraints are inconsistent when at some sequential depth no combination of inputs is possible without violating at least one constraint.
The consistency check is a bounded check; incrementally at each sequential depth k it checks that either the constraints are:
- consistent at depth k, that is, there is a least one input sequence of length k that satisfy all constraints, or
- inconsistent at depth k, that is, no input sequence of length k satisfies all constraints. If the constaints are found inconsistent at depth k+1, the Design Verifier generates an input sequence of length k (that satisfies all constraints) that can be used to debug the connstraints. It also extracts an inconsistent subset of constraints to help locate the problem.

How can I change the settings of the constraint consistency check?
The constraint consistency check shares its settings with Bounded Model Checking (BMC).
The max depth, timeout, and additional options defined in the settings for BMC applies also to the constraint consistency check.

How does formal verification treat uninitialized and undefined values?
In formal verification, uninitialized and undefined values are treated as (free) inputs.
This means that the verification considers
- Any possible initial value for an uninitialized memory element
- Any possible value for any signal value or variable that is read before it is written.
In particular, this means that counter-examples generated by formal verification can depend on such (free) inputs if the functional behavior of your design depends on uninitialized and undefined values.

How can I ensure the functional behavior of my design does not depend on uninitialized and undefined values?
Use formal verification to verify all read-before-write automatic assertions.
If all read-before-write assertions are verified you know that the functional behavior of you design does not depend on any uninitialized and undefined values.

How can I give default values to uninitialized and undefined values?
Use the option -init_variables to force all uninitialized and undefined values to default values.
The default value:
- For Booleans the default value is false.
- For signed, unsigned, integer, float, and double the default value is 0.
- For enumeration types the default value is the first element in the type.
- For strings the default value is the string: "default_string".

How can I see the values used for uninitialized and undefined values when generating counter-examples?
Use the option -use_init_annotations to annotate counter-examples with the uninitialized and undefined values used.
The values are annotations and are not used when simulating hence if the values do not correspond to those used in simulation the counter-example is not correctly simulated and thus might not lead to the expected result.

What SystemC can Esterel Studio generate?
The SystemC generated by Esterel Studio 5.4 is intended to simulate at the cycle-accurate level the synchronous hardware specified by the Esterel design.
Transactional level SystemC generation is currently under study.

What is the difference between the generated "signal-based" SystemC and "cycle-based" SystemC?
Esterel Studio is able to generate two kinds of SystemC:
- Signal-based SystemC, which behaves exactly as the generated hardware in a zero-delay RTL simulation. Signal-based SystemC is slower than cycle-based SystemC, because of its sensitivity to inputs and to registers (internal state) like RTL.
- Cycle-based SystemC, which is sensitive only to clock: cycle-based SystemC samples inputs and computes next state and outputs at every active clock edge, then exactly once and only once per clock cycle. Cycle-based SystemC is faster than signal-based, but, unlike hardware, it does not react to combinational feedbacks from environment.

I have different results when simulating the generated SystemC and the generated HDL! How is that possible?
Esterel compilation flow guarantees that Esterel simulation, Esterel formal verification and Esterel generated target codes are fully aligned. Different behaviors generally come from a run-time error occurring during the execution of the target code: a read-before-write error, a single violation error or an out-of-bound error.
To locate the run-time error, you have 2 options:
- Use formal verification and check all auto-assertions
- Use the signal-record feature on the generated code and replay the created scenario in Esterel Studio. The run-time error will be raised during simulation.

