aboutsummaryrefslogtreecommitdiffstats
path: root/fpga/usrp3/lib/rfnoc/fosphor/f15_wf_agg.v
diff options
context:
space:
mode:
Diffstat (limited to 'fpga/usrp3/lib/rfnoc/fosphor/f15_wf_agg.v')
-rw-r--r--fpga/usrp3/lib/rfnoc/fosphor/f15_wf_agg.v189
1 files changed, 189 insertions, 0 deletions
diff --git a/fpga/usrp3/lib/rfnoc/fosphor/f15_wf_agg.v b/fpga/usrp3/lib/rfnoc/fosphor/f15_wf_agg.v
new file mode 100644
index 000000000..7b12bc4d5
--- /dev/null
+++ b/fpga/usrp3/lib/rfnoc/fosphor/f15_wf_agg.v
@@ -0,0 +1,189 @@
+/*
+ * f15_wf_agg.v
+ *
+ * Watefall Aggregation
+ *
+ * Copyright (C) 2016 Ettus Corporation LLC
+ *
+ * vim: ts=4 sw=4
+ */
+
+`ifdef SIM
+`default_nettype none
+`endif
+
+module f15_wf_agg #(
+ parameter integer Y_WIDTH = 12,
+ parameter integer X_WIDTH = 16,
+ parameter integer DECIM_WIDTH = 8
+)(
+ input wire [Y_WIDTH-1:0] yin_0,
+ input wire [X_WIDTH-1:0] x_0,
+ input wire valid_0,
+ input wire last_0,
+ input wire [15:0] rng_0,
+
+ output wire [Y_WIDTH-1:0] yout_3,
+ output wire [7:0] zout_3,
+ output wire zvalid_3,
+
+ input wire [1:0] cfg_div,
+ input wire cfg_mode, // 0=MaxHold, 1=Average
+ input wire [DECIM_WIDTH-1:0] cfg_decim,
+ input wire cfg_decim_changed,
+
+ input wire clk,
+ input wire rst
+);
+
+ localparam integer R_WIDTH = X_WIDTH + 9;
+
+ // Signals
+ // Data pah
+ reg [R_WIDTH-1:0] xe_1;
+ reg [R_WIDTH-1:0] ye_1;
+
+ wire over_2;
+ reg [R_WIDTH-1:0] r_2;
+ reg [Y_WIDTH-1:0] x_2;
+ reg [Y_WIDTH-1:0] y_2;
+
+ reg [Y_WIDTH-1:0] y_3;
+
+ // Control
+ reg [DECIM_WIDTH:0] decim_cnt;
+ reg init_0;
+ wire init_2;
+ reg init_force_0;
+ reg flush_0;
+ reg zvalid_1;
+
+
+ // Datapath
+ // --------
+
+ // X predivision mux
+ always @(posedge clk)
+ begin
+ case (cfg_div)
+ 2'b00:
+ xe_1 <= { 1'd0, x_0, 8'd0 }; // 1:1
+
+ 2'b01:
+ xe_1 <= { 4'd0, x_0, 5'd0 }; // 1:8
+
+ 2'b10:
+ xe_1 <= { 7'd0, x_0, 2'd0 }; // 1:64
+
+ 2'b11:
+ xe_1 <= { 9'd0, x_0 }; // 1:256
+ endcase
+ end
+
+ // Y register
+ always @(posedge clk)
+ begin
+ if (cfg_mode)
+ // Average
+ ye_1 <= { 1'b0, yin_0, rng_0[R_WIDTH-Y_WIDTH-2:0] };
+ else
+ // Max Hold
+ ye_1 <= { 1'b0, yin_0, {(R_WIDTH-Y_WIDTH-1){1'b0}} };
+ end
+
+ // Adder / Substractor
+ always @(posedge clk)
+ begin
+ if (cfg_mode)
+ // Average
+ r_2 <= ye_1 + xe_1;
+ else
+ // Max-Hold
+ r_2 <= ye_1 - xe_1;
+ end
+
+ assign over_2 = r_2[R_WIDTH-1];
+
+ // Registers for the two branches.
+ always @(posedge clk)
+ begin
+ x_2 <= xe_1[R_WIDTH-2:R_WIDTH-Y_WIDTH-1];
+ y_2 <= ye_1[R_WIDTH-2:R_WIDTH-Y_WIDTH-1];
+ end
+
+ // Output mux
+ always @(posedge clk)
+ begin
+ // If first : take x_2
+ // If average :
+ // - If overflow = 0 -> take r_2
+ // - If overflow = 1 -> sature to all 1's
+ // If max-hold
+ // - If overflow = 0 -> take y_2
+ // - If overflow = 1 -> take x_2
+ if (init_2)
+ y_3 <= x_2;
+ else if (cfg_mode)
+ y_3 <= over_2 ? { (Y_WIDTH){1'b1} } : r_2[R_WIDTH-2:R_WIDTH-Y_WIDTH-1];
+ else
+ y_3 <= over_2 ? x_2 : y_2;
+ end
+
+ assign yout_3 = y_3;
+ assign zout_3 = y_3[Y_WIDTH-1:Y_WIDTH-8];
+
+
+ // Control
+ // -------
+
+ // 1-in-N decimation counter
+ always @(posedge clk)
+ begin
+ if (rst)
+ decim_cnt <= 0;
+ else if (cfg_decim_changed)
+ // Force Reload
+ decim_cnt <= { 1'b0, cfg_decim };
+ else if (valid_0 & last_0)
+ if (decim_cnt[DECIM_WIDTH])
+ // Reload
+ decim_cnt <= { 1'b0, cfg_decim };
+ else
+ // Just decrement
+ decim_cnt <= decim_cnt - 1;
+ end
+
+ // Decimation flush & init states
+ always @(posedge clk)
+ begin
+ if (rst) begin
+ // Initial state
+ flush_0 <= 1'b0;
+ init_0 <= 1'b1;
+ init_force_0 <= 1'b0;
+ end else begin
+ if (valid_0 & last_0) begin
+ // Flushing
+ flush_0 <= decim_cnt[DECIM_WIDTH];
+
+ // Init after flush or if forced
+ init_0 <= flush_0 | init_force_0;
+ end
+
+ // Init forcing after a decim change
+ if (cfg_decim_changed)
+ init_force_0 <= 1'b1;
+ else if (valid_0 & last_0)
+ init_force_0 <= 1'b0;
+ end
+ end
+
+ delay_bit #(2) dl_init(init_0, init_2, clk);
+
+ // Z-output valid
+ always @(posedge clk)
+ zvalid_1 <= valid_0 & flush_0;
+
+ delay_bit #(2) dl_zvalid(zvalid_1, zvalid_3, clk);
+
+endmodule // f15_wf_agg