1/*
2 * f15_rise_decay.v
3 *
4 * Applies the rise or decay to a given value.
5 *
6 * Copyright (C) 2014  Ettus Corporation LLC
7 * Copyright 2018 Ettus Research, a National Instruments Company
8 *
9 * SPDX-License-Identifier: LGPL-3.0-or-later
10 *
11 * vim: ts=4 sw=4
12 */
13
14`ifdef SIM
15`default_nettype none
16`endif
17
18module f15_rise_decay #(
19	parameter integer WIDTH = 9
20)(
21	input  wire [WIDTH-1:0] in_0,	// input
22	output reg  [WIDTH-1:0] out_5,	// output
23	input  wire [15:0] k_0,			// time constant
24	input  wire ena_0,				// If ena=0, then output original value
25	input  wire mode_0,				// 0=rise, 1=decay
26	input  wire [15:0] rng,
27	input  wire clk,
28	input  wire rst
29);
30
31	// Signals
32	reg mode_1;
33	reg [4:0] inmode_1;
34
35	wire [WIDTH-1:0] in_2;
36	wire ena_2;
37	wire [6:0] opmode_2;
38	reg  [3:0] alumode_2;
39
40	wire [47:0] pout_4;
41	wire pmatch_4;
42
43
44	// Main DSP
45	// --------
46
47	// Mode control
48		// For rise  we have INMODE=00000 (A=A2,   B=B2), ALUMODE=0000 (C+M)
49		// For decay we have INMODE=01100 (A=D-A2, B=B2), ALUMODE=0011 (C-M)
50	always @(posedge clk)
51	begin
52		mode_1 <= mode_0;
53
54		if (mode_0)
55			inmode_1 <= 5'b00000;
56		else
57			inmode_1 <= 5'b01100;
58
59		if (mode_1)
60			alumode_2 <= 4'b0011;
61		else
62			alumode_2 <= 4'b0000;
63	end
64
65		// When not enabled, we use OPMODE to do pass-through
66	delay_bit #(2) dl_ena (ena_0, ena_2, clk);
67	assign opmode_2  = ena_2 ? 7'b0110101 : 7'b0110000;
68
69	// Delay for input to C
70	delay_bus #(2, WIDTH) dl_in (in_0, in_2, clk);
71
72	// Instance
73	DSP48E1 #(
74		.A_INPUT("DIRECT"),
75		.B_INPUT("DIRECT"),
76		.USE_DPORT("TRUE"),
77		.USE_MULT("MULTIPLY"),
78		.AUTORESET_PATDET("NO_RESET"),
79		.MASK({1'b1, {(31-WIDTH){1'b0}}, {(WIDTH+16){1'b1}}}),
80		.PATTERN(48'h000000000000),
81		.SEL_MASK("MASK"),
82		.SEL_PATTERN("PATTERN"),
83		.USE_PATTERN_DETECT("PATDET"),
84		.ACASCREG(1),
85		.ADREG(1),
86		.ALUMODEREG(1),
87		.AREG(1),
88		.BCASCREG(2),
89		.BREG(2),
90		.CARRYINREG(1),
91		.CARRYINSELREG(1),
92		.CREG(1),
93		.DREG(1),
94		.INMODEREG(1),
95		.MREG(1),
96		.OPMODEREG(1),
97		.PREG(1),
98		.USE_SIMD("ONE48")
99	)
100	dsp_exp_I (
101		.PATTERNDETECT(pmatch_4),
102		.P(pout_4),
103		.ACIN(30'h0),
104		.BCIN(18'h0),
105		.CARRYCASCIN(1'h0),
106		.MULTSIGNIN(1'h0),
107		.PCIN(48'h000000000000),
108		.ALUMODE(alumode_2),
109		.CARRYINSEL(3'h0),
110		.CEINMODE(1'b1),
111		.CLK(clk),
112		.INMODE(inmode_1),
113		.OPMODE(opmode_2),
114		.RSTINMODE(rst),
115		.A({{(30-WIDTH){1'b0}}, in_0}),
116		.B({ 2'h0, k_0}),
117		.C({{(32-WIDTH){1'b0}}, in_2, rng}),
118		.CARRYIN(1'b0),
119		.D({{(24-WIDTH){1'b0}}, 1'b1, {WIDTH{1'b0}}}),
120		.CEA1(1'b0),
121		.CEA2(1'b1),
122		.CEAD(1'b1),
123		.CEALUMODE(1'b1),
124		.CEB1(1'b1),
125		.CEB2(1'b1),
126		.CEC(1'b1),
127		.CECARRYIN(1'b1),
128		.CECTRL(1'b1),
129		.CED(1'b1),
130		.CEM(1'b1),
131		.CEP(1'b1),
132		.RSTA(rst),
133		.RSTALLCARRYIN(rst),
134		.RSTALUMODE(rst),
135		.RSTB(rst),
136		.RSTC(rst),
137		.RSTCTRL(rst),
138		.RSTD(rst),
139		.RSTM(rst),
140		.RSTP(rst)
141	);
142
143
144	// Saturation
145	// ----------
146
147	always @(posedge clk)
148	begin
149		if (rst == 1)
150			out_5 <= 0;
151		else
152			if (pout_4[47] == 1)
153				out_5 <= {WIDTH{1'b0}};
154			else if (pmatch_4 == 0)
155				out_5 <= {WIDTH{1'b1}};
156			else
157				out_5 <= pout_4[WIDTH+15:16];
158	end
159
160endmodule // f15_rise_decay
161