diff options
Diffstat (limited to 'fpga/usrp3/lib/rfnoc/moving_sum.v')
-rw-r--r-- | fpga/usrp3/lib/rfnoc/moving_sum.v | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/fpga/usrp3/lib/rfnoc/moving_sum.v b/fpga/usrp3/lib/rfnoc/moving_sum.v new file mode 100644 index 000000000..e3d8e2889 --- /dev/null +++ b/fpga/usrp3/lib/rfnoc/moving_sum.v @@ -0,0 +1,80 @@ +// +// Copyright 2016 Ettus Research +// Copyright 2018 Ettus Research, a National Instruments Company +// +// SPDX-License-Identifier: LGPL-3.0-or-later +// + +module moving_sum #( + parameter MAX_LEN = 1023, + parameter WIDTH = 16 +)( + input clk, input reset, input clear, + input [$clog2(MAX_LEN+1)-1:0] len, + input [WIDTH-1:0] i_tdata, input i_tlast, input i_tvalid, output i_tready, + output [WIDTH+$clog2(MAX_LEN+1)-1:0] o_tdata, output o_tlast, output o_tvalid, input o_tready +); + + wire signed [WIDTH+$clog2(MAX_LEN+1)-1:0] sum; + reg signed [WIDTH+$clog2(MAX_LEN+1)-1:0] sum_reg; + reg [$clog2(MAX_LEN+1)-1:0] full_count, len_reg; + reg len_changed; + + wire full = (full_count == len_reg); + wire do_op = (i_tvalid & i_tready); + + wire i_tready_int, i_tvalid_int; + wire fifo_tvalid, fifo_tready; + wire [WIDTH-1:0] fifo_tdata; + + axi_fifo #(.WIDTH(WIDTH), .SIZE($clog2(MAX_LEN))) axi_fifo ( + .clk(clk), .reset(reset | len_changed), .clear(clear), + .i_tdata(i_tdata), .i_tvalid(do_op), .i_tready(), + .o_tdata(fifo_tdata), .o_tvalid(fifo_tvalid), .o_tready(fifo_tready), + .occupied(), .space()); + + assign fifo_tready = i_tvalid & i_tready_int & full; + + always @(posedge clk) begin + if (reset | clear | len_changed) begin + full_count <= 'd0; + end else begin + if (do_op & ~full) begin + full_count <= full_count + 1; + end + end + end + + assign sum = sum_reg + $signed(i_tdata) - (full ? $signed(fifo_tdata) : 0); + + always @(posedge clk) begin + if (reset | clear) begin + sum_reg <= 'd0; + len_reg <= 1; + len_changed <= 1'b0; + end else begin + len_reg <= (len == 0) ? 1 : len; + if (len_reg != len) begin + len_changed <= 1'b1; + end else begin + len_changed <= 1'b0; + end + if (len_changed) begin + sum_reg <= 'd0; + end else if (do_op) begin + sum_reg <= sum; + end + end + end + + // Output register + axi_fifo_flop #(.WIDTH(WIDTH+$clog2(MAX_LEN+1)+1)) axi_fifo_flop ( + .clk(clk), .reset(reset), .clear(clear), + .i_tdata({i_tlast,sum}), .i_tvalid(i_tvalid_int), .i_tready(i_tready_int), + .o_tdata({o_tlast,o_tdata}), .o_tvalid(o_tvalid), .o_tready(o_tready), + .occupied(), .space()); + + assign i_tready = (~full | (fifo_tvalid & full)) & i_tready_int & ~len_changed; + assign i_tvalid_int = (~full | (fifo_tvalid & full)) & i_tvalid & ~len_changed; + +endmodule // moving_sum |