Widen ft601_be to [3:0] for 32-bit FT601 mode, fix NCO XSim TB
- Expand ft601_be from [1:0] to [3:0] across RTL, top-level, testbenches, and XDC (uncomment be[2:3] pin assignments B21/A21) - Fix NCO XSim testbench: correct reset check (0x7FFF not 0), add pipeline warmup and sample skip for DSP48E1 quadrature test - All local regression tests pass (39/39 USB, 10/10 integration, all co-sim)
This commit is contained in:
@@ -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 |
|
||||
|
||||
|
||||
@@ -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[*]}]
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user