Engee 文档
Notebook

Verilog平均滤波器

平均滤波器是一种广泛用于数字信号和图像处理以降低噪声水平的数字滤波器。 中值滤波器为非线性FIR滤波器。 在这个例子中,我们将看看它的简化实现,看看它的工作原理,以及从模型生成代码,并使用icarus verilog检查生成代码的正确性。 下图显示了用于过滤窗口10的已实现过滤器的模型。

image.png

接下来,我们将定义模型的启动函数,并测试模型并记录其运行结果。

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
Out[0]:
run_model (generic function with 1 method)

接下来,让我们运行这个模型。

In [ ]:
run_model("Averaging_filter") # Запуск модели.
Building...
Progress 0%
Progress 100%
Progress 100%
Out[0]:
SimulationResult(
    "filter_out" => WorkspaceArray{Fixed{1, 10, 2, Int16}}("Averaging_filter/filter_out")
,
    "count" => WorkspaceArray{Fixed{1, 10, 2, Int16}}("Averaging_filter/count")

)
In [ ]:
out_model = collect(simout["Averaging_filter/filter_out"]).value
count = collect(simout["Averaging_filter/count"]).value

plot(count, label="Вход фильтра")
plot!(out_model, label="Выход фильтра")
Out[0]:

正如我们所看到的,模型工作正常,计数器值被平均。

代码生成

现在让我们继续从计数器块和接收模块的过滤器生成代码。 稍后,我们将组装最终项目。

In [ ]:
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"
)

伊卡洛斯Verilog

接下来,为了进行测试,我们将实现TestBench并在Icarus Verilog中运行它,这是一个适用于Linux和其他类UNIX系统的免费(GPL)Verilog模拟器。 它是一个功能齐全的Verilog HDL(IEEE-1364)编译器和模拟器。

主要用途:

-合成前的数字电路验证
-Verilog代码的测试和调试

主要特点:

-将Verilog编译为可执行代码(iverilog)
-使用虚拟机进行模拟(vvp)
-支持大部分Verilog-2005标准
-在GTKWave中生成用于分析的VCD文件

基本工具:

  1. iverilog -编译器(转换。字节码中的v文件)
  2. vvp -模拟器(执行编译的字节码)
  3. gtkwave -时间图表查看器(单独的程序)

典型工作流程:

``'bash

汇编

的iverilog-o sim设计.v测试台。v

模拟仿真

vvp sim卡

或与vcd生成可视化

vvp sim-lxt2
gtkwave波形。vcd


In [ ]:
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
Содержимое файла /user/start/examples/codegen/averaging_filter_verilog/Averaging_prj/tb.v:
==================================================
module tb;
  reg clock;
  reg reset;
  wire [9:0] cnt_out;
  wire [9:0] filter_out;
  real real_value;
  Averaging_filter_cnt u_cnt (
    .clock(clock),
    .reset(reset),
    .io_Out1(cnt_out)
  );
  Averaging_filter_Averaging_filter u_filter (
    .clock(clock),
    .reset(reset),
    .io_Count(cnt_out),
    .io_Out1(filter_out)
  );
  always @(*) begin
    real_value = $itor($signed(filter_out)) / 4.0;
  end
  always #5 clock = ~clock;
  initial begin
    clock = 0;
    reset = 1;
    $display("№\tЗначение");
    $display("--\t-------");
    #15 reset = 0;
  end
  integer output_count = 0;
  always @(posedge clock) begin
    if (!reset) begin
      output_count = output_count + 1;
      $display("%d\t%0.2f", output_count, real_value);
      if (output_count >= 8) begin
        $finish;
      end
    end
  end
endmodule
==================================================
Конец файла

此代码是Verilog上的测试平台,用于测试两个模块。: Averaging_filter_cnt (柜台)及 Averaging_filter_Averaging_filter (过滤器)。

测试台产生时钟信号,重置模块,然后开始它们的操作,并以表格格式输出滤波器输出的前8个值,并以定点转换(格式\1,10,2})为实数除以4,输出第8个值后停止模拟。

In [ ]:
run(`cd $(@__DIR__)/Averaging_prj`)
# Компиляция
run(`iverilog -o sim tb.v Averaging_filter_cnt.v Averaging_filter_Averaging_filter.v`)
# Запуск симуляции
run(`vvp sim`)
№	Значение
--	-------
          1	-3.00
          2	-6.00
          3	-8.75
          4	-11.25
          5	12.25
          6	9.75
          7	7.50
          8	5.25
Out[0]:
Process(`vvp sim`, ProcessExited(0))
In [ ]:
# Вывод заголовка таблицы
println("№\tЗначение")
println("--\t-------")

# Вывод только первых 8 значений
for i in 1:8
    println("$i\t$(out_model[i])")
end
№	Значение
--	-------
1	-3.0
2	-5.75
3	-8.5
4	-11.25
5	12.25
6	9.75
7	7.5
8	5.25

正如我们所看到的,结果几乎完全匹配,但问题是模块 **Averaging_filter_Averaging_filter**具有内部寄存器(UnitDelay_state等。)需要时间来初始化和填充管道。 前几个输出值可能不正确或不稳定,直到过滤器充满数据。

结论

在这个例子中,我们分析了使用Engee内置模拟器进行Verilog代码验证的可能性。 这种方法使我们不仅可以获取代码,还可以在不离开环境的情况下验证其可操作性。