The Scrambler
This example discusses the possibilities of verifying the generated code using C functions in Engee using the scrambler model as an example.
A scrambler is a device or algorithm that performs a reversible transformation of a digital stream to give it the properties of a random sequence without changing the transmission rate. This example uses scrambling with a pseudorandom binary sequence (PRBS) generated by an LFSR of length 15 with an initial value of 100101010000000.
Next, let's look at the implemented scrambling and descrambling scheme. It and a bitwise comparison of the operation of this algorithm are shown in the figure below.
Let's run this model using the startup function described by us and save the results of the bit error.
function run_model(name_model)
Path = string(@__DIR__) * "/" * name_model * ".engee"
if name_model in [m.name for m in engee.get_all_models()] # Проверка условия загрузки модели в ядро
model = engee.open( name_model ) # Открыть модель
model_output = engee.run( model, verbose=true ); # Запустить модель
else
model = engee.load( Path, force=true ) # Загрузить модель
model_output = engee.run( model, verbose=true ); # Запустить модель
engee.close( name_model, force=true ); # Закрыть модель
end
return model_output
end
@time run_model("Scrambler_descrambler")
BER = simout["Scrambler_descrambler/Error Rate Calculation.Output_1"];
BER = collect(BER)
BER[end-3:end,:]
As we can see, the algorithm is working correctly. Now let's move on to the settings of the code generator. The screenshot below shows the following points. The target platform is selected as Verilog, and comments in the generated code are disabled (this is done to visually simplify its readability), and C Function generation is enabled to verify the generated code.

Now let's start generating the code and the validation model.
engee.generate_code(
"$(@__DIR__)/Scrambler_descrambler.engee",
"$(@__DIR__)/V_Code",
subsystem_name="Scrambler_descrambler"
)
Let's analyze the generated files.

