diff --git a/9_Firmware/9_2_FPGA/constraints/README.md b/9_Firmware/9_2_FPGA/constraints/README.md index c5fd848..1b3ad33 100644 --- a/9_Firmware/9_2_FPGA/constraints/README.md +++ b/9_Firmware/9_2_FPGA/constraints/README.md @@ -43,7 +43,7 @@ own constraint file. Both files constrain the same RTL top module (`radar_system |--------|-------------------|---------------------| | FT601 USB | Unwired (chip placed, no nets) | Fully wired, Bank 16 | | `dac_clk` | Not connected (DAC clocked by AD9523 directly) | Routed, FPGA drives DAC | -| `ft601_be` width | `[1:0]` in RTL | `[3:0]` needed (RTL update required) | +| `ft601_be` width | `[1:0]` in upstream RTL | `[3:0]` (RTL updated) | | ADC LVDS standard | LVDS_33 (3.3V bank) | LVDS_25 (2.5V bank, better quality) | | Status/debug outputs | No physical pins (commented out) | All routed to Banks 35 + 13 | diff --git a/9_Firmware/9_2_FPGA/constraints/xc7a200t_fbg484.xdc b/9_Firmware/9_2_FPGA/constraints/xc7a200t_fbg484.xdc index ee70b24..2d4503b 100644 --- a/9_Firmware/9_2_FPGA/constraints/xc7a200t_fbg484.xdc +++ b/9_Firmware/9_2_FPGA/constraints/xc7a200t_fbg484.xdc @@ -35,7 +35,7 @@ # 1. ADC uses LVDS_25 (2.5V VCCO) instead of LVDS_33 (better signal quality) # 2. FT601 USB 3.0 is fully wired (Bank 16) — unwired on upstream board # 3. dac_clk output is routed — unconnected on upstream board -# 4. ft601_be is 4 bits wide for 32-bit FT601 mode (upstream RTL has [1:0]) +# 4. ft601_be is 4 bits wide [3:0] for 32-bit FT601 mode # 5. All status/debug outputs have physical pins (Banks 35 + 13) # ============================================================================ @@ -280,8 +280,6 @@ set_property IOSTANDARD LVCMOS18 [get_ports {stm32_*_1v8}] # FT601 is fully wired on the production board. # 32-bit data bus + 4-bit byte enable + control signals. # -# NOTE: Current RTL declares ft601_be[1:0]. Production board requires -# ft601_be[3:0] for 32-bit FT601 mode. RTL update needed. # --- ft601_clk_in on MRCC (D17) constrained above in CLOCK section --- @@ -330,14 +328,10 @@ set_property SLEW FAST [get_ports {ft601_data[*]}] set_property DRIVE 8 [get_ports {ft601_data[*]}] # FT601 Byte Enable [3:0] -# NOTE: RTL currently only drives ft601_be[1:0]. Bits [3:2] are allocated -# for future 32-bit mode but have no driver yet. Constrain only [1:0] -# to avoid critical warnings; add [3:2] when RTL is updated. set_property PACKAGE_PIN C22 [get_ports {ft601_be[0]}] set_property PACKAGE_PIN B22 [get_ports {ft601_be[1]}] -# Reserved for future 4-bit byte enable (uncomment when RTL supports [3:0]): -# set_property PACKAGE_PIN B21 [get_ports {ft601_be[2]}] -# set_property PACKAGE_PIN A21 [get_ports {ft601_be[3]}] +set_property PACKAGE_PIN B21 [get_ports {ft601_be[2]}] +set_property PACKAGE_PIN A21 [get_ports {ft601_be[3]}] set_property IOSTANDARD LVCMOS33 [get_ports {ft601_be[*]}] set_property SLEW FAST [get_ports {ft601_be[*]}] set_property DRIVE 8 [get_ports {ft601_be[*]}] diff --git a/9_Firmware/9_2_FPGA/radar_system_tb.v b/9_Firmware/9_2_FPGA/radar_system_tb.v index 1572048..c08eaaf 100644 --- a/9_Firmware/9_2_FPGA/radar_system_tb.v +++ b/9_Firmware/9_2_FPGA/radar_system_tb.v @@ -52,7 +52,7 @@ reg [7:0] adc_d_n; // FT601 interface wire [31:0] ft601_data; -wire [1:0] ft601_be; +wire [3:0] ft601_be; wire ft601_txe_n; wire ft601_rxf_n; reg ft601_txe; diff --git a/9_Firmware/9_2_FPGA/radar_system_top.v b/9_Firmware/9_2_FPGA/radar_system_top.v index 6f9c731..8583c1c 100644 --- a/9_Firmware/9_2_FPGA/radar_system_top.v +++ b/9_Firmware/9_2_FPGA/radar_system_top.v @@ -77,7 +77,7 @@ module radar_system_top ( // Data bus inout wire [31:0] ft601_data, // 32-bit bidirectional data bus - output wire [1:0] ft601_be, // Byte enable + output wire [3:0] ft601_be, // Byte enable (4 lanes for 32-bit mode) // Control signals output wire ft601_txe_n, // Transmit enable (active low) diff --git a/9_Firmware/9_2_FPGA/tb/tb_nco_xsim.v b/9_Firmware/9_2_FPGA/tb/tb_nco_xsim.v index 97049f3..a92bbb5 100644 --- a/9_Firmware/9_2_FPGA/tb/tb_nco_xsim.v +++ b/9_Firmware/9_2_FPGA/tb/tb_nco_xsim.v @@ -86,8 +86,8 @@ module tb_nco_xsim; // ════════════════════════════════════════════════════════ $display("--- Test Group 1: Reset Behaviour ---"); #50; - check(cos_out === 16'sd0 || cos_out === 16'sd1, - "cos_out near zero during reset"); + check(cos_out === 16'sh7FFF, + "cos_out = 0x7FFF during reset"); check(output_valid === 1'b0, "output_valid = 0 during reset"); // ════════════════════════════════════════════════════════ @@ -184,26 +184,34 @@ module tb_nco_xsim; #50; phase_increment = 32'h4CCCCCCD; reset_n = 1; - repeat (15) @(posedge clk); + // Allow 25 cycles for pipeline flush (DSP48E1 has 6–7 stage latency) + repeat (25) @(posedge clk); begin : quad_test reg [63:0] mag_sq; reg [63:0] mag_min, mag_max; integer sample_count; + integer skip; mag_min = 64'hFFFFFFFFFFFFFFFF; mag_max = 0; sample_count = 0; + skip = 0; for (i = 0; i < 200; i = i + 1) begin @(posedge clk); #0.1; if (output_valid) begin - // cos^2 + sin^2 - mag_sq = cos_out * cos_out + sin_out * sin_out; - if (mag_sq > 0) begin // skip zeros during pipeline fill - if (mag_sq < mag_min) mag_min = mag_sq; - if (mag_sq > mag_max) mag_max = mag_sq; - sample_count = sample_count + 1; + // Skip first 4 valid samples (pipeline settling) + if (skip < 4) begin + skip = skip + 1; + end else begin + // cos^2 + sin^2 + mag_sq = cos_out * cos_out + sin_out * sin_out; + if (mag_sq > 0) begin // skip zeros during pipeline fill + if (mag_sq < mag_min) mag_min = mag_sq; + if (mag_sq > mag_max) mag_max = mag_sq; + sample_count = sample_count + 1; + end end end end diff --git a/9_Firmware/9_2_FPGA/tb/tb_usb_data_interface.v b/9_Firmware/9_2_FPGA/tb/tb_usb_data_interface.v index a8a7dee..a516c55 100644 --- a/9_Firmware/9_2_FPGA/tb/tb_usb_data_interface.v +++ b/9_Firmware/9_2_FPGA/tb/tb_usb_data_interface.v @@ -30,7 +30,7 @@ module tb_usb_data_interface; // FT601 interface wire [31:0] ft601_data; - wire [1:0] ft601_be; + wire [3:0] ft601_be; wire ft601_txe_n; wire ft601_rxf_n; reg ft601_txe; @@ -271,8 +271,8 @@ module tb_usb_data_interface; check(ft601_wr_n === 1'b0, "Write strobe active during range data"); - check(ft601_be === 2'b11, - "Byte enable=11 for range data"); + check(ft601_be === 4'b1111, + "Byte enable=1111 for range data"); // Wait for all 4 range words to complete wait_for_state(S_SEND_DOPPLER, 50); @@ -307,8 +307,8 @@ module tb_usb_data_interface; check(uut.ft601_data_out[7:0] === 8'hAA, "Header byte 0xAA on data bus"); - check(ft601_be === 2'b01, - "Byte enable=01 for header (lower byte only)"); + check(ft601_be === 4'b0001, + "Byte enable=0001 for header (lower byte only)"); check(ft601_wr_n === 1'b0, "Write strobe active during header"); check(uut.ft601_data_oe === 1'b1, diff --git a/9_Firmware/9_2_FPGA/usb_data_interface.v b/9_Firmware/9_2_FPGA/usb_data_interface.v index 1382cc0..a12044c 100644 --- a/9_Firmware/9_2_FPGA/usb_data_interface.v +++ b/9_Firmware/9_2_FPGA/usb_data_interface.v @@ -14,7 +14,7 @@ module usb_data_interface ( // FT601 Interface (Slave FIFO mode) // Data bus inout wire [31:0] ft601_data, // 32-bit bidirectional data bus - output reg [1:0] ft601_be, // Byte enable (for 32-bit mode) + output reg [3:0] ft601_be, // Byte enable (4 lanes for 32-bit mode) // Control signals output reg ft601_txe_n, // Transmit enable (active low) @@ -118,7 +118,7 @@ always @(posedge ft601_clk_in or negedge reset_n) begin byte_counter <= 0; ft601_data_out <= 0; ft601_data_oe <= 0; - ft601_be <= 2'b11; // Both bytes enabled for 32-bit mode + ft601_be <= 4'b1111; // All bytes enabled for 32-bit mode ft601_txe_n <= 1; ft601_rxf_n <= 1; ft601_wr_n <= 1; @@ -142,7 +142,7 @@ always @(posedge ft601_clk_in or negedge reset_n) begin if (!ft601_txe) begin // FT601 TX FIFO not empty ft601_data_oe <= 1; ft601_data_out <= {24'b0, HEADER}; - ft601_be <= 2'b01; // Only lower byte valid + ft601_be <= 4'b0001; // Only lower byte valid ft601_wr_n <= 0; // Assert write strobe current_state <= SEND_RANGE_DATA; end @@ -151,7 +151,7 @@ always @(posedge ft601_clk_in or negedge reset_n) begin SEND_RANGE_DATA: begin if (!ft601_txe) begin ft601_data_oe <= 1; - ft601_be <= 2'b11; // All bytes valid for 32-bit word + ft601_be <= 4'b1111; // All bytes valid for 32-bit word case (byte_counter) 0: ft601_data_out <= range_profile_cap; @@ -174,7 +174,7 @@ always @(posedge ft601_clk_in or negedge reset_n) begin SEND_DOPPLER_DATA: begin if (!ft601_txe && doppler_valid_ft) begin ft601_data_oe <= 1; - ft601_be <= 2'b11; + ft601_be <= 4'b1111; case (byte_counter) 0: ft601_data_out <= {doppler_real_cap, doppler_imag_cap}; @@ -197,7 +197,7 @@ always @(posedge ft601_clk_in or negedge reset_n) begin SEND_DETECTION_DATA: begin if (!ft601_txe && cfar_valid_ft) begin ft601_data_oe <= 1; - ft601_be <= 2'b01; + ft601_be <= 4'b0001; ft601_data_out <= {24'b0, 7'b0, cfar_detection_cap}; ft601_wr_n <= 0; current_state <= SEND_FOOTER; @@ -207,7 +207,7 @@ always @(posedge ft601_clk_in or negedge reset_n) begin SEND_FOOTER: begin if (!ft601_txe) begin ft601_data_oe <= 1; - ft601_be <= 2'b01; + ft601_be <= 4'b0001; ft601_data_out <= {24'b0, FOOTER}; ft601_wr_n <= 0; current_state <= WAIT_ACK;