Livt packages
Livt.Signal
Version 0.1.1
Q1.15 sample streams, filters, windows, rate conversion, FFTs, oscillators, and mixers for Livt.
Published files (80)
tests/oscillator/OscillatorMixerQ15Fixture.lvt
namespace Livt.Signal.Tests.Oscillator
using Livt.Signal.Mixer
using Livt.Signal.Oscillator
using Livt.Signal.Stream
using Livt.Signal.Transform
/**
* Captures four complex Q1.15 tokens from a caller-controlled stream.
*/
component ComplexCapture4
{
stream: IComplexSampleStream<logic[16]>
public ready: in bool
public accepted: int
real0: logic[16]
real1: logic[16]
real2: logic[16]
real3: logic[16]
imag0: logic[16]
imag1: logic[16]
imag2: logic[16]
imag3: logic[16]
public firstSeen: bool
public lastSeen: bool
new(stream: IComplexSampleStream<logic[16]>)
{
this.stream = stream
}
process Drive[]()
{
stream.ready = this.context.rst == 0b0 && ready && accepted < 4
}
process Capture()
{
state {
if (stream.valid && stream.ready && accepted < 4) {
if (accepted == 0) {
real0 = stream.real
imag0 = stream.imag
} else {
if (accepted == 1) {
real1 = stream.real
imag1 = stream.imag
} else {
if (accepted == 2) {
real2 = stream.real
imag2 = stream.imag
} else {
real3 = stream.real
imag3 = stream.imag
}
}
}
if (stream.first) { firstSeen = true }
if (stream.last) { lastSeen = true }
accepted++
}
}
}
public fn GetReal(index: int) int
{
if (index == 0) { return real0 as int }
if (index == 1) { return real1 as int }
if (index == 2) { return real2 as int }
return real3 as int
}
public fn GetImag(index: int) int
{
if (index == 0) { return imag0 as int }
if (index == 1) { return imag1 as int }
if (index == 2) { return imag2 as int }
return imag3 as int
}
}
/**
* Generates one CORDIC NCO sequence and retains its first four samples.
*/
component CordicNcoFixture<INCREMENT: int, INITIAL_PHASE: int = 0>
{
stream: IComplexSampleStream<logic[16]>
nco: CordicNcoQ15<16, INITIAL_PHASE>
observer: ComplexCapture4
public ready: in bool
public accepted: out int
public phase: out logic[16]
new()
{
nco = new CordicNcoQ15<16, INITIAL_PHASE>(stream)
observer = new ComplexCapture4(stream)
}
process Connect[]()
{
nco.phaseIncrement = INCREMENT as logic[16]
observer.ready = ready
accepted = observer.accepted
phase = nco.phase
}
public fn GetReal(index: int) int
{
return observer.GetReal(index)
}
public fn GetImag(index: int) int
{
return observer.GetImag(index)
}
}
/**
* Emits two real half-scale samples as one framed transaction.
*/
component RealPairSource
{
stream: IQ15SampleStream
index: int
public accepted: int
new(stream: flip IQ15SampleStream)
{
this.stream = stream
}
process Send()
{
state Offer {
stream.sample = 16384 as logic[16]
stream.valid = true
stream.first = index == 0
stream.last = index == 1
goto AwaitAccept
}
state AwaitAccept {
if (stream.ready) {
stream.valid = false
accepted++
if (index == 1) { goto Idle } else {
index++;
goto Gap
}
}
}
state Gap {
stream.valid = false;
stream.first = false;
stream.last = false;
goto Offer
}
state Idle {
stream.valid = false;
stream.first = false;
stream.last = false;
goto Idle
}
}
}
/**
* Emits two quarter-turn oscillator values.
*/
component QuarterTurnPairSource
{
stream: IComplexSampleStream<logic[16]>
index: int
public accepted: int
new(stream: flip IComplexSampleStream<logic[16]>)
{
this.stream = stream
}
process Send()
{
state Offer {
if (index == 0) {
stream.real = 32767 as logic[16]
stream.imag = 0x0000
} else {
stream.real = 0x0000
stream.imag = 32767 as logic[16]
}
stream.valid = true
stream.first = false
stream.last = false
goto AwaitAccept
}
state AwaitAccept {
if (stream.ready) {
stream.valid = false
accepted++
if (index == 1) { goto Idle } else {
index++;
goto Gap
}
}
}
state Gap {
stream.valid = false;
goto Offer
}
state Idle {
stream.valid = false;
goto Idle
}
}
}
/**
* Emits one constant complex sample as a one-token frame.
*/
component ComplexSingleSource<REAL: int, IMAG: int>
{
stream: IComplexSampleStream<logic[16]>
public accepted: int
new(stream: flip IComplexSampleStream<logic[16]>)
{
this.stream = stream
}
process Send()
{
state Offer {
stream.real = REAL as logic[16]
stream.imag = IMAG as logic[16]
stream.valid = true
stream.first = true
stream.last = true
goto AwaitAccept
}
state AwaitAccept {
if (stream.ready) {
stream.valid = false
accepted++
goto Idle
}
}
state Idle {
stream.valid = false
stream.first = false
stream.last = false
goto Idle
}
}
}
/**
* Exercises the two-multiplier real-to-complex mixer.
*/
component RealMixerFixture
{
input: IQ15SampleStream
oscillator: IComplexSampleStream<logic[16]>
output: IComplexSampleStream<logic[16]>
source: RealPairSource
oscillatorSource: QuarterTurnPairSource
mixer: RealMixerQ15
observer: ComplexCapture4
public ready: in bool
public accepted: out int
public sourceAccepted: out int
public oscillatorAccepted: out int
new()
{
source = new RealPairSource(input)
oscillatorSource = new QuarterTurnPairSource(oscillator)
mixer = new RealMixerQ15(input, oscillator, output)
observer = new ComplexCapture4(output)
}
process Connect[]()
{
observer.ready = ready
accepted = observer.accepted
sourceAccepted = source.accepted
oscillatorAccepted = oscillatorSource.accepted
}
public fn GetReal(index: int) int
{
return observer.GetReal(index)
}
public fn GetImag(index: int) int
{
return observer.GetImag(index)
}
public fn FirstSeen() bool
{
return observer.firstSeen
}
public fn LastSeen() bool
{
return observer.lastSeen
}
}
/**
* Exercises the four-multiplier complex mixer with a quarter-turn rotation.
*/
component ComplexMixerFixture
{
input: IComplexSampleStream<logic[16]>
oscillator: IComplexSampleStream<logic[16]>
output: IComplexSampleStream<logic[16]>
inputSource: ComplexSingleSource<16384, 16384>
oscillatorSource: ComplexSingleSource<0, 32767>
mixer: ComplexMixerQ15
observer: ComplexCapture4
public ready: in bool
public accepted: out int
new()
{
inputSource = new ComplexSingleSource<16384, 16384>(input)
oscillatorSource = new ComplexSingleSource<0, 32767>(oscillator)
mixer = new ComplexMixerQ15(input, oscillator, output)
observer = new ComplexCapture4(output)
}
process Connect[]()
{
observer.ready = ready
accepted = observer.accepted
}
public fn GetReal() int
{
return observer.GetReal(0)
}
public fn GetImag() int
{
return observer.GetImag(0)
}
}