mirror of
https://github.com/NawfalMotii79/PLFM_RADAR.git
synced 2026-06-13 17:01:17 +00:00
feat(fpga,gui): PR-AC.1 — M-5 status pkt 30→34 B for medium_chirp/medium_listen readback
Closes the 161-µs MEDIUM PRI visibility gap from the 2026-05-02 e2e audit.
PR-G ran out of reserved bits in status_words[3] to fit a second 16-bit
pair, so this PR adds status_words[7] = {medium_chirp[15:0], medium_listen[15:0]}
and bumps STATUS_PKT_LEN 30→34, STATUS_PACKET_SIZE 30→34.
RTL (usb_data_interface_ft2232h.v):
- Two new input ports `status_medium_chirp` / `status_medium_listen`.
- status_words array bound 6→7, init loop 7→8, snapshot block packs word 7.
- STATUS_PKT_LEN width 5→6 bits to hold 34, byte-mux index widened
[4:0]→[5:0] with 4 new entries for word 7 + footer at index 33.
- Header docstring + length-localparam comment refreshed.
Top-level (radar_system_top.v): wire `host_medium_chirp_cycles` /
`host_medium_listen_cycles` into the FT2232H usb_inst (gen_ft2232h branch
only; legacy FT601 path retains its pre-PR-G 6-word / 26-byte layout —
no host code reads it today).
Host parser (radar_protocol.py):
- STATUS_PACKET_SIZE 30→34. Module docstring + parse_status_packet
docstring + find_bulk_frame_boundaries note refreshed.
- StatusResponse gains `medium_chirp` / `medium_listen` fields.
- Word-loop bounds 7→8; word-7 decode added.
Tests:
- tb_usb_protocol_v2 — drive default RP_DEF_MEDIUM_*_CYCLES (500/15600),
move T3.2 footer assertion 29→33, add T3.8..T3.11 for word-7 bytes.
Manual run: 31/31 PASS (TB not in run_regression.sh).
- tb_ft2232h_frame_drop, tb_e2e_dsp_to_host — tie new DUT ports to
16'd0 (these TBs don't exercise status reads).
- test_GUI_V65_Tk — extend _make_status_packet builder kwargs, rename
test_status_packet_is_30_bytes → _is_34_bytes, add round-trip +
16-bit-max tests for word 7.
- test_v7 — TestStatusPacketV2RoundTrip rewired for 8 words / 34 B,
add test_word7_medium_pri_decoded + test_pre_M5_30byte_packet_rejected.
Verification:
- FPGA regression (iverilog + xsim cosim): 42/0/0.
- tb_usb_protocol_v2 standalone: 31/0.
- Host test_GUI_V65_Tk: 119/119.
- Host test_v7: 152/152.
This commit is contained in:
@@ -1002,6 +1002,9 @@ end else begin : gen_ft2232h
|
||||
.status_guard(host_guard_cycles),
|
||||
.status_short_chirp(host_short_chirp_cycles),
|
||||
.status_short_listen(host_short_listen_cycles),
|
||||
// M-5: MEDIUM PRI readback in status_words[7]
|
||||
.status_medium_chirp(host_medium_chirp_cycles),
|
||||
.status_medium_listen(host_medium_listen_cycles),
|
||||
.status_chirps_per_elev(host_chirps_per_elev),
|
||||
.status_range_mode(host_range_mode),
|
||||
.status_chirps_mismatch(chirps_mismatch_error),
|
||||
|
||||
@@ -347,6 +347,10 @@ module tb_e2e_dsp_to_host;
|
||||
.status_guard (16'd0),
|
||||
.status_short_chirp (16'd0),
|
||||
.status_short_listen (16'd0),
|
||||
// M-5: medium PRI readback ports (A6 doesn't exercise status reads;
|
||||
// tied off to keep DUT-port arity in sync).
|
||||
.status_medium_chirp (16'd0),
|
||||
.status_medium_listen (16'd0),
|
||||
.status_chirps_per_elev (6'd0),
|
||||
.status_range_mode (2'd0),
|
||||
.status_chirps_mismatch (1'b0),
|
||||
|
||||
@@ -137,6 +137,10 @@ module tb_ft2232h_frame_drop;
|
||||
.status_guard(status_guard),
|
||||
.status_short_chirp(status_short_chirp),
|
||||
.status_short_listen(status_short_listen),
|
||||
// M-5: medium PRI readback (test only exercises frame_drop path,
|
||||
// medium values left at defaults since this TB doesn't read status).
|
||||
.status_medium_chirp(16'd0),
|
||||
.status_medium_listen(16'd0),
|
||||
.status_chirps_per_elev(status_chirps_per_elev),
|
||||
.status_range_mode(status_range_mode),
|
||||
.status_chirps_mismatch(status_chirps_mismatch),
|
||||
|
||||
@@ -9,8 +9,9 @@
|
||||
// reaches the cmd_* outputs of the read FSM with the right byte order.
|
||||
// 2. Bulk frame header v2 — verify byte0=0xAA, byte1=0x02 (version),
|
||||
// byte2=stream flags, bytes3-8=frame_num/range/doppler counts.
|
||||
// 3. Status packet length — verify 30 bytes (was 26 in v1) and that
|
||||
// status_words[6] carries detect_count_cand/detect_threshold_soft.
|
||||
// 3. Status packet length — verify 34 bytes (M-5; was 30 / PR-G; 26 / v1).
|
||||
// status_words[6] carries detect_count_cand/detect_threshold_soft (PR-G).
|
||||
// status_words[7] carries medium_chirp/medium_listen (M-5).
|
||||
// 4. PR-G FSM trim — full-frame header/body length consistency. With all
|
||||
// streams enabled, total emitted bytes must equal 9 (hdr) + range×2 +
|
||||
// range×doppler×2 (doppler) + range×doppler×2/8 (detect) + 1 (footer).
|
||||
@@ -78,6 +79,10 @@ module tb_usb_protocol_v2;
|
||||
reg [15:0] status_guard = 16'd0;
|
||||
reg [15:0] status_short_chirp = 16'd0;
|
||||
reg [15:0] status_short_listen = 16'd0;
|
||||
// M-5: status_words[7] medium PRI readback (test default = production
|
||||
// RP_DEF_MEDIUM_*_CYCLES so the round-trip canary is the real boot value)
|
||||
reg [15:0] status_medium_chirp = 16'd`RP_DEF_MEDIUM_CHIRP_CYCLES;
|
||||
reg [15:0] status_medium_listen = 16'd`RP_DEF_MEDIUM_LISTEN_CYCLES;
|
||||
reg [5:0] status_chirps_per_elev = 6'd0;
|
||||
reg [1:0] status_range_mode = 2'd0;
|
||||
reg status_chirps_mismatch = 1'b0;
|
||||
@@ -141,6 +146,9 @@ module tb_usb_protocol_v2;
|
||||
.status_guard(status_guard),
|
||||
.status_short_chirp(status_short_chirp),
|
||||
.status_short_listen(status_short_listen),
|
||||
// M-5: medium PRI readback feeding status_words[7]
|
||||
.status_medium_chirp(status_medium_chirp),
|
||||
.status_medium_listen(status_medium_listen),
|
||||
.status_chirps_per_elev(status_chirps_per_elev),
|
||||
.status_range_mode(status_range_mode),
|
||||
.status_chirps_mismatch(status_chirps_mismatch),
|
||||
@@ -271,9 +279,11 @@ module tb_usb_protocol_v2;
|
||||
check_b("T2.8: byte9 = footer 0x55", egress_bytes[9] == 8'h55);
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// TEST 3: Status packet length = 30 bytes; word[6] carries telemetry
|
||||
// TEST 3: Status packet length = 34 bytes (M-5);
|
||||
// word[6] carries 2-tier CFAR telemetry (PR-G);
|
||||
// word[7] carries medium_chirp/medium_listen (M-5).
|
||||
// -------------------------------------------------------------
|
||||
$display("\n[TEST 3] Status packet length 30B + word[6] PR-G fields");
|
||||
$display("\n[TEST 3] Status packet length 34B + word[6]/word[7] fields");
|
||||
egress_count = 0;
|
||||
@(posedge clk);
|
||||
status_request = 1'b1;
|
||||
@@ -281,7 +291,8 @@ module tb_usb_protocol_v2;
|
||||
status_request = 1'b0;
|
||||
wait_clk(300); // Wait for status drain
|
||||
check_b("T3.1: byte0 = 0xBB (status header)", egress_bytes[0] == 8'hBB);
|
||||
check_b("T3.2: byte29 = 0x55 (footer)", egress_bytes[29] == 8'h55);
|
||||
// M-5: footer moved 29→33 with the 4-byte word[7] insertion.
|
||||
check_b("T3.2: byte33 = 0x55 (footer)", egress_bytes[33] == 8'h55);
|
||||
check_b("T3.3: status_words[6] count_cand[15:8]=0", egress_bytes[25] == 8'h00);
|
||||
check_b("T3.4: status_words[6] count_cand[7:0]=42", egress_bytes[26] == 8'd42);
|
||||
check_b("T3.5: status_words[6] thr_soft[15:8]=0x0A", egress_bytes[27] == 8'h0A);
|
||||
@@ -294,6 +305,12 @@ module tb_usb_protocol_v2;
|
||||
// word[4][7:0] = {alpha_soft[7:0], range_mode[1:0]} = {8'h18, 2'b00} = 8'h60
|
||||
check_b("T3.7: status_words[4][7:0] = alpha_soft<<2 = 0x60 (alpha=0x18)",
|
||||
egress_bytes[20] == 8'h60);
|
||||
// M-5: status_words[7] = {medium_chirp, medium_listen}.
|
||||
// Defaults from RP_DEF_*: 500 (0x01F4) chirp / 15600 (0x3CF0) listen.
|
||||
check_b("T3.8: status_words[7] medium_chirp[15:8]=0x01", egress_bytes[29] == 8'h01);
|
||||
check_b("T3.9: status_words[7] medium_chirp[7:0]=0xF4", egress_bytes[30] == 8'hF4);
|
||||
check_b("T3.10: status_words[7] medium_listen[15:8]=0x3C", egress_bytes[31] == 8'h3C);
|
||||
check_b("T3.11: status_words[7] medium_listen[7:0]=0xF0", egress_bytes[32] == 8'hF0);
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// TEST 4: full-frame header/body length consistency (PR-G trim)
|
||||
|
||||
@@ -44,11 +44,12 @@
|
||||
*
|
||||
* Last byte: 0x55 (frame end footer)
|
||||
*
|
||||
* Status packet (FPGA→Host): 30 bytes (PR-G: was 26 in v1, +4 for soft tier)
|
||||
* Status packet (FPGA→Host): 34 bytes (M-5: was 30 / PR-G; was 26 / v1)
|
||||
* Byte 0: 0xBB (status header)
|
||||
* Bytes 1-28: 7 × 32-bit status words, MSB first
|
||||
* word[6] = {detect_count_cand[15:0], detect_threshold_soft[15:0]}
|
||||
* Byte 29: 0x55 (footer)
|
||||
* Bytes 1-32: 8 × 32-bit status words, MSB first
|
||||
* word[6] = {detect_count_cand[15:0], detect_threshold_soft[15:0]} (PR-G)
|
||||
* word[7] = {medium_chirp[15:0], medium_listen[15:0]} (M-5)
|
||||
* Byte 33: 0x55 (footer)
|
||||
*
|
||||
* Command (Host→FPGA): 4 bytes received sequentially (unchanged)
|
||||
* Byte 0: opcode[7:0] (see RP_OP_* in radar_params.vh)
|
||||
@@ -148,6 +149,8 @@ module usb_data_interface_ft2232h (
|
||||
input wire [15:0] status_guard,
|
||||
input wire [15:0] status_short_chirp,
|
||||
input wire [15:0] status_short_listen,
|
||||
input wire [15:0] status_medium_chirp, // M-5: status_words[7][31:16] readback
|
||||
input wire [15:0] status_medium_listen, // M-5: status_words[7][15:0] readback
|
||||
input wire [5:0] status_chirps_per_elev,
|
||||
input wire [1:0] status_range_mode,
|
||||
input wire status_chirps_mismatch, // TX-G: host requested chirps != Doppler FFT size
|
||||
@@ -225,8 +228,9 @@ localparam VALID_DET_BYTES_PER_RANGE = (NUM_DOPPLER_BINS * DETECT_BITS_PER_CELL
|
||||
localparam DETECT_SECTION_BYTES = NUM_RANGE_BINS * VALID_DET_BYTES_PER_RANGE; // 6144
|
||||
localparam [3:0] DET_BYTE_LAST_PER_RANGE = VALID_DET_BYTES_PER_RANGE[3:0] - 4'd1; // 11
|
||||
|
||||
// Status packet: 30 bytes (PR-G: 7 × 32-bit words + header + footer)
|
||||
localparam STATUS_PKT_LEN = 5'd30;
|
||||
// Status packet: 34 bytes (M-5: 8 × 32-bit words + header + footer; PR-G was 7 words / 30 B).
|
||||
// Width bumped 5→6 bits because 34 doesn't fit in 5 bits.
|
||||
localparam STATUS_PKT_LEN = 6'd34;
|
||||
|
||||
// ============================================================================
|
||||
// WRITE FSM STATES (FPGA → Host, ft_clk domain)
|
||||
@@ -698,8 +702,8 @@ always @(posedge clk or negedge reset_n) begin
|
||||
end
|
||||
end
|
||||
|
||||
// --- Status snapshot (ft_clk domain) — PR-G: 7 words (was 6) ---
|
||||
reg [31:0] status_words [0:6];
|
||||
// --- Status snapshot (ft_clk domain) — M-5: 8 words (was 7 / PR-G; was 6 / pre-PR-G) ---
|
||||
reg [31:0] status_words [0:7];
|
||||
|
||||
// Byte counter for write FSM (needs to be wide enough for largest section)
|
||||
reg [15:0] wr_byte_idx;
|
||||
@@ -806,7 +810,7 @@ always @(posedge ft_clk or negedge ft_effective_reset_n) begin
|
||||
det_thr_soft_sync_1 <= 17'd0;
|
||||
det_count_cand_sync_0 <= 16'd0;
|
||||
det_count_cand_sync_1 <= 16'd0;
|
||||
for (si = 0; si < 7; si = si + 1)
|
||||
for (si = 0; si < 8; si = si + 1)
|
||||
status_words[si] <= 32'd0;
|
||||
wr_state <= WR_IDLE;
|
||||
wr_byte_idx <= 16'd0;
|
||||
@@ -904,6 +908,17 @@ always @(posedge ft_clk or negedge ft_effective_reset_n) begin
|
||||
status_words[6] <= {det_count_cand_sync_1,
|
||||
(det_thr_soft_sync_1[16] ? 16'hFFFF
|
||||
: det_thr_soft_sync_1[15:0])};
|
||||
// M-5 word 7: {medium_chirp[15:0], medium_listen[15:0]}.
|
||||
// Host writes via 0x17/0x18; this readback closes the GUI's
|
||||
// 161-µs MEDIUM PRI visibility gap that PR-G left when status word
|
||||
// 3 ran out of reserved bits to fit a second 16-bit pair.
|
||||
// CDC-wise this follows the same convention as long_chirp /
|
||||
// long_listen / short_chirp / short_listen above (status_words[1..3]):
|
||||
// direct sample of the clk-domain register on the ft_clk-domain
|
||||
// status_req_ft strobe, accepting the same quasi-static-write
|
||||
// assumption (host writes cycles once during init, no concurrent
|
||||
// change during a status read).
|
||||
status_words[7] <= {status_medium_chirp, status_medium_listen};
|
||||
end
|
||||
|
||||
// ================================================================
|
||||
@@ -1199,47 +1214,51 @@ always @(posedge ft_clk or negedge ft_effective_reset_n) begin
|
||||
end
|
||||
end
|
||||
|
||||
// ---- Status packet: 30 bytes (PR-G v2: 7 × 32-bit words) ----
|
||||
// ---- Status packet: 34 bytes (M-5: 8 × 32-bit words) ----
|
||||
WR_STATUS_SEND: begin
|
||||
if (!ft_txe_n) begin
|
||||
ft_data_oe <= 1'b1;
|
||||
ft_wr_n <= 1'b0;
|
||||
|
||||
case (wr_byte_idx[4:0])
|
||||
5'd0: ft_data_out <= STATUS_HEADER;
|
||||
5'd1: ft_data_out <= status_words[0][31:24];
|
||||
5'd2: ft_data_out <= status_words[0][23:16];
|
||||
5'd3: ft_data_out <= status_words[0][15:8];
|
||||
5'd4: ft_data_out <= status_words[0][7:0];
|
||||
5'd5: ft_data_out <= status_words[1][31:24];
|
||||
5'd6: ft_data_out <= status_words[1][23:16];
|
||||
5'd7: ft_data_out <= status_words[1][15:8];
|
||||
5'd8: ft_data_out <= status_words[1][7:0];
|
||||
5'd9: ft_data_out <= status_words[2][31:24];
|
||||
5'd10: ft_data_out <= status_words[2][23:16];
|
||||
5'd11: ft_data_out <= status_words[2][15:8];
|
||||
5'd12: ft_data_out <= status_words[2][7:0];
|
||||
5'd13: ft_data_out <= status_words[3][31:24];
|
||||
5'd14: ft_data_out <= status_words[3][23:16];
|
||||
5'd15: ft_data_out <= status_words[3][15:8];
|
||||
5'd16: ft_data_out <= status_words[3][7:0];
|
||||
5'd17: ft_data_out <= status_words[4][31:24];
|
||||
5'd18: ft_data_out <= status_words[4][23:16];
|
||||
5'd19: ft_data_out <= status_words[4][15:8];
|
||||
5'd20: ft_data_out <= status_words[4][7:0];
|
||||
5'd21: ft_data_out <= status_words[5][31:24];
|
||||
5'd22: ft_data_out <= status_words[5][23:16];
|
||||
5'd23: ft_data_out <= status_words[5][15:8];
|
||||
5'd24: ft_data_out <= status_words[5][7:0];
|
||||
5'd25: ft_data_out <= status_words[6][31:24]; // PR-G
|
||||
5'd26: ft_data_out <= status_words[6][23:16]; // PR-G
|
||||
5'd27: ft_data_out <= status_words[6][15:8]; // PR-G
|
||||
5'd28: ft_data_out <= status_words[6][7:0]; // PR-G
|
||||
5'd29: ft_data_out <= FOOTER;
|
||||
case (wr_byte_idx[5:0])
|
||||
6'd0: ft_data_out <= STATUS_HEADER;
|
||||
6'd1: ft_data_out <= status_words[0][31:24];
|
||||
6'd2: ft_data_out <= status_words[0][23:16];
|
||||
6'd3: ft_data_out <= status_words[0][15:8];
|
||||
6'd4: ft_data_out <= status_words[0][7:0];
|
||||
6'd5: ft_data_out <= status_words[1][31:24];
|
||||
6'd6: ft_data_out <= status_words[1][23:16];
|
||||
6'd7: ft_data_out <= status_words[1][15:8];
|
||||
6'd8: ft_data_out <= status_words[1][7:0];
|
||||
6'd9: ft_data_out <= status_words[2][31:24];
|
||||
6'd10: ft_data_out <= status_words[2][23:16];
|
||||
6'd11: ft_data_out <= status_words[2][15:8];
|
||||
6'd12: ft_data_out <= status_words[2][7:0];
|
||||
6'd13: ft_data_out <= status_words[3][31:24];
|
||||
6'd14: ft_data_out <= status_words[3][23:16];
|
||||
6'd15: ft_data_out <= status_words[3][15:8];
|
||||
6'd16: ft_data_out <= status_words[3][7:0];
|
||||
6'd17: ft_data_out <= status_words[4][31:24];
|
||||
6'd18: ft_data_out <= status_words[4][23:16];
|
||||
6'd19: ft_data_out <= status_words[4][15:8];
|
||||
6'd20: ft_data_out <= status_words[4][7:0];
|
||||
6'd21: ft_data_out <= status_words[5][31:24];
|
||||
6'd22: ft_data_out <= status_words[5][23:16];
|
||||
6'd23: ft_data_out <= status_words[5][15:8];
|
||||
6'd24: ft_data_out <= status_words[5][7:0];
|
||||
6'd25: ft_data_out <= status_words[6][31:24]; // PR-G
|
||||
6'd26: ft_data_out <= status_words[6][23:16]; // PR-G
|
||||
6'd27: ft_data_out <= status_words[6][15:8]; // PR-G
|
||||
6'd28: ft_data_out <= status_words[6][7:0]; // PR-G
|
||||
6'd29: ft_data_out <= status_words[7][31:24]; // M-5: medium_chirp[15:8]
|
||||
6'd30: ft_data_out <= status_words[7][23:16]; // M-5: medium_chirp[7:0]
|
||||
6'd31: ft_data_out <= status_words[7][15:8]; // M-5: medium_listen[15:8]
|
||||
6'd32: ft_data_out <= status_words[7][7:0]; // M-5: medium_listen[7:0]
|
||||
6'd33: ft_data_out <= FOOTER;
|
||||
default: ft_data_out <= 8'h00;
|
||||
endcase
|
||||
|
||||
if (wr_byte_idx[4:0] == STATUS_PKT_LEN - 5'd1) begin
|
||||
if (wr_byte_idx[5:0] == STATUS_PKT_LEN - 6'd1) begin
|
||||
wr_state <= WR_DONE;
|
||||
wr_byte_idx <= 16'd0;
|
||||
end else begin
|
||||
|
||||
Reference in New Issue
Block a user