quato_a 3 July 29, 2021 Posted July 29, 2021 · Report post 5 hours ago, Halfback said: Nick_K, Надо проверять, т.к. вычисление должно происходить за один такт. Я с плисиной и verilog еще сравнительно мало работаю. Достаточно работать только на положительном фронте. За один такт скользящее среднее не выполнится, нужно же ещё буфер заполнить; оно работает конвейером. Два фронта используют, когда нужно последовательно две операции за такт выполнять. Выше кидал ссылку на исходники sma: берите, изучите и юзайте Quote Share this post Link to post Share on other sites More sharing options...
RobFPGA 8 July 29, 2021 Posted July 29, 2021 · Report post Приветствую! 10 minutes ago, quato_a said: Два фронта используют ... Два фронта нужно лишь когда надо схитро...пить чтобы при P&R проблемы с времянкой решить. В некоторых случаях помогает. В остальном как выше, уже говорили, на уровне лог. дизайна, одного фронта более чем достаточно. Хотите делать две операции за такт - поднимайте частоту и все одно работайте на одном фронте. Удачи! Rob. Quote Share this post Link to post Share on other sites More sharing options...
stealthisname 7 July 30, 2021 Posted July 30, 2021 · Report post 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 фильтр работает не так как задумывалось накопление в фильтре идет, но размер окна равен 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 все работает так как предполагалось изначально счетчик (k) расчитывается в @(posedge clk) и используется в @(posedge clk), кольцевой буфер дает задержку ровно на 16 тактов, как и положено, размер окна равен 16 Quote Share this post Link to post Share on other sites More sharing options...