mirror of
https://github.com/NawfalMotii79/PLFM_RADAR.git
synced 2026-05-23 08:11:54 +00:00
fix(fpga): TX-N9 — sim-only payload-hold checker on cmd CDC
cmd_data / cmd_opcode / cmd_addr / cmd_value feed downstream CDC sync chains; the safety property is that they only change on the cycle cmd_valid rises (RD_PROCESS), and stay held on every other cycle so the receiver's 2-FF synchronizer sees a clean payload regardless of where its sample window lands. The FSM satisfies this implicitly today, but nothing flagged a regression that introduced a stray write somewhere in the same always block. Added an `ifdef SIMULATION block at the bottom of both usb_data_interface.v (FT601 / ft601_clk_in / ft601_reset_n) and usb_data_interface_ft2232h.v (FT2232H / ft_clk / ft_reset_n). It snapshots the payload + cmd_valid each cycle and fires [ASSERT FAIL] TX-N9: cmd_<field> changed while cmd_valid=0 (old -> new) on any payload change while cmd_valid is low. Local regs suffixed _n9 to avoid future name collisions. Synthesis-inert. Quick FPGA regression unchanged: USB Data Interface 91/91 PASS, overall 28/29 (same baseline; the 1 fail is the pre-existing iverilog/Xilinx-IP RX-NEW-3 gap).
This commit is contained in:
@@ -682,4 +682,52 @@ end
|
||||
assign ft601_clk_out = ft601_clk_in;
|
||||
`endif
|
||||
|
||||
// ============================================================================
|
||||
// TX-N9: payload-hold checker (simulation only)
|
||||
//
|
||||
// cmd_data / cmd_opcode / cmd_addr / cmd_value feed downstream CDC sync
|
||||
// chains; safety property is that they only change on the cycle cmd_valid
|
||||
// rises (RD_PROCESS), and are held stable on every other cycle. The FSM
|
||||
// satisfies this implicitly today; this checker fires `[ASSERT FAIL]` on
|
||||
// any payload change while cmd_valid is low so a future regression is
|
||||
// caught in the simulation log. Synthesis-inert.
|
||||
// ============================================================================
|
||||
`ifdef SIMULATION
|
||||
reg [31:0] cmd_data_prev_n9;
|
||||
reg [7:0] cmd_opcode_prev_n9;
|
||||
reg [7:0] cmd_addr_prev_n9;
|
||||
reg [15:0] cmd_value_prev_n9;
|
||||
reg cmd_valid_prev_n9;
|
||||
|
||||
always @(posedge ft601_clk_in or negedge ft601_reset_n) begin
|
||||
if (!ft601_reset_n) begin
|
||||
cmd_data_prev_n9 <= 32'd0;
|
||||
cmd_opcode_prev_n9 <= 8'd0;
|
||||
cmd_addr_prev_n9 <= 8'd0;
|
||||
cmd_value_prev_n9 <= 16'd0;
|
||||
cmd_valid_prev_n9 <= 1'b0;
|
||||
end else begin
|
||||
if (!cmd_valid && !cmd_valid_prev_n9) begin
|
||||
if (cmd_data !== cmd_data_prev_n9)
|
||||
$display("[ASSERT FAIL] TX-N9: cmd_data changed while cmd_valid=0 (%h -> %h)",
|
||||
cmd_data_prev_n9, cmd_data);
|
||||
if (cmd_opcode !== cmd_opcode_prev_n9)
|
||||
$display("[ASSERT FAIL] TX-N9: cmd_opcode changed while cmd_valid=0 (%h -> %h)",
|
||||
cmd_opcode_prev_n9, cmd_opcode);
|
||||
if (cmd_addr !== cmd_addr_prev_n9)
|
||||
$display("[ASSERT FAIL] TX-N9: cmd_addr changed while cmd_valid=0 (%h -> %h)",
|
||||
cmd_addr_prev_n9, cmd_addr);
|
||||
if (cmd_value !== cmd_value_prev_n9)
|
||||
$display("[ASSERT FAIL] TX-N9: cmd_value changed while cmd_valid=0 (%h -> %h)",
|
||||
cmd_value_prev_n9, cmd_value);
|
||||
end
|
||||
cmd_data_prev_n9 <= cmd_data;
|
||||
cmd_opcode_prev_n9 <= cmd_opcode;
|
||||
cmd_addr_prev_n9 <= cmd_addr;
|
||||
cmd_value_prev_n9 <= cmd_value;
|
||||
cmd_valid_prev_n9 <= cmd_valid;
|
||||
end
|
||||
end
|
||||
`endif
|
||||
|
||||
endmodule
|
||||
@@ -967,4 +967,62 @@ always @(posedge ft_clk or negedge ft_effective_reset_n) begin
|
||||
end
|
||||
end
|
||||
|
||||
// ============================================================================
|
||||
// TX-N9: payload-hold checker (simulation only)
|
||||
//
|
||||
// The cmd_* outputs feed a CDC sync chain in the consumer clock domain.
|
||||
// Safety property: cmd_data / cmd_opcode / cmd_addr / cmd_value must only
|
||||
// change on the cycle that cmd_valid rises (RD_PROCESS in this module).
|
||||
// On every other cycle they must be held stable so the receiver's 2-FF
|
||||
// synchronizer sees a clean payload regardless of where its sample window
|
||||
// lands relative to cmd_valid.
|
||||
//
|
||||
// The current FSM satisfies this implicitly — the payload regs are only
|
||||
// written in RD_PROCESS, never elsewhere — but until now nothing flagged
|
||||
// a regression that introduced a stray write somewhere in the always
|
||||
// block. This checker fires `[ASSERT FAIL]` on any payload change while
|
||||
// cmd_valid is low, surfacing the violation in the simulation log
|
||||
// without affecting synthesis.
|
||||
// ============================================================================
|
||||
`ifdef SIMULATION
|
||||
reg [31:0] cmd_data_prev;
|
||||
reg [7:0] cmd_opcode_prev;
|
||||
reg [7:0] cmd_addr_prev;
|
||||
reg [15:0] cmd_value_prev;
|
||||
reg cmd_valid_prev;
|
||||
|
||||
always @(posedge ft_clk or negedge ft_reset_n) begin
|
||||
if (!ft_reset_n) begin
|
||||
cmd_data_prev <= 32'd0;
|
||||
cmd_opcode_prev <= 8'd0;
|
||||
cmd_addr_prev <= 8'd0;
|
||||
cmd_value_prev <= 16'd0;
|
||||
cmd_valid_prev <= 1'b0;
|
||||
end else begin
|
||||
// Payload may legally change only on the cycle cmd_valid rises
|
||||
// (cmd_valid_prev=0, cmd_valid=1). Any other change is a hold
|
||||
// violation.
|
||||
if (!cmd_valid && !cmd_valid_prev) begin
|
||||
if (cmd_data !== cmd_data_prev)
|
||||
$display("[ASSERT FAIL] TX-N9: cmd_data changed while cmd_valid=0 (%h -> %h)",
|
||||
cmd_data_prev, cmd_data);
|
||||
if (cmd_opcode !== cmd_opcode_prev)
|
||||
$display("[ASSERT FAIL] TX-N9: cmd_opcode changed while cmd_valid=0 (%h -> %h)",
|
||||
cmd_opcode_prev, cmd_opcode);
|
||||
if (cmd_addr !== cmd_addr_prev)
|
||||
$display("[ASSERT FAIL] TX-N9: cmd_addr changed while cmd_valid=0 (%h -> %h)",
|
||||
cmd_addr_prev, cmd_addr);
|
||||
if (cmd_value !== cmd_value_prev)
|
||||
$display("[ASSERT FAIL] TX-N9: cmd_value changed while cmd_valid=0 (%h -> %h)",
|
||||
cmd_value_prev, cmd_value);
|
||||
end
|
||||
cmd_data_prev <= cmd_data;
|
||||
cmd_opcode_prev <= cmd_opcode;
|
||||
cmd_addr_prev <= cmd_addr;
|
||||
cmd_value_prev <= cmd_value;
|
||||
cmd_valid_prev <= cmd_valid;
|
||||
end
|
||||
end
|
||||
`endif
|
||||
|
||||
endmodule
|
||||
|
||||
Reference in New Issue
Block a user