Jump to content

    
Halfback

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

Recommended Posts

5 hours ago, Halfback said:

Nick_K

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

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

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

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

Share this post


Link to post
Share on other sites

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

10 minutes ago, quato_a said:

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

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

 

Удачи! Rob.

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.