/ 9_Firmware / 9_2_FPGA / plfm_chirp_controller.v
plfm_chirp_controller.v
  1  `timescale 1ns / 1ps
  2  
  3  module plfm_chirp_controller_enhanced (
  4      input wire clk_120m,
  5      input wire clk_100m,
  6      input wire reset_n,
  7      input wire new_chirp,
  8      input wire new_elevation,
  9      input wire new_azimuth,
 10      input wire mixers_enable,
 11      output reg [7:0] chirp_data,
 12      output reg chirp_valid,
 13  	 output wire new_chirp_frame,
 14      output reg chirp_done,
 15      output reg rf_switch_ctrl,
 16      output wire rx_mixer_en,
 17      output wire tx_mixer_en,
 18      output wire adar_tx_load_1,
 19      output wire adar_rx_load_1,
 20      output wire adar_tx_load_2,
 21      output wire adar_rx_load_2,
 22      output wire adar_tx_load_3,
 23      output wire adar_rx_load_3,
 24      output wire adar_tx_load_4,
 25      output wire adar_rx_load_4,
 26      output reg adar_tr_1,
 27      output reg adar_tr_2,
 28      output reg adar_tr_3,
 29      output reg adar_tr_4,
 30      output reg [5:0] chirp_counter,
 31      output reg [5:0] elevation_counter,
 32      output reg [5:0] azimuth_counter
 33  );
 34  
 35  // Chirp parameters
 36  parameter F_START = 30000000;       // 30 MHz (starting frequency)
 37  parameter F_END = 10000000;         // 10 MHz (ending frequency)
 38  parameter FS = 120000000;           // 120 MHz
 39  
 40  // Timing parameters
 41  parameter T1_SAMPLES = 3600;        // 30us at 120MHz
 42  parameter T1_RADAR_LISTENING = 16440; //137us at 120MHz
 43  parameter T2_SAMPLES = 60;          // 0.5us at 120MHz
 44  parameter T2_RADAR_LISTENING = 20940; //174.5us at 120MHz
 45  parameter GUARD_SAMPLES = 21048;    // 175.4us at 120MHz
 46  
 47  // Chirp and beam parameters
 48  parameter CHIRP_MAX = 32;
 49  parameter ELEVATION_MAX = 31;
 50  parameter AZIMUTH_MAX = 50;
 51  
 52  // State parameters
 53  parameter IDLE        = 3'b000;
 54  parameter LONG_CHIRP  = 3'b001;
 55  parameter LONG_LISTEN = 3'b010;
 56  parameter GUARD_TIME  = 3'b011;
 57  parameter SHORT_CHIRP = 3'b100;
 58  parameter SHORT_LISTEN = 3'b101;
 59  parameter DONE        = 3'b110;
 60  
 61  reg [2:0] current_state;
 62  reg [2:0] next_state;
 63  
 64  // Control registers
 65  reg [15:0] sample_counter;
 66  
 67  // Edge detection for input signals
 68  wire chirp__toggling, elevation__toggling, azimuth__toggling;
 69  
 70  // LUTs for chirp waveforms
 71  (* ram_style = "block" *) reg [7:0] long_chirp_lut [0:3599];  // T1_SAMPLES-1
 72  reg [7:0] short_chirp_lut [0:59];   // T2_SAMPLES-1
 73  
 74  // Registered BRAM read output (sync-only for BRAM inference)
 75  reg [7:0] long_chirp_rd_data;
 76  
 77  // Edge detection
 78  assign chirp__toggling = new_chirp;
 79  assign elevation__toggling = new_elevation;
 80  assign azimuth__toggling = new_azimuth;
 81  assign new_chirp_frame = (current_state == IDLE && next_state == LONG_CHIRP);
 82  
 83  // Mixer TX/RX sequencing — mutually exclusive based on chirp FSM state.
 84  // TX mixer active during chirp transmission, RX mixer during listen.
 85  // Both require mixers_enable (STM32 master enable) to be high.
 86  assign tx_mixer_en = mixers_enable && (current_state == LONG_CHIRP ||
 87                                         current_state == SHORT_CHIRP);
 88  assign rx_mixer_en = mixers_enable && (current_state == LONG_LISTEN ||
 89                                         current_state == SHORT_LISTEN);
 90  
 91  // ADTR1000 pull to ground tx and rx load pins if not used
 92  assign adar_tx_load_1 = 1'b0;
 93  assign adar_rx_load_1 = 1'b0;
 94  assign adar_tx_load_2 = 1'b0;
 95  assign adar_rx_load_2 = 1'b0;
 96  assign adar_tx_load_3 = 1'b0;
 97  assign adar_rx_load_3 = 1'b0;
 98  assign adar_tx_load_4 = 1'b0;
 99  assign adar_rx_load_4 = 1'b0;
100  
101  
102  
103  
104  // LUT Initialization
105  // Long PLFM chirp LUT loaded from .mem file for BRAM inference
106  initial begin
107      $readmemh("long_chirp_lut.mem", long_chirp_lut);
108  end
109  
110  // Synchronous-only BRAM read (no async reset) for BRAM inference
111  always @(posedge clk_120m) begin
112      long_chirp_rd_data <= long_chirp_lut[sample_counter];
113  end
114  
115  // Short PLFM chirp LUT initialization (too small for BRAM, keep inline)
116  initial begin
117      // Complete Short PLFM chirp LUT (0.5us, 30MHz to 10MHz)
118      short_chirp_lut[ 0] = 8'd255; short_chirp_lut[ 1] = 8'd237; short_chirp_lut[ 2] = 8'd187; short_chirp_lut[ 3] = 8'd118; short_chirp_lut[ 4] = 8'd 49; short_chirp_lut[ 5] = 8'd  6; short_chirp_lut[ 6] = 8'd  7; short_chirp_lut[ 7] = 8'd 54; 
119      short_chirp_lut[ 8] = 8'd132; short_chirp_lut[ 9] = 8'd210; short_chirp_lut[10] = 8'd253; short_chirp_lut[11] = 8'd237; short_chirp_lut[12] = 8'd167; short_chirp_lut[13] = 8'd 75; short_chirp_lut[14] = 8'd 10; short_chirp_lut[15] = 8'd 10; 
120      short_chirp_lut[16] = 8'd 80; short_chirp_lut[17] = 8'd180; short_chirp_lut[18] = 8'd248; short_chirp_lut[19] = 8'd237; short_chirp_lut[20] = 8'd150; short_chirp_lut[21] = 8'd 45; short_chirp_lut[22] = 8'd  1; short_chirp_lut[23] = 8'd 54; 
121      short_chirp_lut[24] = 8'd167; short_chirp_lut[25] = 8'd249; short_chirp_lut[26] = 8'd228; short_chirp_lut[27] = 8'd118; short_chirp_lut[28] = 8'd 15; short_chirp_lut[29] = 8'd 18; short_chirp_lut[30] = 8'd127; short_chirp_lut[31] = 8'd238; 
122      short_chirp_lut[32] = 8'd235; short_chirp_lut[33] = 8'd118; short_chirp_lut[34] = 8'd 10; short_chirp_lut[35] = 8'd 34; short_chirp_lut[36] = 8'd167; short_chirp_lut[37] = 8'd254; short_chirp_lut[38] = 8'd187; short_chirp_lut[39] = 8'd 45; 
123      short_chirp_lut[40] = 8'd  8; short_chirp_lut[41] = 8'd129; short_chirp_lut[42] = 8'd248; short_chirp_lut[43] = 8'd201; short_chirp_lut[44] = 8'd 49; short_chirp_lut[45] = 8'd 10; short_chirp_lut[46] = 8'd145; short_chirp_lut[47] = 8'd254; 
124      short_chirp_lut[48] = 8'd167; short_chirp_lut[49] = 8'd 17; short_chirp_lut[50] = 8'd 46; short_chirp_lut[51] = 8'd210; short_chirp_lut[52] = 8'd235; short_chirp_lut[53] = 8'd 75; short_chirp_lut[54] = 8'd  7; short_chirp_lut[55] = 8'd155; 
125      short_chirp_lut[56] = 8'd253; short_chirp_lut[57] = 8'd118; short_chirp_lut[58] = 8'd  1; short_chirp_lut[59] = 8'd129; 
126  end
127  
128  // chirp_counter is driven solely by the clk_120m FSM always block (line ~683).
129  // Removed redundant clk_100m driver that caused multi-driven register
130  // (synthesis failure, simulation race condition).
131  // The FSM internally sequences through CHIRP_MAX chirps per beam position,
132  // so external new_chirp edge counting is unnecessary here.
133  
134  // Elevation counter
135  
136  always @(posedge clk_100m or negedge reset_n) begin
137      if (!reset_n) begin
138          elevation_counter <= 6'b1;
139      end else begin 
140  			if (elevation__toggling) begin  
141  						if (elevation_counter == ELEVATION_MAX) begin
142  							elevation_counter <= 6'b1;
143  						end else begin
144  							elevation_counter <= elevation_counter + 6'b1;
145  					  end
146      end
147  end
148  end
149  
150  
151  // Azimuth counter
152  
153  always @(posedge clk_100m or negedge reset_n) begin
154      if (!reset_n) begin
155          azimuth_counter <= 6'd1;
156      end else begin 
157  			if (azimuth__toggling) begin  
158  						if (azimuth_counter == AZIMUTH_MAX) begin
159  							azimuth_counter <= 6'd1;
160  						end else begin
161  							azimuth_counter <= azimuth_counter + 6'd1;
162  					  end
163      end
164  end
165  end
166  
167  // State register
168  always @(posedge clk_120m or negedge reset_n) begin
169      if (!reset_n) begin
170          current_state <= IDLE;
171      end else begin
172          current_state <= next_state;
173      end
174  end
175  
176  // Next state logic
177  always @(*) begin
178      case (current_state)
179          IDLE: begin
180              if (chirp__toggling && mixers_enable)
181                  next_state = LONG_CHIRP;
182              else
183                  next_state = IDLE;
184          end
185          
186          LONG_CHIRP: begin
187              if (sample_counter == T1_SAMPLES-1)
188                  next_state = LONG_LISTEN;
189              else
190                  next_state = LONG_CHIRP;
191          end
192          
193          LONG_LISTEN: begin
194              if (sample_counter == T1_RADAR_LISTENING-1) begin
195                  if (chirp_counter == (CHIRP_MAX/2)-1)
196                      next_state = GUARD_TIME;
197                  else
198                      next_state = LONG_CHIRP;
199              end else begin
200                  next_state = LONG_LISTEN;
201              end
202          end
203          
204          GUARD_TIME: begin
205              if (sample_counter == GUARD_SAMPLES-1)
206                  next_state = SHORT_CHIRP;
207              else
208                  next_state = GUARD_TIME;
209          end
210          
211          SHORT_CHIRP: begin
212              if (sample_counter == T2_SAMPLES-1)
213                  next_state = SHORT_LISTEN;
214              else
215                  next_state = SHORT_CHIRP;
216          end
217          
218          SHORT_LISTEN: begin
219              if (sample_counter == T2_RADAR_LISTENING-1) begin
220                  if (chirp_counter == CHIRP_MAX-1)
221                      next_state = DONE;
222                  else
223                      next_state = SHORT_CHIRP;
224              end else begin
225                  next_state = SHORT_LISTEN;
226              end
227          end
228          
229          DONE: begin
230              next_state = IDLE;
231          end
232          
233          default: begin
234              next_state = IDLE;
235          end
236      endcase
237  end
238  
239  always @(posedge clk_120m or negedge reset_n) begin
240      if (!reset_n) begin
241          sample_counter <= 0;
242          chirp_counter <= 0;
243          chirp_valid <= 0;
244          chirp_done <= 0;
245          chirp_data <= 8'd128;
246          rf_switch_ctrl <= 1'b0;
247          adar_tr_1 <= 1'b0;
248          adar_tr_2 <= 1'b0;
249          adar_tr_3 <= 1'b0;
250          adar_tr_4 <= 1'b0;
251      end else if (mixers_enable) begin
252          // Default outputs
253          chirp_valid <= 0;
254          chirp_done <= 0;
255          rf_switch_ctrl <= 0;
256          {adar_tr_1, adar_tr_2, adar_tr_3, adar_tr_4} <= 4'b0000;
257          
258          // Sample counter increment logic
259          if (current_state == LONG_CHIRP || current_state == LONG_LISTEN || 
260              current_state == GUARD_TIME || current_state == SHORT_CHIRP || 
261              current_state == SHORT_LISTEN) begin
262              if (sample_counter == get_max_counter(current_state) - 1) begin
263                  sample_counter <= 0;
264                  // Increment chirp counter at end of listen states
265                  if (current_state == LONG_LISTEN || current_state == SHORT_LISTEN) begin
266                      chirp_counter <= chirp_counter + 1;
267                  end
268              end else begin
269                  sample_counter <= sample_counter + 1;
270              end
271          end else begin
272              sample_counter <= 0;
273          end
274          
275          // State-specific outputs
276          case (current_state)
277              IDLE: begin
278                  chirp_data <= 8'd128;
279              end
280              
281              LONG_CHIRP: begin
282                  rf_switch_ctrl <= 1'b1;
283                  {adar_tr_1, adar_tr_2, adar_tr_3, adar_tr_4} <= 4'b1111;
284                  
285                  // CRITICAL FIX: Generate valid signal
286                  if (sample_counter < T1_SAMPLES) begin
287                      chirp_data <= long_chirp_rd_data;
288                      chirp_valid <= 1'b1;  // Valid during entire chirp
289                  end else begin
290                      chirp_data <= 8'd128;
291                  end
292              end
293              
294              LONG_LISTEN: begin
295                  chirp_data <= 8'd128;
296  				rf_switch_ctrl <= 1'b0;
297              end
298              
299              GUARD_TIME: begin
300                  chirp_data <= 8'd128;
301  				rf_switch_ctrl <= 1'b0;
302              end
303              
304              SHORT_CHIRP: begin
305                  rf_switch_ctrl <= 1'b1;
306                  {adar_tr_1, adar_tr_2, adar_tr_3, adar_tr_4} <= 4'b1111;
307                  
308                  // CRITICAL FIX: Generate valid signal for short chirp
309                  if (sample_counter < T2_SAMPLES) begin
310                      chirp_data <= short_chirp_lut[sample_counter];
311                      chirp_valid <= 1'b1;  // Valid during entire chirp
312                  end else begin
313                      chirp_data <= 8'd128;
314                  end
315              end
316              
317              SHORT_LISTEN: begin
318                  chirp_data <= 8'd128;
319  				rf_switch_ctrl <= 1'b0;
320              end
321              
322              DONE: begin
323                  chirp_done <= 1'b1;
324                  chirp_data <= 8'd128;
325              end
326              
327              default: begin
328                  chirp_data <= 8'd128;
329              end
330          endcase
331      end else begin
332          // Mixers disabled
333          chirp_data <= 8'd128;
334          chirp_valid <= 0;
335          chirp_done <= 0;
336          rf_switch_ctrl <= 0;
337          {adar_tr_1, adar_tr_2, adar_tr_3, adar_tr_4} <= 4'b0000;
338          sample_counter <= 0;
339      end
340  end
341  
342  // Helper function to get max counter for each state
343  function [15:0] get_max_counter;
344      input [2:0] state;
345      begin
346          case (state)
347              LONG_CHIRP:   get_max_counter = T1_SAMPLES;
348              LONG_LISTEN:  get_max_counter = T1_RADAR_LISTENING;
349              GUARD_TIME:   get_max_counter = GUARD_SAMPLES;
350              SHORT_CHIRP:  get_max_counter = T2_SAMPLES;
351              SHORT_LISTEN: get_max_counter = T2_RADAR_LISTENING;
352              default:      get_max_counter = 0;
353          endcase
354      end
355  endfunction
356  
357  endmodule