ddc_400m.v
1 `timescale 1ns / 1ps 2 3 module ddc_400m_enhanced ( 4 input wire clk_400m, // 400MHz clock from ADC DCO 5 input wire clk_100m, // 100MHz system clock 6 input wire reset_n, 7 input wire mixers_enable, 8 input wire [7:0] adc_data, // ADC data at 400MHz 9 input wire adc_data_valid_i, // Valid at 400MHz 10 input wire adc_data_valid_q, 11 output wire signed [17:0] baseband_i, 12 output wire signed [17:0] baseband_q, 13 output wire baseband_valid_i, 14 output wire baseband_valid_q, 15 16 output wire [1:0] ddc_status, 17 // Enhanced interfaces 18 output wire [7:0] ddc_diagnostics, 19 output wire mixer_saturation, 20 output wire filter_overflow, 21 22 input wire [1:0] test_mode, 23 input wire [15:0] test_phase_inc, 24 input wire force_saturation, 25 input wire reset_monitors, 26 output wire [31:0] debug_sample_count, 27 output wire [17:0] debug_internal_i, 28 output wire [17:0] debug_internal_q 29 ); 30 31 // Parameters for numerical precision 32 parameter ADC_WIDTH = 8; 33 parameter NCO_WIDTH = 16; 34 parameter MIXER_WIDTH = 18; 35 parameter OUTPUT_WIDTH = 18; 36 37 // IF frequency parameters 38 parameter IF_FREQ = 120000000; 39 parameter FS = 400000000; 40 parameter PHASE_WIDTH = 32; 41 42 // Internal signals 43 wire signed [15:0] sin_out, cos_out; 44 wire nco_ready; 45 wire cic_valid; 46 wire fir_valid; 47 wire [17:0] cic_i_out, cic_q_out; 48 wire signed [17:0] fir_i_out, fir_q_out; 49 50 51 // Diagnostic registers 52 reg [2:0] saturation_count; 53 reg overflow_detected; 54 reg [7:0] error_counter; 55 56 // ============================================================================ 57 // 400 MHz Reset Synchronizer 58 // 59 // reset_n arrives from the 100 MHz domain (sys_reset_n from radar_system_top). 60 // Using it directly as an async reset in the 400 MHz domain causes the reset 61 // deassertion edge to violate timing: the 100 MHz flip-flop driving reset_n 62 // has its output fanning out to 1156 registers across the FPGA in the 400 MHz 63 // domain, requiring 18.243ns of routing (WNS = -18.081ns). 64 // 65 // Solution: 2-stage async-assert, sync-deassert reset synchronizer in the 66 // 400 MHz domain. Reset assertion is immediate (asynchronous — combinatorial 67 // path from reset_n to all 400 MHz registers). Reset deassertion is 68 // synchronized to clk_400m rising edge, preventing metastability. 69 // 70 // All 400 MHz submodules (NCO, CIC, mixers, LFSR) use reset_n_400m. 71 // All 100 MHz submodules (FIR, output stage) continue using reset_n directly 72 // (already synchronized to 100 MHz at radar_system_top level). 73 // ============================================================================ 74 (* ASYNC_REG = "TRUE" *) reg [1:0] reset_sync_400m; 75 (* max_fanout = 50 *) wire reset_n_400m = reset_sync_400m[1]; 76 77 // Active-high reset for DSP48E1 RST ports (avoids LUT1 inverter fan-out) 78 (* max_fanout = 50 *) reg reset_400m; 79 80 always @(posedge clk_400m or negedge reset_n) begin 81 if (!reset_n) begin 82 reset_sync_400m <= 2'b00; 83 reset_400m <= 1'b1; 84 end else begin 85 reset_sync_400m <= {reset_sync_400m[0], 1'b1}; 86 reset_400m <= ~reset_sync_400m[1]; 87 end 88 end 89 90 // CDC synchronization for control signals (2-stage synchronizers) 91 (* ASYNC_REG = "TRUE" *) reg [1:0] mixers_enable_sync_chain; 92 (* ASYNC_REG = "TRUE" *) reg [1:0] force_saturation_sync_chain; 93 wire mixers_enable_sync; 94 wire force_saturation_sync; 95 96 // Debug monitoring signals 97 reg [31:0] sample_counter; 98 wire signed [17:0] debug_mixed_i_trunc; 99 wire signed [17:0] debug_mixed_q_trunc; 100 101 // Real-time status monitoring 102 reg [7:0] signal_power_i, signal_power_q; 103 104 // Internal mixing signals 105 // DSP48E1 with AREG=1, BREG=1, MREG=1, PREG=1 handles all internal pipelining 106 // Latency: 4 cycles (1 for AREG/BREG, 1 for MREG, 1 for PREG, 1 for post-DSP retiming) 107 wire signed [MIXER_WIDTH-1:0] adc_signed_w; 108 reg signed [MIXER_WIDTH + NCO_WIDTH -1:0] mixed_i, mixed_q; 109 reg mixed_valid; 110 reg mixer_overflow_i, mixer_overflow_q; 111 // Pipeline valid tracking: 4-stage shift register (3 for DSP48E1 + 1 for post-DSP retiming) 112 reg [3:0] dsp_valid_pipe; 113 // Post-DSP retiming registers — breaks DSP48E1 CLK→P to fabric timing path 114 // This extra pipeline stage absorbs the 1.866ns DSP output prop delay + routing, 115 // ensuring WNS > 0 at 400 MHz regardless of placement seed 116 (* DONT_TOUCH = "TRUE" *) reg signed [MIXER_WIDTH+NCO_WIDTH-1:0] mult_i_retimed, mult_q_retimed; 117 118 // Output stage registers 119 reg signed [17:0] baseband_i_reg, baseband_q_reg; 120 reg baseband_valid_reg; 121 122 // ============================================================================ 123 // Phase Dithering Signals 124 // ============================================================================ 125 wire [7:0] phase_dither_bits; 126 reg [31:0] phase_inc_dithered; 127 128 129 130 // ============================================================================ 131 // Debug Signal Assignments 132 // ============================================================================ 133 assign debug_internal_i = mixed_i[25:8]; 134 assign debug_internal_q = mixed_q[25:8]; 135 assign debug_sample_count = sample_counter; 136 assign debug_mixed_i_trunc = mixed_i[25:8]; 137 assign debug_mixed_q_trunc = mixed_q[25:8]; 138 139 // ============================================================================ 140 // Clock Domain Crossing for Control Signals (2-stage synchronizers) 141 // ============================================================================ 142 assign mixers_enable_sync = mixers_enable_sync_chain[1]; 143 assign force_saturation_sync = force_saturation_sync_chain[1]; 144 145 always @(posedge clk_400m or negedge reset_n_400m) begin 146 if (!reset_n_400m) begin 147 mixers_enable_sync_chain <= 2'b00; 148 force_saturation_sync_chain <= 2'b00; 149 end else begin 150 mixers_enable_sync_chain <= {mixers_enable_sync_chain[0], mixers_enable}; 151 force_saturation_sync_chain <= {force_saturation_sync_chain[0], force_saturation}; 152 end 153 end 154 155 // ============================================================================ 156 // Sample Counter and Debug Monitoring 157 // ============================================================================ 158 always @(posedge clk_400m or negedge reset_n_400m) begin 159 if (!reset_n_400m || reset_monitors) begin 160 sample_counter <= 0; 161 error_counter <= 0; 162 end else if (adc_data_valid_i && adc_data_valid_q ) begin 163 sample_counter <= sample_counter + 1; 164 end 165 end 166 167 168 // ============================================================================ 169 // Enhanced Phase Dithering Instance 170 // ============================================================================ 171 lfsr_dither_enhanced #( 172 .DITHER_WIDTH(8) 173 ) phase_dither_gen ( 174 .clk(clk_400m), 175 .reset_n(reset_n_400m), 176 .enable(nco_ready), 177 .dither_out(phase_dither_bits) 178 ); 179 180 // ============================================================================ 181 // Phase Increment Calculation with Dithering 182 // ============================================================================ 183 // Calculate phase increment for 120MHz IF at 400MHz sampling 184 localparam PHASE_INC_120MHZ = 32'h4CCCCCCD; 185 186 // Apply dithering to reduce spurious tones (registered for 400 MHz timing) 187 always @(posedge clk_400m or negedge reset_n_400m) begin 188 if (!reset_n_400m) 189 phase_inc_dithered <= PHASE_INC_120MHZ; 190 else 191 phase_inc_dithered <= PHASE_INC_120MHZ + {24'b0, phase_dither_bits}; 192 end 193 194 // ============================================================================ 195 // Enhanced NCO with Diagnostics 196 // ============================================================================ 197 nco_400m_enhanced nco_core ( 198 .clk_400m(clk_400m), 199 .reset_n(reset_n_400m), 200 .frequency_tuning_word(phase_inc_dithered), 201 .phase_valid(mixers_enable), 202 .phase_offset(16'h0000), 203 .sin_out(sin_out), 204 .cos_out(cos_out), 205 .dds_ready(nco_ready) 206 ); 207 208 // ============================================================================ 209 // Enhanced Mixing Stage — DSP48E1 direct instantiation for 400 MHz timing 210 // 211 // Architecture: 212 // ADC data → sign-extend to 18b → DSP48E1 A-port (AREG=1 pipelines it) 213 // NCO cos/sin → sign-extend to 18b → DSP48E1 B-port (BREG=1 pipelines it) 214 // Multiply result captured by MREG=1, then output registered by PREG=1 215 // force_saturation override applied AFTER DSP48E1 output (not on input path) 216 // 217 // Latency: 3 clock cycles (AREG/BREG + MREG + PREG) 218 // PREG=1 absorbs DSP48E1 CLK→P delay internally, preventing fabric timing violations 219 // In simulation (Icarus), uses behavioral equivalent since DSP48E1 is Xilinx-only 220 // ============================================================================ 221 222 // Combinational ADC sign conversion (no register — DSP48E1 AREG handles it) 223 assign adc_signed_w = {1'b0, adc_data, {(MIXER_WIDTH-ADC_WIDTH-1){1'b0}}} - 224 {1'b0, {ADC_WIDTH{1'b1}}, {(MIXER_WIDTH-ADC_WIDTH-1){1'b0}}} / 2; 225 226 // Valid pipeline: 4-stage shift register (3 for DSP48E1 AREG+MREG+PREG + 1 for retiming) 227 always @(posedge clk_400m or negedge reset_n_400m) begin 228 if (!reset_n_400m) begin 229 dsp_valid_pipe <= 4'b0000; 230 end else begin 231 dsp_valid_pipe <= {dsp_valid_pipe[2:0], (nco_ready && adc_data_valid_i && adc_data_valid_q)}; 232 end 233 end 234 235 `ifdef SIMULATION 236 // ---- Behavioral model for Icarus Verilog simulation ---- 237 // Mimics DSP48E1 with AREG=1, BREG=1, MREG=1, PREG=1 (3-cycle latency) 238 reg signed [MIXER_WIDTH-1:0] adc_signed_reg; // Models AREG 239 reg signed [15:0] cos_pipe_reg, sin_pipe_reg; // Models BREG 240 reg signed [MIXER_WIDTH+NCO_WIDTH-1:0] mult_i_internal, mult_q_internal; // Models MREG 241 reg signed [MIXER_WIDTH+NCO_WIDTH-1:0] mult_i_reg, mult_q_reg; // Models PREG 242 243 // Stage 1: AREG/BREG equivalent 244 always @(posedge clk_400m or negedge reset_n_400m) begin 245 if (!reset_n_400m) begin 246 adc_signed_reg <= 0; 247 cos_pipe_reg <= 0; 248 sin_pipe_reg <= 0; 249 end else begin 250 adc_signed_reg <= adc_signed_w; 251 cos_pipe_reg <= cos_out; 252 sin_pipe_reg <= sin_out; 253 end 254 end 255 256 // Stage 2: MREG equivalent 257 always @(posedge clk_400m or negedge reset_n_400m) begin 258 if (!reset_n_400m) begin 259 mult_i_internal <= 0; 260 mult_q_internal <= 0; 261 end else begin 262 mult_i_internal <= $signed(adc_signed_reg) * $signed(cos_pipe_reg); 263 mult_q_internal <= $signed(adc_signed_reg) * $signed(sin_pipe_reg); 264 end 265 end 266 267 // Stage 3: PREG equivalent 268 always @(posedge clk_400m or negedge reset_n_400m) begin 269 if (!reset_n_400m) begin 270 mult_i_reg <= 0; 271 mult_q_reg <= 0; 272 end else begin 273 mult_i_reg <= mult_i_internal; 274 mult_q_reg <= mult_q_internal; 275 end 276 end 277 278 // Stage 4: Post-DSP retiming register (matches synthesis path) 279 always @(posedge clk_400m or negedge reset_n_400m) begin 280 if (!reset_n_400m) begin 281 mult_i_retimed <= 0; 282 mult_q_retimed <= 0; 283 end else begin 284 mult_i_retimed <= mult_i_reg; 285 mult_q_retimed <= mult_q_reg; 286 end 287 end 288 289 `else 290 // ---- Direct DSP48E1 instantiation for Vivado synthesis ---- 291 // This guarantees AREG/BREG/MREG are used, achieving timing closure at 400 MHz 292 wire [47:0] dsp_p_i, dsp_p_q; 293 294 // DSP48E1 for I-channel mixer (adc_signed * cos_out) 295 DSP48E1 #( 296 // Feature control attributes 297 .A_INPUT("DIRECT"), 298 .B_INPUT("DIRECT"), 299 .USE_DPORT("FALSE"), 300 .USE_MULT("MULTIPLY"), 301 .USE_SIMD("ONE48"), 302 // Pipeline register attributes — all enabled for max timing 303 .AREG(1), 304 .BREG(1), 305 .MREG(1), 306 .PREG(1), // P register enabled — absorbs CLK→P delay for timing closure 307 .ADREG(0), 308 .ACASCREG(1), 309 .BCASCREG(1), 310 .ALUMODEREG(0), 311 .CARRYINREG(0), 312 .CARRYINSELREG(0), 313 .CREG(0), 314 .DREG(0), 315 .INMODEREG(0), 316 .OPMODEREG(0), 317 // Pattern detector (unused) 318 .AUTORESET_PATDET("NO_RESET"), 319 .MASK(48'h3fffffffffff), 320 .PATTERN(48'h000000000000), 321 .SEL_MASK("MASK"), 322 .SEL_PATTERN("PATTERN"), 323 .USE_PATTERN_DETECT("NO_PATDET") 324 ) dsp_mixer_i ( 325 // Clock and reset 326 .CLK(clk_400m), 327 .RSTA(reset_400m), 328 .RSTB(reset_400m), 329 .RSTM(reset_400m), 330 .RSTP(reset_400m), 331 .RSTALLCARRYIN(1'b0), 332 .RSTALUMODE(1'b0), 333 .RSTCTRL(1'b0), 334 .RSTC(1'b0), 335 .RSTD(1'b0), 336 .RSTINMODE(1'b0), 337 // Clock enables 338 .CEA1(1'b0), // AREG=1 uses CEA2 339 .CEA2(1'b1), 340 .CEB1(1'b0), // BREG=1 uses CEB2 341 .CEB2(1'b1), 342 .CEM(1'b1), 343 .CEP(1'b1), // P register clock enable (PREG=1) 344 .CEAD(1'b0), 345 .CEALUMODE(1'b0), 346 .CECARRYIN(1'b0), 347 .CECTRL(1'b0), 348 .CEC(1'b0), 349 .CED(1'b0), 350 .CEINMODE(1'b0), 351 // Data ports 352 .A({{12{adc_signed_w[MIXER_WIDTH-1]}}, adc_signed_w}), // Sign-extend 18b to 30b 353 .B({{2{cos_out[15]}}, cos_out}), // Sign-extend 16b to 18b 354 .C(48'b0), 355 .D(25'b0), 356 .CARRYIN(1'b0), 357 // Control ports 358 .OPMODE(7'b0000101), // P = M (multiply only, no accumulate) 359 .ALUMODE(4'b0000), // Z + X + Y + CIN 360 .INMODE(5'b00000), // A2 * B2 (direct) 361 .CARRYINSEL(3'b000), 362 // Output ports 363 .P(dsp_p_i), 364 .PATTERNDETECT(), 365 .PATTERNBDETECT(), 366 .OVERFLOW(), 367 .UNDERFLOW(), 368 .CARRYOUT(), 369 // Cascade ports (unused) 370 .ACIN(30'b0), 371 .BCIN(18'b0), 372 .CARRYCASCIN(1'b0), 373 .MULTSIGNIN(1'b0), 374 .PCIN(48'b0), 375 .ACOUT(), 376 .BCOUT(), 377 .CARRYCASCOUT(), 378 .MULTSIGNOUT(), 379 .PCOUT() 380 ); 381 382 // DSP48E1 for Q-channel mixer (adc_signed * sin_out) 383 DSP48E1 #( 384 .A_INPUT("DIRECT"), 385 .B_INPUT("DIRECT"), 386 .USE_DPORT("FALSE"), 387 .USE_MULT("MULTIPLY"), 388 .USE_SIMD("ONE48"), 389 .AREG(1), 390 .BREG(1), 391 .MREG(1), 392 .PREG(1), 393 .ADREG(0), 394 .ACASCREG(1), 395 .BCASCREG(1), 396 .ALUMODEREG(0), 397 .CARRYINREG(0), 398 .CARRYINSELREG(0), 399 .CREG(0), 400 .DREG(0), 401 .INMODEREG(0), 402 .OPMODEREG(0), 403 .AUTORESET_PATDET("NO_RESET"), 404 .MASK(48'h3fffffffffff), 405 .PATTERN(48'h000000000000), 406 .SEL_MASK("MASK"), 407 .SEL_PATTERN("PATTERN"), 408 .USE_PATTERN_DETECT("NO_PATDET") 409 ) dsp_mixer_q ( 410 .CLK(clk_400m), 411 .RSTA(reset_400m), 412 .RSTB(reset_400m), 413 .RSTM(reset_400m), 414 .RSTP(reset_400m), 415 .RSTALLCARRYIN(1'b0), 416 .RSTALUMODE(1'b0), 417 .RSTCTRL(1'b0), 418 .RSTC(1'b0), 419 .RSTD(1'b0), 420 .RSTINMODE(1'b0), 421 .CEA1(1'b0), 422 .CEA2(1'b1), 423 .CEB1(1'b0), 424 .CEB2(1'b1), 425 .CEM(1'b1), 426 .CEP(1'b1), // P register clock enable (PREG=1) 427 .CEAD(1'b0), 428 .CEALUMODE(1'b0), 429 .CECARRYIN(1'b0), 430 .CECTRL(1'b0), 431 .CEC(1'b0), 432 .CED(1'b0), 433 .CEINMODE(1'b0), 434 .A({{12{adc_signed_w[MIXER_WIDTH-1]}}, adc_signed_w}), 435 .B({{2{sin_out[15]}}, sin_out}), 436 .C(48'b0), 437 .D(25'b0), 438 .CARRYIN(1'b0), 439 .OPMODE(7'b0000101), 440 .ALUMODE(4'b0000), 441 .INMODE(5'b00000), 442 .CARRYINSEL(3'b000), 443 .P(dsp_p_q), 444 .PATTERNDETECT(), 445 .PATTERNBDETECT(), 446 .OVERFLOW(), 447 .UNDERFLOW(), 448 .CARRYOUT(), 449 .ACIN(30'b0), 450 .BCIN(18'b0), 451 .CARRYCASCIN(1'b0), 452 .MULTSIGNIN(1'b0), 453 .PCIN(48'b0), 454 .ACOUT(), 455 .BCOUT(), 456 .CARRYCASCOUT(), 457 .MULTSIGNOUT(), 458 .PCOUT() 459 ); 460 461 // Extract the multiply result from DSP48E1 P output 462 // adc_signed is 18 bits, NCO is 16 bits → product is 34 bits (bits [33:0] of P) 463 wire signed [MIXER_WIDTH+NCO_WIDTH-1:0] mult_i_reg = dsp_p_i[MIXER_WIDTH+NCO_WIDTH-1:0]; 464 wire signed [MIXER_WIDTH+NCO_WIDTH-1:0] mult_q_reg = dsp_p_q[MIXER_WIDTH+NCO_WIDTH-1:0]; 465 466 // Stage 4: Post-DSP retiming register — breaks DSP48E1 CLK→P to fabric path 467 // Without this, the DSP output prop delay (1.866ns) + routing (0.515ns) exceeds 468 // the 2.500ns clock period at slow process corner 469 always @(posedge clk_400m or negedge reset_n_400m) begin 470 if (!reset_n_400m) begin 471 mult_i_retimed <= 0; 472 mult_q_retimed <= 0; 473 end else begin 474 mult_i_retimed <= mult_i_reg; 475 mult_q_retimed <= mult_q_reg; 476 end 477 end 478 479 `endif 480 481 // ============================================================================ 482 // Post-DSP48E1 output stage: force_saturation override + overflow detection 483 // force_saturation mux is intentionally AFTER the DSP48E1 output to avoid 484 // polluting the critical input path with extra logic 485 // ============================================================================ 486 always @(posedge clk_400m or negedge reset_n_400m) begin 487 if (!reset_n_400m) begin 488 mixed_i <= 0; 489 mixed_q <= 0; 490 mixed_valid <= 0; 491 mixer_overflow_i <= 0; 492 mixer_overflow_q <= 0; 493 saturation_count <= 0; 494 overflow_detected <= 0; 495 end else if (dsp_valid_pipe[3]) begin 496 // Force saturation for testing (applied after DSP output, not on input path) 497 if (force_saturation_sync) begin 498 mixed_i <= 34'h1FFFFFFFF; 499 mixed_q <= 34'h200000000; 500 mixer_overflow_i <= 1'b1; 501 mixer_overflow_q <= 1'b1; 502 end else begin 503 // Normal path: take retimed DSP48E1 multiply result 504 mixed_i <= mult_i_retimed; 505 mixed_q <= mult_q_retimed; 506 507 // Overflow detection on retimed multiply result 508 mixer_overflow_i <= (mult_i_retimed > (2**(MIXER_WIDTH+NCO_WIDTH-2)-1)) || 509 (mult_i_retimed < -(2**(MIXER_WIDTH+NCO_WIDTH-2))); 510 mixer_overflow_q <= (mult_q_retimed > (2**(MIXER_WIDTH+NCO_WIDTH-2)-1)) || 511 (mult_q_retimed < -(2**(MIXER_WIDTH+NCO_WIDTH-2))); 512 end 513 514 mixed_valid <= 1; 515 516 if (mixer_overflow_i || mixer_overflow_q) begin 517 saturation_count <= saturation_count + 1; 518 overflow_detected <= 1'b1; 519 end else begin 520 overflow_detected <= 1'b0; 521 end 522 523 end else begin 524 mixed_valid <= 0; 525 mixer_overflow_i <= 0; 526 mixer_overflow_q <= 0; 527 overflow_detected <= 1'b0; 528 end 529 end 530 531 // ============================================================================ 532 // Enhanced CIC Decimators 533 // ============================================================================ 534 wire cic_valid_i, cic_valid_q; 535 536 cic_decimator_4x_enhanced cic_i_inst ( 537 .clk(clk_400m), 538 .reset_n(reset_n_400m), 539 .data_in(mixed_i[33:16]), 540 .data_valid(mixed_valid), 541 .data_out(cic_i_out), 542 .data_out_valid(cic_valid_i) 543 ); 544 545 cic_decimator_4x_enhanced cic_q_inst ( 546 .clk(clk_400m), 547 .reset_n(reset_n_400m), 548 .data_in(mixed_q[33:16]), 549 .data_valid(mixed_valid), 550 .data_out(cic_q_out), 551 .data_out_valid(cic_valid_q) 552 ); 553 554 assign cic_valid = cic_valid_i & cic_valid_q; 555 556 // ============================================================================ 557 // Enhanced FIR Filters with FIXED valid signal handling 558 // NOTE: Wire declarations moved BEFORE CDC instances to fix forward-reference 559 // error in Icarus Verilog (was originally after CDC instantiation) 560 // ============================================================================ 561 wire fir_in_valid_i, fir_in_valid_q; 562 wire fir_valid_i, fir_valid_q; 563 wire fir_i_ready, fir_q_ready; 564 wire [17:0] fir_d_in_i, fir_d_in_q; 565 566 cdc_adc_to_processing #( 567 .WIDTH(18), 568 .STAGES(3) 569 )CDC_FIR_i( 570 .src_clk(clk_400m), 571 .dst_clk(clk_100m), 572 .src_reset_n(reset_n_400m), 573 .dst_reset_n(reset_n), 574 .src_data(cic_i_out), 575 .src_valid(cic_valid_i), 576 .dst_data(fir_d_in_i), 577 .dst_valid(fir_in_valid_i) 578 ); 579 580 cdc_adc_to_processing #( 581 .WIDTH(18), 582 .STAGES(3) 583 )CDC_FIR_q( 584 .src_clk(clk_400m), 585 .dst_clk(clk_100m), 586 .src_reset_n(reset_n_400m), 587 .dst_reset_n(reset_n), 588 .src_data(cic_q_out), 589 .src_valid(cic_valid_q), 590 .dst_data(fir_d_in_q), 591 .dst_valid(fir_in_valid_q) 592 ); 593 594 // ============================================================================ 595 // FIR Filter Instances 596 // ============================================================================ 597 598 // FIR I channel 599 fir_lowpass_parallel_enhanced fir_i_inst ( 600 .clk(clk_100m), 601 .reset_n(reset_n), 602 .data_in(fir_d_in_i), // Use synchronized data 603 .data_valid(fir_in_valid_i), // Use synchronized valid 604 .data_out(fir_i_out), 605 .data_out_valid(fir_valid_i), 606 .fir_ready(fir_i_ready), 607 .filter_overflow() 608 ); 609 610 // FIR Q channel 611 fir_lowpass_parallel_enhanced fir_q_inst ( 612 .clk(clk_100m), 613 .reset_n(reset_n), 614 .data_in(fir_d_in_q), // Use synchronized data 615 .data_valid(fir_in_valid_q), // Use synchronized valid 616 .data_out(fir_q_out), 617 .data_out_valid(fir_valid_q), 618 .fir_ready(fir_q_ready), 619 .filter_overflow() 620 ); 621 622 assign fir_valid = fir_valid_i & fir_valid_q; 623 624 // ============================================================================ 625 // Enhanced Output Stage 626 // ============================================================================ 627 always @(posedge clk_100m or negedge reset_n) begin 628 if (!reset_n) begin 629 baseband_i_reg <= 0; 630 baseband_q_reg <= 0; 631 baseband_valid_reg <= 0; 632 end else if (fir_valid) begin 633 baseband_i_reg <= fir_i_out; 634 baseband_q_reg <= fir_q_out; 635 baseband_valid_reg <= 1; 636 end else begin 637 baseband_valid_reg <= 0; 638 end 639 end 640 641 642 // ============================================================================ 643 // Output Assignments 644 // ============================================================================ 645 assign baseband_i = baseband_i_reg; 646 assign baseband_q = baseband_q_reg; 647 assign baseband_valid_i = baseband_valid_reg; 648 assign baseband_valid_q = baseband_valid_reg; 649 assign ddc_status = {mixer_overflow_i | mixer_overflow_q, nco_ready}; 650 assign mixer_saturation = overflow_detected; 651 assign ddc_diagnostics = {saturation_count, error_counter[4:0]}; 652 653 // ============================================================================ 654 // Enhanced Debug and Monitoring 655 // ============================================================================ 656 reg [31:0] debug_cic_count, debug_fir_count, debug_bb_count; 657 658 `ifdef SIMULATION 659 always @(posedge clk_100m) begin 660 661 if (fir_valid_i && debug_fir_count < 20) begin 662 debug_fir_count <= debug_fir_count + 1; 663 $display("FIR_OUTPUT: fir_i=%6d, fir_q=%6d", fir_i_out, fir_q_out); 664 end 665 666 if (adc_data_valid_i && adc_data_valid_q && debug_bb_count < 20) begin 667 debug_bb_count <= debug_bb_count + 1; 668 $display("BASEBAND_OUT: i=%6d, q=%6d, count=%0d", 669 baseband_i, baseband_q, debug_bb_count); 670 end 671 end 672 `endif 673 674 // In ddc_400m.v, add these debug signals: 675 676 // Debug monitoring (simulation only) 677 `ifdef SIMULATION 678 reg [31:0] debug_adc_count = 0; 679 reg [31:0] debug_baseband_count = 0; 680 681 always @(posedge clk_400m) begin 682 if (adc_data_valid_i && adc_data_valid_q && debug_adc_count < 10) begin 683 debug_adc_count <= debug_adc_count + 1; 684 $display("DDC_ADC: data=%0d, count=%0d, time=%t", 685 adc_data, debug_adc_count, $time); 686 end 687 end 688 689 always @(posedge clk_100m) begin 690 if (baseband_valid_i && baseband_valid_q && debug_baseband_count < 10) begin 691 debug_baseband_count <= debug_baseband_count + 1; 692 $display("DDC_BASEBAND: i=%0d, q=%0d, count=%0d, time=%t", 693 baseband_i, baseband_q, debug_baseband_count, $time); 694 end 695 end 696 `endif 697 698 699 endmodule 700 701 // ============================================================================ 702 // Enhanced Phase Dithering Module 703 // ============================================================================ 704 `timescale 1ns / 1ps 705 706 module lfsr_dither_enhanced #( 707 parameter DITHER_WIDTH = 8 // Increased for better dithering 708 )( 709 input wire clk, 710 input wire reset_n, 711 input wire enable, 712 output wire [DITHER_WIDTH-1:0] dither_out 713 ); 714 715 reg [DITHER_WIDTH-1:0] lfsr_reg; 716 reg [15:0] cycle_counter; 717 reg lock_detected; 718 719 // Polynomial for better randomness: x^8 + x^6 + x^5 + x^4 + 1 720 wire feedback; 721 722 generate 723 if (DITHER_WIDTH == 4) begin 724 assign feedback = lfsr_reg[3] ^ lfsr_reg[2]; 725 end else if (DITHER_WIDTH == 8) begin 726 assign feedback = lfsr_reg[7] ^ lfsr_reg[5] ^ lfsr_reg[4] ^ lfsr_reg[3]; 727 end else begin 728 assign feedback = lfsr_reg[DITHER_WIDTH-1] ^ lfsr_reg[DITHER_WIDTH-2]; 729 end 730 endgenerate 731 732 always @(posedge clk or negedge reset_n) begin 733 if (!reset_n) begin 734 lfsr_reg <= {DITHER_WIDTH{1'b1}}; // Non-zero initial state 735 cycle_counter <= 0; 736 lock_detected <= 0; 737 end else if (enable) begin 738 lfsr_reg <= {lfsr_reg[DITHER_WIDTH-2:0], feedback}; 739 cycle_counter <= cycle_counter + 1; 740 741 // Detect LFSR lock after sufficient cycles 742 if (cycle_counter > (2**DITHER_WIDTH * 8)) begin 743 lock_detected <= 1'b1; 744 end 745 end 746 end 747 748 assign dither_out = lfsr_reg; 749 750 endmodule