observerw/main / chip__ADV7513-Example__Verilog___pattern_vg___5940205a5d /testbench /tb_response.txt
| ```python | |
| #!/usr/bin/env python3 | |
| """ | |
| Testbench for pattern_vg module. | |
| """ | |
| import random | |
| import sys | |
| from pathlib import Path | |
| import cocotb | |
| from cocotb.clock import Clock | |
| from cocotb.triggers import RisingEdge, FallingEdge, Timer | |
| from cocotb_tools.runner import get_runner | |
| # Project root is one level above testbench directory | |
| project_root = Path(__file__).resolve().parents[1] | |
| async def reset_dut(dut, active_high=True, duration=10): | |
| """Reset the DUT.""" | |
| if hasattr(dut, "reset"): | |
| dut.reset.value = 1 if active_high else 0 | |
| await Timer(duration, units="ns") | |
| dut.reset.value = 0 if active_high else 1 | |
| await RisingEdge(dut.clk_in) | |
| await FallingEdge(dut.clk_in) | |
| @cocotb.test() | |
| async def test_reset_and_control_signals(dut): | |
| """Test reset behavior and control signal passthrough.""" | |
| # Create clock | |
| clock = Clock(dut.clk_in, 10, units="ns") | |
| cocotb.start_soon(clock.start()) | |
| # Apply reset | |
| await reset_dut(dut, active_high=True, duration=20) | |
| # Test control signal passthrough | |
| for _ in range(10): | |
| vn_val = random.randint(0, 1) | |
| hn_val = random.randint(0, 1) | |
| dn_val = random.randint(0, 1) | |
| dut.vn_in.value = vn_val | |
| dut.hn_in.value = hn_val | |
| dut.dn_in.value = dn_val | |
| await RisingEdge(dut.clk_in) | |
| await FallingEdge(dut.clk_in) | |
| # Control signals should pass through with one cycle delay | |
| assert dut.vn_out.value == vn_val, f"vn_out mismatch: {dut.vn_out.value} != {vn_val}" | |
| assert dut.hn_out.value == hn_val, f"hn_out mismatch: {dut.hn_out.value} != {hn_val}" | |
| assert dut.den_out.value == dn_val, f"den_out mismatch: {dut.den_out.value} != {dn_val}" | |
| @cocotb.test() | |
| async def test_pattern_0_no_pattern(dut): | |
| """Test pattern 0: no pattern (passthrough).""" | |
| clock = Clock(dut.clk_in, 10, units="ns") | |
| cocotb.start_soon(clock.start()) | |
| await reset_dut(dut) | |
| # Set pattern 0 | |
| dut.pattern.value = 0 | |
| dut.dn_in.value = 1 # Data enable | |
| # Test RGB passthrough | |
| for _ in range(5): | |
| r_val = random.randint(0, 255) | |
| g_val = random.randint(0, 255) | |
| b_val = random.randint(0, 255) | |
| dut.r_in.value = r_val | |
| dut.g_in.value = g_val | |
| dut.b_in.value = b_val | |
| await RisingEdge(dut.clk_in) | |
| await FallingEdge(dut.clk_in) | |
| # RGB should pass through unchanged | |
| assert dut.r_out.value == r_val, f"r_out mismatch: {dut.r_out.value} != {r_val}" | |
| assert dut.g_out.value == g_val, f"g_out mismatch: {dut.g_out.value} != {g_val}" | |
| assert dut.b_out.value == b_val, f"b_out mismatch: {dut.b_out.value} != {b_val}" | |
| @cocotb.test() | |
| async def test_pattern_1_border(dut): | |
| """Test pattern 1: border pattern.""" | |
| clock = Clock(dut.clk_in, 10, units="ns") | |
| cocotb.start_soon(clock.start()) | |
| await reset_dut(dut) | |
| # Set pattern 1 | |
| dut.pattern.value = 1 | |
| dut.dn_in.value = 1 | |
| dut.total_active_pix.value = 640 | |
| dut.total_active_lines.value = 480 | |
| # Test border pixels (should be white) | |
| border_cases = [ | |
| (0, 0), # top-left corner | |
| (639, 0), # top-right corner | |
| (0, 479), # bottom-left corner | |
| (639, 479), # bottom-right corner | |
| (320, 0), # top border | |
| (0, 240), # left border | |
| (639, 240), # right border | |
| (320, 479), # bottom border | |
| ] | |
| for x, y in border_cases: | |
| dut.x.value = x | |
| dut.y.value = y | |
| dut.r_in.value = 0x12 | |
| dut.g_in.value = 0x34 | |
| dut.b_in.value = 0x56 | |
| await RisingEdge(dut.clk_in) | |
| await FallingEdge(dut.clk_in) | |
| # Border should be white | |
| assert dut.r_out.value == 0xFF, f"Border r_out not white: {dut.r_out.value}" | |
| assert dut.g_out.value == 0xFF, f"Border g_out not white: {dut.g_out.value}" | |
| assert dut.b_out.value == 0xFF, f"Border b_out not white: {dut.b_out.value}" | |
| # Test non-border pixel (should pass through) | |
| dut.x.value = 100 | |
| dut.y.value = 100 | |
| dut.r_in.value = 0x12 | |
| dut.g_in.value = 0x34 | |
| dut.b_in.value = 0x56 | |
| await RisingEdge(dut.clk_in) | |
| await FallingEdge(dut.clk_in) | |
| assert dut.r_out.value == 0x12, f"Non-border r_out mismatch: {dut.r_out.value}" | |
| assert dut.g_out.value == 0x34, f"Non-border g_out mismatch: {dut.g_out.value}" | |
| assert dut.b_out.value == 0x56, f"Non-border b_out mismatch: {dut.b_out.value}" | |
| @cocotb.test() | |
| async def test_pattern_2_moirex(dut): | |
| """Test pattern 2: moireX pattern.""" | |
| clock = Clock(dut.clk_in, 10, units="ns") | |
| cocotb.start_soon(clock.start()) | |
| await reset_dut(dut) | |
| # Set pattern 2 | |
| dut.pattern.value = 2 | |
| dut.dn_in.value = 1 | |
| # Test even and odd x coordinates | |
| test_cases = [(100, 0), (101, 1), (102, 0), (103, 1)] | |
| for x_val, expected_white in test_cases: | |
| dut.x.value = x_val | |
| dut.y.value = 50 | |
| dut.r_in.value = 0x12 | |
| dut.g_in.value = 0x34 | |
| dut.b_in.value = 0x56 | |
| await RisingEdge(dut.clk_in) | |
| await FallingEdge(dut.clk_in) | |
| if expected_white: | |
| # Odd x should be white | |
| assert dut.r_out.value == 0xFF, f"moireX odd x not white: {dut.r_out.value}" | |
| assert dut.g_out.value == 0xFF, f"moireX odd x not white: {dut.g_out.value}" | |
| assert dut.b_out.value == 0xFF, f"moireX odd x not white: {dut.b_out.value}" | |
| else: | |
| # Even x should be black | |
| assert dut.r_out.value == 0x00, f"moireX even x not black: {dut.r_out.value}" | |
| assert dut.g_out.value == 0x00, f"moireX even x not black: {dut.g_out.value}" | |
| assert dut.b_out.value == 0x00, f"moireX even x not black: {dut.b_out.value}" | |
| @cocotb.test() | |
| async def test_pattern_4_ramp(dut): | |
| """Test pattern 4: ramp pattern.""" | |
| clock = Clock(dut.clk_in, 10, units="ns") | |
| cocotb.start_soon(clock.start()) | |
| await reset_dut(dut) | |
| # Set pattern 4 | |
| dut.pattern.value = 4 | |
| dut.dn_in.value = 1 | |
| dut.total_active_pix.value = 10 | |
| dut.ramp_step.value = 0x100 # 8-bit integer step (1.0 in fixed point) | |
| # Test ramp accumulation | |
| for i in range(10): | |
| dut.x.value = i | |
| await RisingEdge(dut.clk_in) | |
| await FallingEdge(dut.clk_in) | |
| # Ramp value should increase by 1 each pixel | |
| expected_rgb = i if i < 256 else 255 | |
| assert dut.r_out.value == expected_rgb, f"Ramp r_out mismatch at x={i}: {dut.r_out.value} != {expected_rgb}" | |
| assert dut.g_out.value == expected_rgb, f"Ramp g_out mismatch at x={i}: {dut.g_out.value} != {expected_rgb}" | |
| assert dut.b_out.value == expected_rgb, f"Ramp b_out mismatch at x={i}: {dut.b_out.value} != {expected_rgb}" | |
| # Test reset at end of line | |
| dut.x.value = 9 # Last pixel | |
| await RisingEdge(dut.clk_in) | |
| await FallingEdge(dut.clk_in) | |
| # Next pixel should start from ramp_step | |
| dut.x.value = 0 | |
| await RisingEdge(dut.clk_in) | |
| await FallingEdge(dut.clk_in) | |
| assert dut.r_out.value == 1, f"Ramp reset mismatch: {dut.r_out.value} != 1" | |
| def run_tests(): | |
| """Run the tests using cocotb runner.""" | |
| sim = "icarus" | |
Xet Storage Details
- Size:
- 7.33 kB
- Xet hash:
- ab2883ddb8fc7b8f4e972b219bf0e94c869d7f493376c56a0d73d9663983e3d2
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.