Livt packages

Eccelerators.Video

Version 1.0.1

Streaming pixel pipelines, filters, test patterns, and parallel camera capture for Livt FPGA applications.

Published files (22)

tests/PixelThroughputTest.lvt

namespace Eccelerators.Video.Tests

using Eccelerators.Video

/**
 * Counts actual edge acceptances through a producer/bypass, with a continuously ready sink.
 * The concurrent sink records errors; the scheduled test checks final counters.
 */
@Test
@Context(ClockFrequency = 50MHz)
component PixelThroughputTest
{
	// Owned producer and combinational transport stage.
	source: PatternSource<4, 3, 0>
	bypass: PixelBypass

	// Test controls and observed counters; sink owns accepted/errors/ticks.
	enabled: bool
	pattern: int
	public accepted: out uint
	public errors: out uint
	public ticks: out uint
	public activeCycles: out uint
	public started: out bool

	/**
	 * Builds a small Gray8 raster without blanking.
	 */
	new()
	{
		this.pattern = 0
		this.source = new PatternSource<4, 3, 0>(this.enabled, this.pattern)
		this.bypass = new PixelBypass(this.source.data, this.source.valid, this.source.frameStart,
			this.source.lineEnd, this.source.frameEnd, this.source.frameId)
	}

	/**
	 * Accepts every edge and stops after three complete frames.
	 */
	process Ready[]()
	{
		this.source.ready = this.bypass.upstreamReady
		this.bypass.ready = this.accepted < 36
	}

	/**
	 * Checks every accepted token against an independently counted raster position.
	 */
	process Sink()
	{
		state Tick {
			this.ticks++

			if ((this.started || this.bypass.valid) && this.accepted < 36) {
				this.activeCycles++
				this.started = true
			}

			if (this.bypass.valid && this.bypass.ready) {
				var position = this.accepted % 12

				if (this.bypass.data != position as logic[16]
					|| this.bypass.frameStart != (position == 0)
					|| this.bypass.lineEnd != (position % 4 == 3)
					|| this.bypass.frameEnd != (position == 11)
					|| this.bypass.frameId != this.accepted / 12) {
					this.errors++
				}

				this.accepted++
			}

			goto Tick
		}
	}

	/**
	 * Checks 36 accepted pixels in exactly 36 active clock cycles.
	 */
	@Test
	fn AcceptsOnePixelEveryClock()
	{
		this.enabled = true
		Simulation.Wait(200)
		assert this.accepted == 36
		assert this.errors == 0
		assert this.activeCycles == 36
	}
}