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