The Verilog Averaging Filter
An averaging filter is a type of digital filter widely used in digital signal and image processing to reduce noise levels. The median filter is a nonlinear FIR filter. In this example, we will look at its simplified implementation and see how well it works, as well as generate code from the model and check the correctness of the generated code using icarus verilog. The figure below shows the model of the implemented filter for a filtering window of 10.
 
Next, we will define the launch function of the model and test the model and record the results of its operation.
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
Next, let's run this model.
run_model("Averaging_filter") # Запуск модели.
out_model = collect(simout["Averaging_filter/filter_out"]).value
count = collect(simout["Averaging_filter/count"]).value
plot(count, label="Вход фильтра")
plot!(out_model, label="Выход фильтра")
As we can see, the model is working correctly, and the counter values are averaged.
Code generation
Now let's move on to generating code from the counter block and the filter from the received modules. Later, we will assemble the final project.
engee.generate_code(
"$(@__DIR__)/Averaging_filter.engee",
"$(@__DIR__)/Averaging_prj",
subsystem_name="cnt"
)
engee.generate_code(
"$(@__DIR__)/Averaging_filter.engee",
"$(@__DIR__)/Averaging_prj",
subsystem_name="Averaging_filter"
)
Icarus Verilog
Next, for testing, we will implement TestBench and run it in Icarus Verilog, a free (GPL) Verilog simulator for Linux and other UNIX-like systems. It is a fully functional Verilog HDL (IEEE-1364) compiler and simulator.
Main purpose:
- Verification of digital circuits before synthesis
- Testing and debugging of Verilog code
Key features:
- Compilation of Verilog into executable code (iverilog)
- Simulation using a virtual machine (vvp)
- Support for most of the Verilog-2005 standard
- Generation of VCD files for analysis in GTKWave
Basic tools:
- iverilog— the compiler (converts .v files in bytecode)
- vvp— simulator (executes compiled bytecode)
- gtkwave— time chart viewer (separate program)
Typical workflow:
# Compilation
of iverilog -o sim design.v testbench.v
# Simulation
vvp sim
# Or with VCD generation for visualization
vvp sim -lxt2
gtkwave waveform.vcd
filename = "$(@__DIR__)/Averaging_prj/tb.v"
try
    if !isfile(filename)
        println("Файл $filename не найден!")
        return
    end
    println("Содержимое файла $filename:")
    println("="^50)
    content = read(filename, String)
    println(content)
    println("="^50)
    println("Конец файла")
catch e
    println("Ошибка при чтении файла: ", e)
end
This code is a testbench on Verilog for testing two modules.: Averaging_filter_cnt (counter) and Averaging_filter_Averaging_filter (filter).
The test bench generates a clock signal, resets the modules, then starts their operation and outputs the first 8 values of the filter output in a table format with fixed-point conversion (format {1,10,2}) to real numbers divided by 4, stopping the simulation after outputting the 8th value.
run(`cd $(@__DIR__)/Averaging_prj`)
# Компиляция
run(`iverilog -o sim tb.v Averaging_filter_cnt.v Averaging_filter_Averaging_filter.v`)
# Запуск симуляции
run(`vvp sim`)
# Вывод заголовка таблицы
println("№\tЗначение")
println("--\t-------")
# Вывод только первых 8 значений
for i in 1:8
    println("$i\t$(out_model[i])")
end
As we can see, the results almost completely matched, but the problem is that the module Averaging_filter_Averaging_filter has internal registers (UnitDelay_state, etc.) that take time to initialize and fill the pipeline. The first few output values may be incorrect or unstable until the filter is filled with data.
Conclusion
In this example, we have analyzed the possibilities of Verilog code verification using the built-in simulator in Engee. This approach allows us not only to obtain the code, but also to verify its operability without leaving the environment.