As we can see, in addition to the verilog code file, the folder also contains:
- executable file .so
- Library file .h
- Code file.jl
Let's start with the last one. This file allows us to generate a model containing a C function for comparison with the original model.
# This is a verification script for the Scrambler_descrambler_Scrambler_descrambler generated code.
# Run this code in order to create a verification model with a CFunction block inside that behaves like the original model.
# CFunction variables
start_code = """
Scrambler_descrambler_Scrambler_descrambler_init();"""
output_code = """
Scrambler_descrambler_Scrambler_descrambler_eval(In1,
&Out1;);
"""
terminate_code = """
Scrambler_descrambler_Scrambler_descrambler_final();"""
# Close
try engee.close("Scrambler_descrambler_Scrambler_descrambler_verification";force=true) catch end
# Create
engee.create("Scrambler_descrambler_Scrambler_descrambler_verification")
# Add Blocks
engee.add_block("/Basic/Ports & Subsystems/In1", "Scrambler_descrambler_Scrambler_descrambler_verification/In1")
engee.add_block("/Basic/User-Defined Functions/C Function", "Scrambler_descrambler_Scrambler_descrambler_verification/")
engee.add_block("/Basic/Ports & Subsystems/Out1", "Scrambler_descrambler_Scrambler_descrambler_verification/Out1")
# Edit block parameters
engee.set_param!("Scrambler_descrambler_Scrambler_descrambler_verification/In1", "PortDimensions" => "()")
engee.set_param!("Scrambler_descrambler_Scrambler_descrambler_verification/In1", "SignalType" => "real")
engee.set_param!("Scrambler_descrambler_Scrambler_descrambler_verification/In1", "OutDataTypeStr" => "Bool")
engee.set_param!("Scrambler_descrambler_Scrambler_descrambler_verification/C Function", "OutputCode" => output_code, "StartCode" => start_code, "TerminateCode" => terminate_code)
engee.set_param!("Scrambler_descrambler_Scrambler_descrambler_verification/C Function", "Inputs" => 1)
engee.set_param!("Scrambler_descrambler_Scrambler_descrambler_verification/C Function", "Outputs" => 1)
engee.set_param!("Scrambler_descrambler_Scrambler_descrambler_verification/C Function", "InputPort1Label" => "In1")
engee.set_param!("Scrambler_descrambler_Scrambler_descrambler_verification/C Function", "InputPort1VarName" => "In1")
engee.set_param!("Scrambler_descrambler_Scrambler_descrambler_verification/C Function", "InputPort1Type" => "bool")
engee.set_param!("Scrambler_descrambler_Scrambler_descrambler_verification/C Function", "InputPort1Size" => "()")
engee.set_param!("Scrambler_descrambler_Scrambler_descrambler_verification/C Function", "SampleTime" => "0.01")
engee.set_param!("Scrambler_descrambler_Scrambler_descrambler_verification/C Function", "Parameters" => 0)
engee.set_param!("Scrambler_descrambler_Scrambler_descrambler_verification/C Function", "OutputPort1Label" => "Out1")
engee.set_param!("Scrambler_descrambler_Scrambler_descrambler_verification/C Function", "OutputPort1VarName" => "Out1")
engee.set_param!("Scrambler_descrambler_Scrambler_descrambler_verification/C Function", "OutputPort1Type" => "bool")
engee.set_param!("Scrambler_descrambler_Scrambler_descrambler_verification/C Function", "OutputPort1Size" => "()")
engee.set_param!("Scrambler_descrambler_Scrambler_descrambler_verification/C Function", "IncludeDirectories" => "/user/my_projects/Demo/Work/scrambler_Verilog/V_Code/obj_dir")
engee.set_param!("Scrambler_descrambler_Scrambler_descrambler_verification/C Function", "LibraryDirectories" => "/user/my_projects/Demo/Work/scrambler_Verilog/V_Code/obj_dir")
engee.set_param!("Scrambler_descrambler_Scrambler_descrambler_verification/C Function", "Headers" => "Scrambler_descrambler_Scrambler_descrambler_cfn_api.h ")
engee.set_param!("Scrambler_descrambler_Scrambler_descrambler_verification/C Function", "Libraries" => "libScrambler_descrambler_Scrambler_descrambler.so ")
# Edit model parameters
engee.set_param!("Scrambler_descrambler_Scrambler_descrambler_verification", "FixedStep" => 0.01)
engee.set_param!("Scrambler_descrambler_Scrambler_descrambler_verification", "StartTime" => 0.0)
engee.set_param!("Scrambler_descrambler_Scrambler_descrambler_verification", "StopTime" => 10)
engee.set_param!("Scrambler_descrambler_Scrambler_descrambler_verification", "EnableMultiTasking" => false)
# Add lines
engee.add_line("Scrambler_descrambler_Scrambler_descrambler_verification", "In1/1", "C Function/1")
engee.add_line("Scrambler_descrambler_Scrambler_descrambler_verification", "C Function/1", "Out1/1")
# Save
engee.save("Scrambler_descrambler_Scrambler_descrambler_verification.engee"; force=true)
Let's run this file and get the C function block, which we will later compare with the original model.
Based on the results of the generated file execution .jl we got a block that accesses the library and the executable file. Now let's build several models based on this block. Let's start with a model similar to the original one.
Let's run this model and compare the execution time and the general behavior of the model.
@time run_model("Scrambler_descrambler_verification")
BER = simout["Scrambler_descrambler_verification/Error Rate Calculation.Output_1"];
BER = collect(BER)
BER[end-3:end,:]
As we can see, the model is faster than the original model and, judging by the BER, is identical to the original model. Now let's compare these blocks in the general model.

