Перейти к содержанию
    

Фильтр скользящее среднее

5 hours ago, Halfback said:

Nick_K

 Надо проверять, т.к. вычисление должно происходить за один такт. Я с плисиной и verilog еще сравнительно мало работаю.

Достаточно работать только на положительном фронте. За один такт скользящее среднее не выполнится, нужно же ещё буфер заполнить; оно работает конвейером.

Два фронта используют, когда нужно последовательно две операции за такт выполнять. 

Выше кидал ссылку на исходники sma: берите, изучите и юзайте

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Приветствую!

10 minutes ago, quato_a said:

Два фронта используют ...

Два фронта  нужно лишь  когда  надо схитро...пить  чтобы  при P&R  проблемы с времянкой решить. В некоторых случаях  помогает.  В остальном как выше,  уже говорили, на уровне лог. дизайна, одного фронта более чем достаточно.
Хотите делать две операции за такт - поднимайте частоту и все одно работайте на  одном фронте. 

 

Удачи! Rob.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

12 hours ago, Halfback said:

Пока мне не очень понятно насколько корректно будет работать описание внутри posegde и negedge если их засунуть в один posegde. Надо проверять, т.к. вычисление должно происходить за один такт.

надо проверять, и в данном случае можно разобраться на примере вашего фильтра

тестбенч похож на предыдущий, но упрощен входной сигнал

Spoiler

`timescale 1 ns / 1 ps

module MovAverageFilter_tb();

reg clk = 0;

always #(10.0/2)
begin
    clk = ~clk;
end

reg [15:0] datain;


MovAverageFilter 
#(
    .FIFO_LEN_LOG(4)//,
)
MovAverageFilter_i
(
	.clk(clk),
	.datain(datain)//,
);

MovAverageFilter_ram 
#(
    .FIFO_LEN_LOG(4)//,
)
MovAverageFilter_ram_i
(
	.clk(clk),
	.datain(datain)//,
);

initial
begin
    datain = 0;
end

always @(posedge clk)
begin
    
    datain = 1;
    
end

endmodule

 

сначала посмотрим вариант с такой конструкцией

    always @(posedge clk)
    begin
        fifo_sum <= fifo_sum + datain - FIFO[k];        
    end
    
    always @(negedge clk)
    begin
        FIFO[k] <= datain;
        k <= k + 1;
    end
Spoiler

 module MovAverageFilter_ram
#(
    parameter FIFO_LEN_LOG = 4//,
)
(
    input  clk,
    input  [15:0] datain,
    output [15:0] dataout//,
);
    localparam FIFO_LEN = (1 << FIFO_LEN_LOG);
    
    reg [15:0] FIFO [0:FIFO_LEN-1];
    reg [FIFO_LEN_LOG+15:0] fifo_sum = 0;
    integer i;
     
    reg [FIFO_LEN_LOG-1:0] k = 0;
    
    initial
    begin
        for(i = FIFO_LEN-1; i >= 0; i=i-1)  FIFO[i] = 16'd0;
    end
    
    
    always @(posedge clk)
    begin
        fifo_sum <= fifo_sum + datain - FIFO[k];        
    end
    
    always @(negedge clk)
    begin
        FIFO[k] <= datain;
        k <= k + 1;
    end
    
    wire [15:0] FIFO_k;
    assign FIFO_k = FIFO[k];
    
    assign dataout = fifo_sum >> FIFO_LEN_LOG;
    
endmodule 

 

фильтр работает не так как задумывалось

res_01.thumb.png.97967acaf237774412c52880069781c4.png

накопление в фильтре идет, но размер окна равен 15, а не 16. счетчик (k) расчитывается в @(negedge clk), а используется как в @(negedge clk), так и в @(posedge clk). задержка в памяти с учетом этого получается на такт меньше, и тут для получения нужной задержки требовалось бы еще задержать счетчик (k) до  @(posedge clk) для использования в чтении с памяти, или брать предыдущий отсчет считывая (k-1) или задерживать выход памяти, или делать что-то еще, но

но посмотрим, что будет с конструкцией

    always @(posedge clk)
    begin
        fifo_sum <= fifo_sum + datain - FIFO[k];        
    end
    
    always @(posedge clk)
    begin
        FIFO[k] <= datain;
        k <= k + 1;
    end
Spoiler

 module MovAverageFilter_ram
#(
    parameter FIFO_LEN_LOG = 4//,
)
(
    input  clk,
    input  [15:0] datain,
    output [15:0] dataout//,
);
    localparam FIFO_LEN = (1 << FIFO_LEN_LOG);
    
    reg [15:0] FIFO [0:FIFO_LEN-1];
    reg [FIFO_LEN_LOG+15:0] fifo_sum = 0;
    integer i;
     
    reg [FIFO_LEN_LOG-1:0] k = 0;
    
    initial
    begin
        for(i = FIFO_LEN-1; i >= 0; i=i-1)  FIFO[i] = 16'd0;
    end
    
    
    always @(posedge clk)
    begin
        fifo_sum <= fifo_sum + datain - FIFO[k];        
    end
    
    always @(posedge clk)
    begin
        FIFO[k] <= datain;
        k <= k + 1;
    end
    
    wire [15:0] FIFO_k;
    assign FIFO_k = FIFO[k];
    
    assign dataout = fifo_sum >> FIFO_LEN_LOG;
    
endmodule 

 

все работает так как предполагалось изначально

res_02.thumb.png.1e08d1c2f4f07df2b70056fb2b67f445.png

счетчик (k) расчитывается  в @(posedge clk) и используется в @(posedge clk), кольцевой буфер дает задержку ровно на 16 тактов, как и положено, размер окна равен 16

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...