Engee documentation
Notebook

Binary logic

In this example we will investigate the application of binary logic for solving logical problems using an equation written in Julia programming language and its implementation in a model for Verilog code generation and verification of this code. The example and its implementation are described in more detail at the following link: https://engee.com/community/ru/catalogs/projects/binarnaia-logika.

The purpose of this demonstration is to show the possibilities of the generator and code optimisation on a simple example.

Description of binary equation

Let us specify the states of our system, which in this case will be three: 𝐴, 𝐵 and 𝐶. In this case, the state 𝐴 will be determined randomly: if a random value of 𝑋 is greater than 0.5, then 𝐴 is true, otherwise it is false.

Our logic is defined by the following equation: Z = ((A and B) or (C and B)).

In [ ]:
A = rand() > 0.5
println("A = $(A)")
B = false
C = true
println("B = $(B)")
println("C = $(C)")

Z = ((A && B) || (C && B))
println("Z = $(Z)")
A = false
B = false
C = true
Z = false

Binary logic modelling and code generation

In [ ]:
# Подключение вспомогательной функции запуска модели.
function run_model( name_model)
    
    Path = (@__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
    sleep(0.1)
    return model_output
end

run_model("Logical_Operator") # Запуск модели.
Z_model = collect(Z_model).value[end]
println()
println("Z_model = $(Z_model)")
Building...
Progress 0%
Progress 100%
Progress 100%

Z_model = false

Now let's perform code generation from the model and analyse the result.

In [ ]:
engee.generate_code(
"$(@__DIR__)/Logical_Operator.engee",
"$(@__DIR__)/V_Code",
subsystem_name="Logical"
)
// Generated by CIRCT firtool-1.62.1
module Logical_Operator_Logical(
  input  clock,
         reset,
  output io_Out1
);

  assign io_Out1 = 1'h0;
endmodule

[ Info: Generated code and artifacts: /user/my_projects/Demo/Work/logical_operator/V_Code

Conclusion

In [ ]:
open("$(@__DIR__)/V_Code/Logical_Operator_Logical.v", "r") do file
    for line in eachline(file)
        println(line)
    end
end
// Generated by CIRCT firtool-1.62.1
module Logical_Operator_Logical(
  input  clock,
         reset,
  output io_Out1
);

  assign io_Out1 = 1'h0;
endmodule

As we can see, the code optimiser has removed all the logic except for the output value. This is due to the fact that we have explicitly set the parameters of constants. Accordingly, all values inside the code are static, so generating code from them is not an optimal solution in terms of FPGA resources. We will get the same effect if we use the block Terminator. Any branch of the model solution ending with this block will be discarded from the final generated code.

Blocks used in example