1///////////////////////////////////////////////////////////////////
2//
3// Copyright 2018 Ettus Research, A National Instruments Company
4//
5// SPDX-License-Identifier: LGPL-3.0-or-later
6//
7// Module: rhodium_lo_gain
8// Description:
9//   LO Gain controller for Rhodium
10//   Implements a gain index register (not a table)
11//
12//   Provides 1 SPI slave:
13//     The "ctrl" slave takes in a gain index and drives the DSA with that
14//     value.
15//   The SPI formats are provided below.
16//////////////////////////////////////////////////////////////////////
17
18`default_nettype none
19
20/**
21* SPI DATA FORMAT (left-most bit is first)
22*   CTRL
23*     M {table_sel[1:0], rsvd, gain[4:0], rsvd[1:0], wr_dsa1, ------rsvd[5:0], wr_dsa2, ----rsvd[5:0]
24*     S {-------------------------------, --------------rsvd[3:0], gain1[4:0], -rsvd[1:0], gain2[4:0]}
25*/
26module rhodium_lo_gain #(
27  parameter TABLE_NUM = 2'b01
28) (
29  input  wire       ctrl_sck,
30  input  wire       ctrl_csb,
31  input  wire       ctrl_mosi,
32  output reg        ctrl_miso,
33  output wire [4:0] dsa,
34  output reg        dsa1_le,
35  output reg        dsa2_le
36);
37
38localparam CNT_GAIN1_DRIVE = 10,
39           CNT_DSA1_LE_RISE = 11,
40           CNT_DSA1_LE_FALL = 14,
41           CNT_GAIN1_RELEASE = 17;
42localparam CNT_GAIN2_DRIVE = 17,
43           CNT_DSA2_LE_RISE = 18,
44           CNT_DSA2_LE_FALL = 21,
45           CNT_GAIN2_RELEASE = 24;
46
47reg  [4:0]  ctrl_bit_cnt;
48reg  [1:0]  ctrl_tbl;
49reg  [5:0]  ctrl_index;
50reg  [5:0]  gain1, gain2;
51reg gain1_t;
52reg gain2_t;
53
54assign dsa = (!gain1_t | !gain2_t) ? ctrl_index[4:0] : 5'b11111;
55
56// Cycle counter for where we are in protocol and shift register for input
57// Also controls timing of DSAs' latch enable signals
58always @ (posedge ctrl_sck or posedge ctrl_csb)
59begin
60  if (ctrl_csb) begin
61    ctrl_bit_cnt <= 5'd0;
62    dsa1_le      <= 1'b0;
63    dsa2_le      <= 1'b0;
64    gain1_t      <= 1'b1;
65    gain2_t      <= 1'b1;
66  end else if (!ctrl_csb) begin
67    if (ctrl_bit_cnt < 23) begin
68      ctrl_bit_cnt <= ctrl_bit_cnt + 5'd1;
69    end
70
71    if (ctrl_bit_cnt < 8) begin
72      {ctrl_tbl, ctrl_index} <= {ctrl_tbl[0], ctrl_index, ctrl_mosi};
73    end
74
75    if (ctrl_tbl == TABLE_NUM) begin
76      if ((ctrl_bit_cnt == CNT_GAIN1_DRIVE) && (ctrl_mosi)) begin
77        gain1   <= ctrl_index;
78        gain1_t <= 1'b0;
79      end else if ((gain1_t == 1'b0) && (ctrl_bit_cnt == CNT_DSA1_LE_RISE)) begin
80        dsa1_le <= 1'b1;
81      end else if ((gain1_t == 1'b0) && (ctrl_bit_cnt == CNT_DSA1_LE_FALL)) begin
82        dsa1_le <= 1'b0;
83      end else if ((gain1_t == 1'b0) && (ctrl_bit_cnt == CNT_GAIN1_RELEASE)) begin
84        gain1_t <= 1'b1;
85      end
86
87      if ((ctrl_bit_cnt == CNT_GAIN2_DRIVE) && (ctrl_mosi)) begin
88        gain2   <= ctrl_index;
89        gain2_t <= 1'b0;
90      end else if ((gain2_t == 1'b0) && (ctrl_bit_cnt == CNT_DSA2_LE_RISE)) begin
91        dsa2_le <= 1'b1;
92      end else if ((gain2_t == 1'b0) && (ctrl_bit_cnt == CNT_DSA2_LE_FALL)) begin
93        dsa2_le <= 1'b0;
94      end else if ((gain2_t == 1'b0) && (ctrl_bit_cnt == CNT_GAIN2_RELEASE)) begin
95        gain2_t <= 1'b1;
96      end
97    end
98  end
99end
100
101// SPI readback for ctrl bus, based on current bit count
102always @ (negedge ctrl_sck)
103begin
104  case (ctrl_bit_cnt) // Shift out on neg edge
105  11:      ctrl_miso <= gain1[5];
106  12:      ctrl_miso <= gain1[4];
107  13:      ctrl_miso <= gain1[3];
108  14:      ctrl_miso <= gain1[2];
109  15:      ctrl_miso <= gain1[1];
110  16:      ctrl_miso <= gain1[0];
111  18:      ctrl_miso <= gain2[5];
112  19:      ctrl_miso <= gain2[4];
113  20:      ctrl_miso <= gain2[3];
114  21:      ctrl_miso <= gain2[2];
115  22:      ctrl_miso <= gain2[1];
116  23:      ctrl_miso <= gain2[0];
117  default: ctrl_miso <= 1'b0;
118  endcase
119end
120
121
122endmodule // rhodium_lo_gain
123`default_nettype wire
124
125