Files
61782b02d7 fpga: x400: Add support for X410 motherboard FPGA
Co-authored-by: Andrew Moch <Andrew.Moch@ni.com>
Co-authored-by: Daniel Jepson <daniel.jepson@ni.com>
Co-authored-by: Javier Valenzuela <javier.valenzuela@ni.com>
Co-authored-by: Joerg Hofrichter <joerg.hofrichter@ni.com>
Co-authored-by: Kumaran Subramoniam <kumaran.subramoniam@ni.com>
Co-authored-by: Max Köhler <max.koehler@ni.com>
Co-authored-by: Michael Auchter <michael.auchter@ni.com>
Co-authored-by: Paul Butler <paul.butler@ni.com>
Co-authored-by: Wade Fife <wade.fife@ettus.com>
Co-authored-by: Hector Rubio <hrubio@ni.com>


Original-commit: 6d3765605262016a80f71e36357f749ea35cbe5a
2021-06-10 11:56:58 -05:00

221 lines
8.9 KiB
VHDL

--
-- Copyright 2021 Ettus Research, a National Instruments Brand
--
-- SPDX-License-Identifier: LGPL-3.0-or-later
--
-- Module: PkgRf
--
-- Description:
--
-- This package has some type definition and functions used in the RF data
-- chain.
--
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
package PkgRf is
-- DDC sample data out width.
constant kDdcDataOutWidth : natural := 17;
-- Each sample is padded in MSB with 7 extra bits of zero to byte align.
constant kDdcDataWordWidth : natural := kDdcDataOutWidth+7;
-- DUC sample data out width.
constant kDucDataOutWidth : natural := 18;
-- Each sample is padded in MSB with 6 extra bits of zero to byte align.
constant kDucDataWordWidth : natural := kDucDataOutWidth+6;
-- Saturated data output width.
constant kSatDataWidth : natural := 16;
-- ADC sample resolution.
constant kAdcSampleRes : natural := 16;
subtype Sample18_t is signed(17 downto 0);
subtype Sample17_t is signed(16 downto 0);
subtype Sample16_t is signed(15 downto 0);
subtype Sample16slv_t is std_logic_vector(15 downto 0);
type Samples16_t is array(natural range<>) of Sample16_t;
type Samples17_t is array(natural range<>) of Sample17_t;
type Samples18_t is array(natural range<>) of Sample18_t;
-- These constants have the largest and smallest 18-bit, 17-bit, and 16-bit
-- signed values.
constant kLargest18 : Sample18_t := to_signed(2**17 - 1, 18);
constant kSmallest18 : Sample18_t := to_signed(-2**17, 18);
constant kLargest17 : Sample17_t := to_signed(2**16 - 1, 17);
constant kSmallest17 : Sample17_t := to_signed(-2**16, 17);
constant kLargest16 : Sample16_t := to_signed(2**15 - 1, 16);
constant kSmallest16 : Sample16_t := to_signed(-2**15, 16);
function Saturate(s : signed ) return Sample16_t;
function to_stdlogicvector(d : Samples16_t) return std_logic_vector;
function to_Samples16(d : std_logic_vector) return Samples16_t;
function to_Samples17(d : std_logic_vector) return Samples17_t;
function to_Samples18(d : std_logic_vector) return Samples18_t;
-- Shift the ADC sample to the left by 1 bit.
function Gain2x(d : std_logic_vector) return std_logic_vector;
function Gain2x(s : Samples16_t) return Samples16_t;
--synopsys translate_off
function tb_saturate(s: std_logic_vector) return Sample16slv_t;
--synopsys translate_on
end package PkgRf;
package body PkgRf is
-- Function to saturate any signed number greater then 16 bits.
-- A saturated 16-bit data is returned.
function Saturate ( s : signed) return Sample16_t is
begin
if s > kLargest16 then
return kLargest16;
elsif s < kSmallest16 then
return kSmallest16;
else
return resize(s, 16);
end if;
end function Saturate;
-- This function will convert 16 bit signed array into a single
-- std_logic_vector.
function to_stdlogicvector(d : Samples16_t) return std_logic_vector is
-- This alias is used to normalize the input vector to [d'length-1 downto 0]
alias normalD : Samples16_t(d'length-1 downto 0) is d;
variable rval : std_logic_vector(d'length * 16 - 1 downto 0);
constant dataWidth : natural := Sample16_t'length;
begin
for i in normalD'range loop
rval(i*dataWidth + dataWidth-1 downto i*dataWidth)
:= std_logic_vector(normalD(i));
end loop;
return rval;
end function to_stdlogicvector;
-- This function will convert a std_logic_vector into an array of 18 bit
-- signed array. The input std_logic_vector has data packed in 24 bits. But
-- only 18 bits has valid data and remaining 6 MSB bits are padded with
-- zeros.
function to_Samples18(d : std_logic_vector) return Samples18_t is
-- This alias is used to normalize the input vector to [d'length-1 downto 0]
alias normalD : std_logic_vector(d'length-1 downto 0) is d;
variable rval : Samples18_t(d'length / kDucDataWordWidth - 1 downto 0);
begin
--synopsys translate_off
assert (((d'length) mod kDucDataWordWidth) = 0)
report "Input to the function to_Samples18 must be a multiple of kDucDataWordWidth"
severity error;
--synopsys translate_on
for i in rval'range loop
rval(i) := Sample18_t(normalD(i*kDucDataWordWidth + Sample18_t'length-1
downto i*kDucDataWordWidth));
end loop;
return rval;
end function to_Samples18;
-- This function will convert a std_logic_vector into an array of 16 bit
-- signed array. The input std_logic_vector has data packed in 16 bits. But
-- only 15 bits has valid data and the uper two bits only have the signed
-- bit.
function to_Samples16(d : std_logic_vector) return Samples16_t is
-- This alias is used to normalize the input vector to [d'length-1 downto 0]
alias normalD : std_logic_vector(d'length-1 downto 0) is d;
variable rval : Samples16_t(d'length / kAdcSampleRes - 1 downto 0);
begin
--synopsys translate_off
assert (((d'length) mod kAdcSampleRes) = 0)
report "Input to the function to_Samples16 must be a multiple of kAdcSampleRes"
severity error;
--synopsys translate_on
for i in rval'range loop
rval(i) := Sample16_t(normalD(i*kAdcSampleRes + Sample16_t'length-1
downto i*kAdcSampleRes));
end loop;
return rval;
end function to_Samples16;
-- This function will convert a std_logic_vector into an array of 19 bit
-- signed array. The input std_logic_vector has data packed in 24 bits. But
-- only 17 bits has valid data and remaining 7 MSB bits are padded with
-- zeros.
function to_Samples17(d : std_logic_vector) return Samples17_t is
-- This alias is used to normalize the input vector to [d'length-1 downto 0]
alias normalD : std_logic_vector(d'length-1 downto 0) is d;
variable rval : Samples17_t(d'length / kDdcDataWordWidth - 1 downto 0);
begin
--synopsys translate_off
assert (((d'length) mod kDdcDataWordWidth) = 0)
report "Input to the function to_Samples17 must be a multiple of kDdcDataWordWidth"
severity error;
--synopsys translate_on
for i in rval'range loop
rval(i) := Sample17_t(normalD(i*kDdcDataWordWidth + Sample17_t'length-1
downto i*kDdcDataWordWidth));
end loop;
return rval;
end function to_Samples17;
-- Function to shift the sample to the left by one bit and effectively
-- multiply by 2.
function Gain2x(s : Samples16_t) return Samples16_t is
variable rval : Samples16_t(s'range);
begin
for i in rval'range loop
rval(i) := s(i)(kAdcSampleRes-2 downto 0) & '0';
end loop;
return rval;
end function Gain2x;
function Gain2x (d : std_logic_vector) return std_logic_vector is
begin
return to_stdlogicvector(Gain2x(to_Samples16(d)));
end function;
--synopsys translate_off
---------------------------------------------------------------
-- Function below this comment is used only for testbench.
---------------------------------------------------------------
-- This function does saturation of a signed number in std_logic_vector data
-- type. The current implementation supports only 17 or 18 bit signed
-- number.
function tb_saturate(s: std_logic_vector) return Sample16slv_t is
-- This alias is used to normalize the input vector to [s'length-1 downto 0]
alias normalS : std_logic_vector(s'length-1 downto 0) is s;
variable rval : Sample16slv_t;
constant len : integer := s'length;
begin
-- If 2 MSBs = 00, output <= input without MSB, e.g. positive number < 1
-- If 2 MSBs = 01, output <= 0.111111111111111, e.g. positive number >= 1
-- If 2 MSBs = 10, output <= 1.000000000000000, e.g. negative number < -1
-- If 2 MSBs = 11, output <= input without MSB, e.g. negative number >= -1
if len = kDdcDataOutWidth then
if normalS(len-1 downto len-2) = "01" then
rval := "0111111111111111";
elsif normalS(len-1 downto len-2) = "10" then
rval := "1000000000000000";
else
rval := normalS(len-2 downto 0);
end if;
-- If 3 MSBs = 000, output <= input without MSB, e.g. positive number < 1
-- If 3 MSBs = 0x1/01x, output <= 0.111111111111111, e.g. positive number >= 1
-- If 3 MSBs = 1x0/10x, output <= 1.000000000000000, e.g. negative number < -1
-- If 3 MSBs = 111, output <= input without MSB, e.g. negative number >= -1
else -- len = kDucDataOutWidth
if normalS(len-1) = '0' and normalS(len-2 downto len-3) /= "00" then
rval := "0111111111111111";
elsif (normalS(len-1 downto len-3) = "000") or
(normalS(len-1 downto len-3) = "111") then
rval := normalS(len-3 downto 0);
else
rval := "1000000000000000";
end if;
end if;
return rval;
end function tb_saturate;
--synopsys translate_on
end package body;