Let's run this model and compare the error.
run_model("Scrambler_add_verification")
err = simout["Scrambler_add_verification/err"];
println("Кол-во ошибок: $(sum(collect(err).value))")
As we can see from the results, the blocks are identical, which means that the code generation was performed correctly.
Conclusion
In this example, we demonstrated a code generation verification tool, and also successfully generated the verilog code of the scrambler model.
The code itself is presented below.
```verilog
module Scrambler_descrambler_Scrambler_descrambler(
input clock,
reset,
io_In1,
output io_Out1
);
reg UnitDelay_13_state;
reg UnitDelay_2_state;
reg UnitDelay_13_1_state;
reg UnitDelay_2_1_state;
reg UnitDelay_14_state;
reg UnitDelay_14_1_state;
reg UnitDelay_3_state;
reg UnitDelay_3_1_state;
reg UnitDelay_4_state;
reg UnitDelay_4_1_state;
reg UnitDelay_state;
reg UnitDelay_1_state;
reg UnitDelay_5_state;
reg UnitDelay_5_1_state;
reg UnitDelay_6_state;
reg UnitDelay_1_1_state;
reg UnitDelay_1_2_state;
reg UnitDelay_6_1_state;
reg UnitDelay_7_state;
reg UnitDelay_7_1_state;
reg UnitDelay_8_state;
reg UnitDelay_8_1_state;
reg UnitDelay_9_state;
reg UnitDelay_9_1_state;
reg UnitDelay_10_state;
reg UnitDelay_10_1_state;
reg UnitDelay_11_state;
reg UnitDelay_11_1_state;
reg UnitDelay_12_state;
reg UnitDelay_12_1_state;
wire LogicalOperator = UnitDelay_13_state ^ UnitDelay_14_state;
wire LogicalOperator_1 = UnitDelay_13_1_state ^ UnitDelay_14_1_state;
always @(posedge clock) begin
if (reset) begin
UnitDelay_13_state <= 1'h0;
UnitDelay_2_state <= 1'h0;
UnitDelay_13_1_state <= 1'h0;
UnitDelay_2_1_state <= 1'h0;
UnitDelay_14_state <= 1'h0;
UnitDelay_14_1_state <= 1'h0;
UnitDelay_3_state <= 1'h0;
UnitDelay_3_1_state <= 1'h0;
UnitDelay_4_state <= 1'h0;
UnitDelay_4_1_state <= 1'h0;
UnitDelay_state <= 1'h0;
UnitDelay_1_state <= 1'h0;
UnitDelay_5_state <= 1'h0;
UnitDelay_5_1_state <= 1'h0;
UnitDelay_6_state <= 1'h0;
UnitDelay_1_1_state <= 1'h0;
UnitDelay_1_2_state <= 1'h0;
UnitDelay_6_1_state <= 1'h0;
UnitDelay_7_state <= 1'h0;
UnitDelay_7_1_state <= 1'h0;
UnitDelay_8_state <= 1'h0;
UnitDelay_8_1_state <= 1'h0;
UnitDelay_9_state <= 1'h0;
UnitDelay_9_1_state <= 1'h0;
UnitDelay_10_state <= 1'h0;
UnitDelay_10_1_state <= 1'h0;
UnitDelay_11_state <= 1'h0;
UnitDelay_11_1_state <= 1'h0;
UnitDelay_12_state <= 1'h0;
UnitDelay_12_1_state <= 1'h0;
end
else begin
UnitDelay_13_state <= UnitDelay_12_state;
UnitDelay_2_state <= UnitDelay_1_1_state;
UnitDelay_13_1_state <= UnitDelay_12_1_state;
UnitDelay_2_1_state <= UnitDelay_1_2_state;
UnitDelay_14_state <= UnitDelay_13_state;
UnitDelay_14_1_state <= UnitDelay_13_1_state;
UnitDelay_3_state <= UnitDelay_2_1_state;
UnitDelay_3_1_state <= UnitDelay_2_state;
UnitDelay_4_state <= UnitDelay_3_state;
UnitDelay_4_1_state <= UnitDelay_3_1_state;
UnitDelay_state <= LogicalOperator;
UnitDelay_1_state <= LogicalOperator_1;
UnitDelay_5_state <= UnitDelay_4_1_state;
UnitDelay_5_1_state <= UnitDelay_4_state;
UnitDelay_6_state <= UnitDelay_5_1_state;
UnitDelay_1_1_state <= UnitDelay_1_state;
UnitDelay_1_2_state <= UnitDelay_state;
UnitDelay_6_1_state <= UnitDelay_5_state;
UnitDelay_7_state <= UnitDelay_6_state;
UnitDelay_7_1_state <= UnitDelay_6_1_state;
UnitDelay_8_state <= UnitDelay_7_1_state;
UnitDelay_8_1_state <= UnitDelay_7_state;
UnitDelay_9_state <= UnitDelay_8_1_state;
UnitDelay_9_1_state <= UnitDelay_8_state;
UnitDelay_10_state <= UnitDelay_9_state;
UnitDelay_10_1_state <= UnitDelay_9_1_state;
UnitDelay_11_state <= UnitDelay_10_state;
UnitDelay_11_1_state <= UnitDelay_10_1_state;
UnitDelay_12_state <= UnitDelay_11_state;
UnitDelay_12_1_state <= UnitDelay_11_1_state;
end
end // always @(posedge)
assign io_Out1 = LogicalOperator_1 ^ LogicalOperator ^ io_In1;
endmodule