/ 9_Firmware / 9_2_FPGA / radar_transmitter.v
radar_transmitter.v
  1  `timescale 1ns / 1ps
  2  //////////////////////////////////////////////////////////////////////////////////
  3  // Company: 
  4  // Engineer: 
  5  // 
  6  // Create Date:    19:04:35 12/14/2025 
  7  // Design Name: 
  8  // Module Name:    radar_transmitter 
  9  // Project Name: 
 10  // Target Devices: 
 11  // Tool versions: 
 12  // Description: 
 13  //
 14  // Dependencies: 
 15  //
 16  // Revision: 
 17  // Revision 0.01 - File Created
 18  // Additional Comments: 
 19  //
 20  //////////////////////////////////////////////////////////////////////////////////
 21  module radar_transmitter(
 22      // System Clocks
 23      input wire clk_100m,           // System clock
 24      input wire clk_120m_dac,       // 120MHz DAC clock
 25      input wire reset_n,            // Reset synchronized to clk_120m_dac
 26      input wire reset_100m_n,       // Reset synchronized to clk_100m (for edge detectors/CDC)
 27      
 28      // DAC Interface
 29      output wire [7:0] dac_data,
 30      output wire dac_clk,
 31      output wire dac_sleep,
 32      output wire rx_mixer_en,
 33      output wire tx_mixer_en,
 34  	 
 35  	     // STM32 Control Interface
 36      input wire stm32_new_chirp,
 37      input wire stm32_new_elevation, 
 38      input wire stm32_new_azimuth,
 39      input wire stm32_mixers_enable,
 40  	 
 41  	 output wire fpga_rf_switch,
 42  	 
 43  	     // ADAR1000 Control Interface
 44      output wire adar_tx_load_1,
 45      output wire adar_rx_load_1,
 46      output wire adar_tx_load_2,
 47      output wire adar_rx_load_2,
 48      output wire adar_tx_load_3,
 49      output wire adar_rx_load_3,
 50      output wire adar_tx_load_4,
 51      output wire adar_rx_load_4,
 52      output wire adar_tr_1,
 53      output wire adar_tr_2,
 54      output wire adar_tr_3,
 55      output wire adar_tr_4,
 56      
 57      // Level Shifter SPI Interface (STM32F7 to ADAR1000)
 58      input wire stm32_sclk_3v3,
 59      input wire stm32_mosi_3v3,
 60      output wire stm32_miso_3v3,
 61      input wire stm32_cs_adar1_3v3,
 62      input wire stm32_cs_adar2_3v3,
 63      input wire stm32_cs_adar3_3v3,
 64      input wire stm32_cs_adar4_3v3,
 65      
 66      output wire stm32_sclk_1v8,
 67      output wire stm32_mosi_1v8,
 68      input wire stm32_miso_1v8,
 69      output wire stm32_cs_adar1_1v8,
 70      output wire stm32_cs_adar2_1v8,
 71      output wire stm32_cs_adar3_1v8,
 72      output wire stm32_cs_adar4_1v8,
 73  	 
 74  			 // Beam Position Tracking
 75  	 output wire [5:0] current_elevation,
 76  	 output wire [5:0] current_azimuth,
 77  	 output wire [5:0] current_chirp,
 78  	 output wire new_chirp_frame
 79  
 80  
 81      );
 82  	 
 83  // ========== SPI LEVEL SHIFTER PASSTHROUGH ==========
 84  // FPGA bridges 3.3V STM32 SPI bus (Bank 15) to 1.8V ADAR1000 SPI bus (Bank 34).
 85  // The FPGA I/O banks handle the actual voltage translation; these assigns
 86  // route the signals through the fabric.
 87  assign stm32_sclk_1v8      = stm32_sclk_3v3;
 88  assign stm32_mosi_1v8       = stm32_mosi_3v3;
 89  assign stm32_miso_3v3       = stm32_miso_1v8;
 90  assign stm32_cs_adar1_1v8   = stm32_cs_adar1_3v3;
 91  assign stm32_cs_adar2_1v8   = stm32_cs_adar2_3v3;
 92  assign stm32_cs_adar3_1v8   = stm32_cs_adar3_3v3;
 93  assign stm32_cs_adar4_1v8   = stm32_cs_adar4_3v3;
 94  
 95  // Edge Detection Signals
 96  wire new_chirp_pulse;
 97  wire new_elevation_pulse;
 98  wire new_azimuth_pulse;
 99  
100  // CDC: Synchronized versions of async STM32 GPIO inputs to clk_100m
101  wire stm32_new_chirp_sync;
102  wire stm32_new_elevation_sync;
103  wire stm32_new_azimuth_sync;
104  
105  // CDC: Synchronized versions of signals crossing clk_100m -> clk_120m_dac
106  wire mixers_enable_120m;   // stm32_mixers_enable sync'd to clk_120m_dac
107  wire new_chirp_pulse_120m; // new_chirp_pulse (toggle CDC) in clk_120m_dac domain
108  
109  // Chirp Control Signals
110  wire [7:0] chirp_data;
111  wire chirp_valid;
112  wire chirp_sequence_done;
113  
114  // Toggle CDC for new_chirp_pulse: clk_100m -> clk_120m_dac
115  // Edge detector produces a 1-cycle pulse on clk_100m. A level synchronizer
116  // would miss it (120/100 MHz ratio). Toggle CDC converts pulse to level toggle,
117  // syncs the toggle, then detects edges on the destination side.
118  reg chirp_toggle_100m;
119  always @(posedge clk_100m or negedge reset_100m_n) begin
120      if (!reset_100m_n)
121          chirp_toggle_100m <= 1'b0;
122      else if (new_chirp_pulse)
123          chirp_toggle_100m <= ~chirp_toggle_100m;
124  end
125  
126  // Sync the toggle to clk_120m_dac domain
127  wire chirp_toggle_120m;
128  cdc_single_bit #(.STAGES(3)) cdc_chirp_toggle (
129      .src_clk(clk_100m),
130      .dst_clk(clk_120m_dac),
131      .reset_n(reset_n),
132      .src_signal(chirp_toggle_100m),
133      .dst_signal(chirp_toggle_120m)
134  );
135  
136  // Detect edges on synchronized toggle to recover pulse in clk_120m domain
137  reg chirp_toggle_120m_prev;
138  always @(posedge clk_120m_dac or negedge reset_n) begin
139      if (!reset_n)
140          chirp_toggle_120m_prev <= 1'b0;
141      else
142          chirp_toggle_120m_prev <= chirp_toggle_120m;
143  end
144  assign new_chirp_pulse_120m = chirp_toggle_120m ^ chirp_toggle_120m_prev;
145  
146  // Sync stm32_mixers_enable (async GPIO level) to clk_120m_dac domain
147  cdc_single_bit #(.STAGES(3)) cdc_mixers_en_120m (
148      .src_clk(clk_100m),         // Treat as pseudo-source (GPIO is async)
149      .dst_clk(clk_120m_dac),
150      .reset_n(reset_n),
151      .src_signal(stm32_mixers_enable),
152      .dst_signal(mixers_enable_120m)
153  );
154  
155  // CDC synchronizers: async STM32 GPIO inputs -> clk_100m domain
156  // These prevent metastability in the edge detectors. Without these,
157  // the edge detector's first FF can go metastable, and the XOR output
158  // can glitch, producing false chirp/elevation/azimuth pulses.
159  cdc_single_bit #(.STAGES(2)) cdc_stm32_chirp (
160      .src_clk(clk_100m),         // Pseudo-source for async GPIO
161      .dst_clk(clk_100m),
162      .reset_n(reset_100m_n),
163      .src_signal(stm32_new_chirp),
164      .dst_signal(stm32_new_chirp_sync)
165  );
166  
167  cdc_single_bit #(.STAGES(2)) cdc_stm32_elevation (
168      .src_clk(clk_100m),
169      .dst_clk(clk_100m),
170      .reset_n(reset_100m_n),
171      .src_signal(stm32_new_elevation),
172      .dst_signal(stm32_new_elevation_sync)
173  );
174  
175  cdc_single_bit #(.STAGES(2)) cdc_stm32_azimuth (
176      .src_clk(clk_100m),
177      .dst_clk(clk_100m),
178      .reset_n(reset_100m_n),
179      .src_signal(stm32_new_azimuth),
180      .dst_signal(stm32_new_azimuth_sync)
181  );
182  
183  // Enhanced STM32 Input Edge Detection with Debouncing
184  // Inputs are now CDC-synchronized (safe from metastability)
185  edge_detector_enhanced chirp_edge (
186      .clk(clk_100m),
187      .reset_n(reset_100m_n),
188      .signal_in(stm32_new_chirp_sync),
189      .rising_falling_edge(new_chirp_pulse)            
190  );
191  
192  edge_detector_enhanced elevation_edge (
193      .clk(clk_100m),
194      .reset_n(reset_100m_n),
195      .signal_in(stm32_new_elevation_sync),
196      .rising_falling_edge(new_elevation_pulse)
197  );
198  
199  edge_detector_enhanced azimuth_edge (
200      .clk(clk_100m),
201      .reset_n(reset_100m_n),
202      .signal_in(stm32_new_azimuth_sync),
203      .rising_falling_edge(new_azimuth_pulse)
204  );
205  
206  // Enhanced PLFM Chirp Generation
207  plfm_chirp_controller_enhanced plfm_chirp_inst (
208      .clk_120m(clk_120m_dac),
209      .clk_100m(clk_100m),
210      .reset_n(reset_n),
211      .new_chirp(new_chirp_pulse_120m),      // CDC-synchronized pulse in clk_120m domain
212      .new_elevation(new_elevation_pulse),
213      .new_azimuth(new_azimuth_pulse),
214      .new_chirp_frame(new_chirp_frame),
215      .mixers_enable(mixers_enable_120m),    // CDC-synchronized level in clk_120m domain
216      .chirp_data(chirp_data),
217      .chirp_valid(chirp_valid),
218      .chirp_done(chirp_sequence_done),
219      .rf_switch_ctrl(fpga_rf_switch),
220      .rx_mixer_en(rx_mixer_en),
221      .tx_mixer_en(tx_mixer_en),
222      .adar_tx_load_1(adar_tx_load_1),
223      .adar_rx_load_1(adar_rx_load_1),
224      .adar_tx_load_2(adar_tx_load_2),
225      .adar_rx_load_2(adar_rx_load_2),
226      .adar_tx_load_3(adar_tx_load_3),
227      .adar_rx_load_3(adar_rx_load_3),
228      .adar_tx_load_4(adar_tx_load_4),
229      .adar_rx_load_4(adar_rx_load_4),
230      .adar_tr_1(adar_tr_1),
231      .adar_tr_2(adar_tr_2),
232      .adar_tr_3(adar_tr_3),
233      .adar_tr_4(adar_tr_4),
234      .elevation_counter(current_elevation),
235      .azimuth_counter(current_azimuth),
236      .chirp_counter(current_chirp)
237  );
238  
239  // Enhanced DAC Interface
240  dac_interface_enhanced dac_interface_inst (
241      .clk_120m(clk_120m_dac),
242      .reset_n(reset_n),
243      .chirp_data(chirp_data),
244      .chirp_valid(chirp_valid),
245      .dac_data(dac_data),
246      .dac_clk(dac_clk),
247      .dac_sleep(dac_sleep)
248  );
249  endmodule