Circuit Debugging Guide
Systematic Debugging Methodology
When a circuit produces incorrect output, follow this systematic approach to isolate and fix the problem.
Step 1: Verify Input Handling
First, confirm inputs are being read correctly:
- Create a passthrough test - output should equal input directly
- Test with multiple input values to confirm they differ
- If all outputs are identical regardless of input, check input signal initialization
Common input initialization patterns:
- Some simulators require explicit identity:
out{i} = in{i} or out{i} = out{i}
- Some simulators auto-pass inputs
- Setting inputs to constant 0 is a common mistake
Step 2: Test Primitive Operations
Verify basic gates work as expected:
- AND gate - Test:
1 AND 1 = 1, 1 AND 0 = 0
- OR gate - Test:
0 OR 1 = 1, 0 OR 0 = 0
- XOR gate - Test:
1 XOR 1 = 0, 1 XOR 0 = 1
- NOT gate - Test:
NOT 0 = 1, NOT 1 = 0
Step 3: Test Compound Operations
Build up complexity incrementally:
- N-bit adder - Test:
3 + 5 = 8, verify carry propagation with 255 + 1 = 256
- Comparator - Test:
5 < 10 = 1, 10 < 5 = 0, 5 < 5 = 0
- Multiplexer - Test selector with both 0 and 1, verify correct value selected
Step 4: Isolate Component Failures
For composite circuits, test components independently:
- Extract the isqrt subcircuit - test:
isqrt(16) = 4, isqrt(17) = 4, isqrt(0) = 0
- Extract the Fibonacci subcircuit - test:
fib(0) = 0, fib(1) = 1, fib(10) = 55
- Test control logic separately - verify state transitions
Step 5: Add Debug Outputs
Expose intermediate signals to trace execution:
# Example: expose isqrt result as debug output
debug_isqrt_result = [output bits of isqrt component]
# Example: expose Fibonacci state
debug_fib_a = [current 'a' register]
debug_fib_b = [current 'b' register]
debug_counter = [iteration counter]
Run simulation and examine intermediate values at each step.
Common Bug Patterns and Fixes
Pattern: Output Always Zero
Symptoms: Output is 0 regardless of input.
Likely Causes:
- Input signals not connected properly
- Gate output not routed to final output
- Control signal stuck, causing mux to always select 0
Debug Steps:
- Add debug output for raw input
- Trace signal path from input to output
- Check control/selector signals
Pattern: Output Constant But Non-Zero
Symptoms: Output is always the same non-zero value.
Likely Causes:
- Sequential logic not iterating (counter stuck)
- Feedback not connected
- Initial value being output without updates
Debug Steps:
- Output the iteration counter
- Verify feedback connections
- Check done/ready signal logic
Pattern: Off-By-One Errors
Symptoms: Output is close to expected but consistently wrong.
Likely Causes:
- Loop bounds incorrect (< vs <=)
- Counter initialized to wrong value
- Output taken from wrong state variable
Debug Steps:
- Trace state through iterations
- Verify initial counter value
- Check which variable holds final result
Pattern: Correct for Small Inputs, Wrong for Large
Symptoms: Works for inputs like 0, 1, 4 but fails for larger values.
Likely Causes:
- Bit width insufficient (overflow)
- Algorithm only handles subset of cases
- Carry propagation issues in adders
Debug Steps:
- Check bit widths of all intermediate values
- Verify adder handles full range
- Test boundary values explicitly
Pattern: Intermittent Failures
Symptoms: Sometimes correct, sometimes wrong for same input.
Likely Causes:
- Race conditions in asynchronous logic
- Uninitialized state
- Timing-dependent feedback behavior
Debug Steps:
- Add extra propagation steps
- Verify all state is properly initialized
- Check feedback timing
Testing Framework Pattern
Create a reusable testing harness to avoid duplicating test code:
class CircuitTester:
def __init__(self, circuit_generator, simulator):
self.generator = circuit_generator
self.simulator = simulator
def test_case(self, input_val, expected_output):
circuit = self.generator()
result = self.simulator.run(circuit, input_val)
return result == expected_output
def run_suite(self, test_cases):
results = []
for input_val, expected in test_cases:
passed = self.test_case(input_val, expected)
results.append((input_val, expected, passed))
return results
Standard Test Suites
isqrt test cases:
- (0, 0), (1, 1), (2, 1), (3, 1), (4, 2), (8, 2), (9, 3), (15, 3), (16, 4), (100, 10)
Fibonacci test cases:
- (0, 0), (1, 1), (2, 1), (3, 2), (4, 3), (5, 5), (10, 55), (20, 6765)
Combined fib(isqrt(N)) test cases:
- (0, 0), (1, 1), (4, 1), (9, 2), (16, 3), (25, 5), (100, 55), (208, 377)
Gate Count Estimation
Estimate gate requirements before implementation:
| Component |
Approximate Gates |
| N-bit ripple adder |
5N |
| N-bit carry-lookahead adder |
10N |
| N-bit comparator |
3N |
| N-bit multiplexer (2:1) |
3N |
| N-bit AND/OR/XOR |
N |
| N-bit multiplier |
N² to N²log(N) |
For a 32-bit fib(isqrt(N)) implementation:
- isqrt (bit-by-bit): ~16 iterations × ~200 gates = ~3200 gates
- Fibonacci iteration: ~3 adders + muxes = ~500 gates
- Control logic: ~100 gates
- Total estimate: ~4000-5000 gates
If approaching gate limits, consider:
- Reducing bit width where safe
- Sharing logic between components
- Using more efficient algorithms
1---2name: circuit-debugging-guide3description: When a circuit produces incorrect output, follow this systematic approach to isolate and fix the problem.4---5# Circuit Debugging Guide67## Systematic Debugging Methodology89When a circuit produces incorrect output, follow this systematic approach to isolate and fix the problem.1011### Step 1: Verify Input Handling1213First, confirm inputs are being read correctly:14151. Create a passthrough test - output should equal input directly162. Test with multiple input values to confirm they differ173. If all outputs are identical regardless of input, check input signal initialization1819Common input initialization patterns:20- Some simulators require explicit identity: `out{i} = in{i}` or `out{i} = out{i}`21- Some simulators auto-pass inputs22- Setting inputs to constant 0 is a common mistake2324### Step 2: Test Primitive Operations2526Verify basic gates work as expected:27281. **AND gate** - Test: `1 AND 1 = 1`, `1 AND 0 = 0`292. **OR gate** - Test: `0 OR 1 = 1`, `0 OR 0 = 0`303. **XOR gate** - Test: `1 XOR 1 = 0`, `1 XOR 0 = 1`314. **NOT gate** - Test: `NOT 0 = 1`, `NOT 1 = 0`3233### Step 3: Test Compound Operations3435Build up complexity incrementally:36371. **N-bit adder** - Test: `3 + 5 = 8`, verify carry propagation with `255 + 1 = 256`382. **Comparator** - Test: `5 < 10 = 1`, `10 < 5 = 0`, `5 < 5 = 0`393. **Multiplexer** - Test selector with both 0 and 1, verify correct value selected4041### Step 4: Isolate Component Failures4243For composite circuits, test components independently:44451. Extract the isqrt subcircuit - test: `isqrt(16) = 4`, `isqrt(17) = 4`, `isqrt(0) = 0`462. Extract the Fibonacci subcircuit - test: `fib(0) = 0`, `fib(1) = 1`, `fib(10) = 55`473. Test control logic separately - verify state transitions4849### Step 5: Add Debug Outputs5051Expose intermediate signals to trace execution:5253```54# Example: expose isqrt result as debug output55debug_isqrt_result = [output bits of isqrt component]5657# Example: expose Fibonacci state58debug_fib_a = [current 'a' register]59debug_fib_b = [current 'b' register]60debug_counter = [iteration counter]61```6263Run simulation and examine intermediate values at each step.6465## Common Bug Patterns and Fixes6667### Pattern: Output Always Zero6869**Symptoms**: Output is 0 regardless of input.7071**Likely Causes**:721. Input signals not connected properly732. Gate output not routed to final output743. Control signal stuck, causing mux to always select 07576**Debug Steps**:771. Add debug output for raw input782. Trace signal path from input to output793. Check control/selector signals8081### Pattern: Output Constant But Non-Zero8283**Symptoms**: Output is always the same non-zero value.8485**Likely Causes**:861. Sequential logic not iterating (counter stuck)872. Feedback not connected883. Initial value being output without updates8990**Debug Steps**:911. Output the iteration counter922. Verify feedback connections933. Check done/ready signal logic9495### Pattern: Off-By-One Errors9697**Symptoms**: Output is close to expected but consistently wrong.9899**Likely Causes**:1001. Loop bounds incorrect (< vs <=)1012. Counter initialized to wrong value1023. Output taken from wrong state variable103104**Debug Steps**:1051. Trace state through iterations1062. Verify initial counter value1073. Check which variable holds final result108109### Pattern: Correct for Small Inputs, Wrong for Large110111**Symptoms**: Works for inputs like 0, 1, 4 but fails for larger values.112113**Likely Causes**:1141. Bit width insufficient (overflow)1152. Algorithm only handles subset of cases1163. Carry propagation issues in adders117118**Debug Steps**:1191. Check bit widths of all intermediate values1202. Verify adder handles full range1213. Test boundary values explicitly122123### Pattern: Intermittent Failures124125**Symptoms**: Sometimes correct, sometimes wrong for same input.126127**Likely Causes**:1281. Race conditions in asynchronous logic1292. Uninitialized state1303. Timing-dependent feedback behavior131132**Debug Steps**:1331. Add extra propagation steps1342. Verify all state is properly initialized1353. Check feedback timing136137## Testing Framework Pattern138139Create a reusable testing harness to avoid duplicating test code:140141```python142class CircuitTester:143 def __init__(self, circuit_generator, simulator):144 self.generator = circuit_generator145 self.simulator = simulator146147 def test_case(self, input_val, expected_output):148 circuit = self.generator()149 result = self.simulator.run(circuit, input_val)150 return result == expected_output151152 def run_suite(self, test_cases):153 results = []154 for input_val, expected in test_cases:155 passed = self.test_case(input_val, expected)156 results.append((input_val, expected, passed))157 return results158```159160### Standard Test Suites161162**isqrt test cases**:163- (0, 0), (1, 1), (2, 1), (3, 1), (4, 2), (8, 2), (9, 3), (15, 3), (16, 4), (100, 10)164165**Fibonacci test cases**:166- (0, 0), (1, 1), (2, 1), (3, 2), (4, 3), (5, 5), (10, 55), (20, 6765)167168**Combined fib(isqrt(N)) test cases**:169- (0, 0), (1, 1), (4, 1), (9, 2), (16, 3), (25, 5), (100, 55), (208, 377)170171## Gate Count Estimation172173Estimate gate requirements before implementation:174175| Component | Approximate Gates |176|-----------|------------------|177| N-bit ripple adder | 5N |178| N-bit carry-lookahead adder | 10N |179| N-bit comparator | 3N |180| N-bit multiplexer (2:1) | 3N |181| N-bit AND/OR/XOR | N |182| N-bit multiplier | N² to N²log(N) |183184For a 32-bit fib(isqrt(N)) implementation:185- isqrt (bit-by-bit): ~16 iterations × ~200 gates = ~3200 gates186- Fibonacci iteration: ~3 adders + muxes = ~500 gates187- Control logic: ~100 gates188- Total estimate: ~4000-5000 gates189190If approaching gate limits, consider:1911. Reducing bit width where safe1922. Sharing logic between components1933. Using more efficient algorithms