aboutsummaryrefslogtreecommitdiffstats
path: root/fpga/usrp3/lib/rfnoc/fosphor/f15_maxhold.v
blob: ecd92adfbc5020a3c93f449e49553cb6b9c12e75 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
/*
 * f15_maxhold.v
 *
 * Computes the max hold (with epsilon decay)
 *
 * Copyright (C) 2015  Ettus Corporation LLC
 * Copyright 2018 Ettus Research, a National Instruments Company
 *
 * SPDX-License-Identifier: LGPL-3.0-or-later
 *
 * vim: ts=4 sw=4
 */

`ifdef SIM
`default_nettype none
`endif

module f15_maxhold #(
	parameter integer Y_WIDTH = 12,
	parameter integer X_WIDTH = 16,
	parameter integer FRAC_WIDTH = 8
)(
	input  wire [Y_WIDTH-1:0] yin_0,
	input  wire [X_WIDTH-1:0] x_0,
	input  wire [15:0] rng_0,
	input  wire [15:0] epsilon_0,
	input  wire clear_0,
	output wire [Y_WIDTH-1:0] yout_4,
	input  wire clk,
	input  wire rst
);

	 localparam integer I_WIDTH = X_WIDTH + FRAC_WIDTH;

	// Signals
	reg [X_WIDTH-1:0] x_1;
	reg [I_WIDTH  :0] y_1;
	reg [Y_WIDTH  :0] d_1;
	reg clear_1;

	reg [Y_WIDTH-1:0] y_2;

	// Stage 1
	always @(posedge clk)
	begin
		x_1 <= x_0;
		y_1 <= { 1'b0, yin_0, rng_0[I_WIDTH-Y_WIDTH-1:0] } - epsilon_0;
		d_1 <= { 1'b0, yin_0 } - { 1'b0, x_0[X_WIDTH-1:X_WIDTH-Y_WIDTH] };
		clear_1 <= clear_0;
	end

	// Stage 2
	always @(posedge clk)
	begin
		if (clear_1)
			y_2 <= 0;
		else if (d_1[Y_WIDTH])
			// x is larger, use this
			y_2 <= x_1[X_WIDTH-1:X_WIDTH-Y_WIDTH];
		else
			// y is larger, take old y with small decay
			if (y_1[I_WIDTH])
				y_2 <= 0;
			else
				y_2 <= y_1[I_WIDTH-1:I_WIDTH-Y_WIDTH];
	end

	// Apply two more delay to match the avg block
	delay_bus #(2, Y_WIDTH) dl_y (y_2, yout_4, clk);

endmodule // f15_maxhold