diff --git a/target/sim/src/vip_cheshire_soc.sv b/target/sim/src/vip_cheshire_soc.sv index dce214a33..84baab9af 100644 --- a/target/sim/src/vip_cheshire_soc.sv +++ b/target/sim/src/vip_cheshire_soc.sv @@ -1069,9 +1069,9 @@ module vip_cheshire_soc_tristate import cheshire_pkg::*; ( ); // I2C - bufif1 (i2c_sda_i, i2c_sda, ~i2c_sda_en); + assign i2c_sda_i = i2c_sda; bufif1 (i2c_sda, i2c_sda_o, i2c_sda_en); - bufif1 (i2c_scl_i, i2c_scl, ~i2c_scl_en); + assign i2c_scl_i = i2c_scl; bufif1 (i2c_scl, i2c_scl_o, i2c_scl_en); pullup (i2c_sda); pullup (i2c_scl); diff --git a/target/sim/test/I2C_RESOLVED_INPUTS.md b/target/sim/test/I2C_RESOLVED_INPUTS.md new file mode 100644 index 000000000..5d1d9ae6f --- /dev/null +++ b/target/sim/test/I2C_RESOLVED_INPUTS.md @@ -0,0 +1,54 @@ +# I2C resolved inputs in the simulation VIP + +The I2C input buffers used `~i2c_*_en` as their enable. +When the DUT drove either line low, its corresponding input became high impedance. +The controller therefore could not observe the actual resolved bus value. + +Sample both I2C inputs continuously. Preserve the open-drain output buffers, +pullups, and all SPI input/output buffers. + +The finite test instantiates the real `vip_cheshire_soc_tristate` module. +It sweeps all 16 combinations of DUT and peer low/release controls for SDA/SCL. +It also checks released inputs and unchanged SPI input gating. +The test contains no EEPROM model. + +Official base: `6c6dd5e834347f72c7be31cd6c41021ec293c5b9`. +VCS W-2024.09-SP1 compiled both versions. The same 78-check input produced +16 input mismatches on the original and zero on the patch. +The original ended with the expected failure. The patch finished normally at 250 ns. +Both used a 1 us HDL deadline and a 60-second wall-clock limit. + +## Reproduction + +The isolated test extracts the complete real tristate module without edits. +A small package supplies only the SPI chip-select port width for elaboration. +It does not model any I2C behavior or replace the DUT. +From the repository root with VCS on PATH: + +```bash +ROOT=$PWD +mkdir test-i2c-inputs +cd test-i2c-inputs +cat > package.sv <<'SV' +package cheshire_pkg; + localparam int unsigned SpihNumCs = 2; +endpackage +SV +sed -n '/^module vip_cheshire_soc_tristate/,$p' \ + "$ROOT/target/sim/src/vip_cheshire_soc.sv" > vip_tristate.sv +timeout 120 vcs -full64 -sverilog -timescale=1ns/1ps package.sv \ + vip_tristate.sv "$ROOT/target/sim/test/tb_i2c_resolved_inputs.sv" \ + -top tb_i2c_resolved_inputs -o simv -l compile.log +timeout 60 ./simv -l run.log +``` + +For the original comparison, extract the module from the stated official base. +Use a separate output directory and the identical test and package. +The patched log must contain one `I2C_PIN_DONE checks=78 errors=0`, a normal +`$finish`, and no mismatch, fatal, or timeout. The original must report exactly +16 mismatches and the failure marker. A process exit code alone is insufficient. + +This is a four-state simulation-wrapper test. It does not verify the full +I2C controller, EEPROM protocol, or SoC. No synthesizable RTL changes. + +AI assistance: OpenAI Codex assisted the patch, test, and validation. diff --git a/target/sim/test/tb_i2c_resolved_inputs.sv b/target/sim/test/tb_i2c_resolved_inputs.sv new file mode 100644 index 000000000..06c11513d --- /dev/null +++ b/target/sim/test/tb_i2c_resolved_inputs.sv @@ -0,0 +1,57 @@ +// Copyright 2026 CheshireAra contributors. +// SPDX-License-Identifier: Apache-2.0 +`timescale 1ns/1ps +module tb_i2c_resolved_inputs; + tri sda, scl, sck; + tri [1:0] csb; + tri [3:0] sd; + wire sda_i, scl_i; + wire [3:0] sd_i; + logic sda_en = 0, scl_en = 0; + logic peer_sda_low = 0, peer_scl_low = 0; + logic [3:0] sd_en = 0; + logic [3:0] sd_o = 0; + int checks = 0, errors = 0; + assign sda = peer_sda_low ? 1'b0 : 1'bz; + assign scl = peer_scl_low ? 1'b0 : 1'bz; + vip_cheshire_soc_tristate dut ( + .i2c_sda_i(sda_i), .i2c_sda_o(1'b0), .i2c_sda_en(sda_en), + .i2c_scl_i(scl_i), .i2c_scl_o(1'b0), .i2c_scl_en(scl_en), + .i2c_sda(sda), .i2c_scl(scl), + .spih_sck_o(1'b0), .spih_sck_en(1'b0), .spih_sck(sck), + .spih_csb_o(2'b00), .spih_csb_en(2'b00), .spih_csb(csb), + .spih_sd_o(sd_o), .spih_sd_en(sd_en), .spih_sd_i(sd_i), .spih_sd(sd) + ); + task automatic check_bit(input string label, input logic got, want); + checks++; + if (got !== want) begin + errors++; + $display("PIN_MISMATCH %s got=%b want=%b",label,got,want); + end + endtask + initial begin + for (int state_id=0; state_id<16; state_id++) begin + {sda_en,scl_en,peer_sda_low,peer_scl_low}=4'(state_id); + #10; + check_bit("SDA wire",sda,!(sda_en || peer_sda_low)); + check_bit("SDA input",sda_i,!(sda_en || peer_sda_low)); + check_bit("SCL wire",scl,!(scl_en || peer_scl_low)); + check_bit("SCL input",scl_i,!(scl_en || peer_scl_low)); + end + sda_en=0; scl_en=0; peer_sda_low=0; peer_scl_low=0; + #10; + check_bit("SDA release",sda_i,1'b1); + check_bit("SCL release",scl_i,1'b1); + for (int pin=0;pin<4;pin++) begin + sd_o=0; sd_en=4'(1<