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)

src/mixer/Q15MixerPipelinePrimitive.vhd

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.livt_lang_icontext_package.all;

entity livt_signal_mixer_q15mixerpipelineprimitive is
    port (
        ctor_lvt_context_in : in t_icontext_in;
        ctor_realinput : in boolean;
        ctor_samplevalid : in boolean;
        ctor_sampleready : out boolean;
        ctor_samplereal : in std_logic_vector(15 downto 0);
        ctor_sampleimag : in std_logic_vector(15 downto 0);
        ctor_samplefirst : in boolean;
        ctor_samplelast : in boolean;
        ctor_oscillatorvalid : in boolean;
        ctor_oscillatorready : out boolean;
        ctor_oscillatorreal : in std_logic_vector(15 downto 0);
        ctor_oscillatorimag : in std_logic_vector(15 downto 0);
        ctor_outputvalid : out boolean;
        ctor_outputready : in boolean;
        ctor_outputreal : out std_logic_vector(15 downto 0);
        ctor_outputimag : out std_logic_vector(15 downto 0);
        ctor_outputfirst : out boolean;
        ctor_outputlast : out boolean
    );
end;

architecture rtl of livt_signal_mixer_q15mixerpipelineprimitive is
    subtype wide_t is signed(32 downto 0);
    signal result_valid : boolean := false;
    signal result_real, result_imag : std_logic_vector(15 downto 0) := (others => '0');
    signal result_first, result_last : boolean := false;
    signal advance : boolean;

    function quantize_q15(value : wide_t) return std_logic_vector is
        variable magnitude, rounded : unsigned(32 downto 0);
        variable negative : boolean;
    begin
        negative := value(value'high) = '1';
        if negative then magnitude := unsigned(-value); else magnitude := unsigned(value); end if;
        rounded := shift_right(magnitude, 15);
        if magnitude(14) = '1' and
            (magnitude(13 downto 0) /= to_unsigned(0, 14) or rounded(0) = '1') then
            rounded := rounded + 1;
        end if;
        if negative then
            if rounded > to_unsigned(32768, rounded'length) then
                return std_logic_vector(to_signed(-32768, 16));
            end if;
            return std_logic_vector(-signed(resize(rounded, 16)));
        end if;
        if rounded > to_unsigned(32767, rounded'length) then
            return std_logic_vector(to_signed(32767, 16));
        end if;
        return std_logic_vector(resize(rounded, 16));
    end function;
begin
    advance <= not result_valid or ctor_outputready;
    ctor_sampleready <= ctor_lvt_context_in.rst = '0' and advance and ctor_oscillatorvalid;
    ctor_oscillatorready <= ctor_lvt_context_in.rst = '0' and advance and ctor_samplevalid;
    ctor_outputvalid <= ctor_lvt_context_in.rst = '0' and result_valid;
    ctor_outputreal <= result_real;
    ctor_outputimag <= result_imag;
    ctor_outputfirst <= result_first;
    ctor_outputlast <= result_last;

    process (ctor_lvt_context_in.clk)
        variable ar, ai, br, bi : signed(15 downto 0);
        variable ac, bd, ad, bc : signed(31 downto 0);
    begin
        if rising_edge(ctor_lvt_context_in.clk) then
            if ctor_lvt_context_in.rst = '1' then
                result_valid <= false;
                result_first <= false;
                result_last <= false;
            elsif advance then
                result_valid <= ctor_samplevalid and ctor_oscillatorvalid;
                if ctor_samplevalid and ctor_oscillatorvalid then
                    ar := signed(ctor_samplereal);
                    ai := signed(ctor_sampleimag);
                    br := signed(ctor_oscillatorreal);
                    bi := signed(ctor_oscillatorimag);
                    ac := ar * br;
                    ad := ar * bi;
                    if ctor_realinput then
                        result_real <= quantize_q15(resize(ac, wide_t'length));
                        result_imag <= quantize_q15(resize(ad, wide_t'length));
                    else
                        bd := ai * bi;
                        bc := ai * br;
                        result_real <= quantize_q15(resize(ac, wide_t'length) - resize(bd, wide_t'length));
                        result_imag <= quantize_q15(resize(ad, wide_t'length) + resize(bc, wide_t'length));
                    end if;
                    result_first <= ctor_samplefirst;
                    result_last <= ctor_samplelast;
                else
                    result_first <= false;
                    result_last <= false;
                end if;
            end if;
        end if;
    end process;
end;