1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
|
--
-- 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;
|