├── LICENSE
├── README.md
├── fpga
├── common
│ └── wlan_files.tcl
├── ip
│ ├── altera
│ │ ├── fft64
│ │ │ ├── fft64.qsys
│ │ │ └── generate.sh
│ │ ├── viterbi_decoder
│ │ │ ├── generate.sh
│ │ │ └── viterbi_decoder.qsys
│ │ └── wlan_pll
│ │ │ └── generate.sh
│ ├── generate.sh
│ └── nuand
│ │ ├── cordic.vhd
│ │ ├── fft
│ │ ├── model
│ │ │ ├── Makefile
│ │ │ ├── dft.c
│ │ │ └── idft.c
│ │ └── vhdl
│ │ │ ├── dual_port_ram.vhd
│ │ │ ├── fft.vhd
│ │ │ ├── fft_top.vhd
│ │ │ └── tb
│ │ │ ├── compile.do
│ │ │ └── fft_tb.vhd
│ │ ├── nco.vhd
│ │ └── viterbi_decoder
│ │ ├── model
│ │ ├── encoder.c
│ │ └── out.c
│ │ └── vhdl
│ │ ├── branch_compare.vhd
│ │ ├── comp2.vhd
│ │ ├── r2_comparator.vhd
│ │ ├── tb
│ │ ├── compile.do
│ │ ├── r2_comparator_tb.vhd
│ │ ├── viterbi_decoder_tb.vhd
│ │ └── wave.do
│ │ ├── traceback.vhd
│ │ ├── tracer.vhd
│ │ ├── viterbi_decoder.vhd
│ │ └── viterbi_p.vhd
├── modelsim
│ └── wlan.do
├── quartus
│ └── wlan.qip
└── vhdl
│ ├── clock_sync_logic.vhd
│ ├── clock_sync_logic_vector.vhd
│ ├── clock_sync_params.vhd
│ ├── tb
│ ├── wlan_ack_generator_tb.vhd
│ ├── wlan_acquisition_tb.vhd
│ ├── wlan_bsd_tb.vhd
│ ├── wlan_channel_inverter_tb.vhd
│ ├── wlan_clock_tb.vhd
│ ├── wlan_dsss_plcp_crc_tb.vhd
│ ├── wlan_interleaver_tb.vhd
│ ├── wlan_lfsr_tb.vhd
│ ├── wlan_modulator_tb.vhd
│ ├── wlan_peak_finder_tb.vhd
│ ├── wlan_rx_tb.vhd
│ ├── wlan_sample_loader.vhd
│ ├── wlan_sample_saver.vhd
│ ├── wlan_symbol_shaper_tb.vhd
│ ├── wlan_tables_p.vhd
│ ├── wlan_tb.vhd
│ ├── wlan_top_tb.vhd
│ ├── wlan_tx_long_tb.vhd
│ ├── wlan_tx_short_tb.vhd
│ ├── wlan_tx_tb.vhd
│ ├── wlan_viterbi_encoder_tb.vhd
│ └── wlan_viterbi_tb.vhd
│ ├── wlan_ack_generator.vhd
│ ├── wlan_acquisition.vhd
│ ├── wlan_agc.vhd
│ ├── wlan_agc_drv.vhd
│ ├── wlan_bsd.vhd
│ ├── wlan_cfo_correction.vhd
│ ├── wlan_cfo_estimate.vhd
│ ├── wlan_channel_inverter.vhd
│ ├── wlan_clamper.vhd
│ ├── wlan_correlator.vhd
│ ├── wlan_crc.vhd
│ ├── wlan_csma.vhd
│ ├── wlan_dcf.vhd
│ ├── wlan_deinterleaver.vhd
│ ├── wlan_delay_correlator.vhd
│ ├── wlan_demodulator.vhd
│ ├── wlan_depuncturer.vhd
│ ├── wlan_descrambler.vhd
│ ├── wlan_divide.vhd
│ ├── wlan_dsss_demodulator.vhd
│ ├── wlan_dsss_despreader.vhd
│ ├── wlan_dsss_p_norm.vhd
│ ├── wlan_dsss_peak_finder.vhd
│ ├── wlan_dsss_plcp_crc.vhd
│ ├── wlan_dsss_rx.vhd
│ ├── wlan_dsss_rx_controller.vhd
│ ├── wlan_dsss_rx_framer.vhd
│ ├── wlan_encoder.vhd
│ ├── wlan_equalizer.vhd
│ ├── wlan_fft64.vhd
│ ├── wlan_framer.vhd
│ ├── wlan_ifft64.vhd
│ ├── wlan_interleaver.vhd
│ ├── wlan_interleaver_p.vhd
│ ├── wlan_lfsr.vhd
│ ├── wlan_modulator.vhd
│ ├── wlan_p.vhd
│ ├── wlan_p_norm.vhd
│ ├── wlan_peak_finder.vhd
│ ├── wlan_phase_correction.vhd
│ ├── wlan_rx.vhd
│ ├── wlan_rx_controller.vhd
│ ├── wlan_rx_framer.vhd
│ ├── wlan_rx_p.vhd
│ ├── wlan_rx_packet_buffer.vhd
│ ├── wlan_sample_buffer.vhd
│ ├── wlan_scrambler.vhd
│ ├── wlan_symbol_shaper.vhd
│ ├── wlan_top.vhd
│ ├── wlan_tx.vhd
│ ├── wlan_tx_controller.vhd
│ ├── wlan_tx_long.vhd
│ ├── wlan_tx_p.vhd
│ ├── wlan_tx_short.vhd
│ ├── wlan_viterbi_decoder.vhd
│ └── wlan_viterbi_encoder.vhd
└── matlab
├── util.m
└── wlan_rx.m
/README.md:
--------------------------------------------------------------------------------
1 | # bladeRF-wiphy
2 |
3 | bladeRF-wiphy is an open-source IEEE 802.11 compatible software defined radio VHDL modem
4 |
5 |
6 |
7 | ## What is the bladeRF-wiphy project?
8 | The bladeRF-wiphy project is an open-source IEEE 802.11 compatible software defined radio VHDL modem. The modem is able to modulate and demodulate 802.11 packets (the protocol WiFi is based on), and run directly on the bladeRF 2.0 micro xA9’s FPGA.
9 |
10 | The bladeRF-wiphy coupled with Linux mac80211 allows the [bladeRF 2.0 micro xA9](https://www.nuand.com/product/bladerf-xA9/) to become a software defined radio 802.11 access point! 802.11 packets (PDUs) are modulated and demodulated directly on the FPGA, so only 802.11 packets are transferred between the FPGA and libbladeRF.
11 |
12 | ## Documentation
13 | A technical deep dive of bladeRF-wiphy https://www.nuand.com/bladeRF-wiphy/
14 |
15 | Instructions to compile, install, and run bladeRF-wiphy and tools https://www.nuand.com/bladeRF-wiphy-instructions/
16 |
17 | Instructions to simulate bladeRF-wiphy: https://www.nuand.com/bladeRF-wiphy-simulation/
18 |
19 |
20 |
21 |
22 |
23 | ## Features
24 | - IEEE 802.11 compatible FPGA based PHY receiver and transmitter
25 | - Compatible with [bladeRF 2.0 micro xA9](https://www.nuand.com/product/bladerf-xA9/)
26 | - Linux mac80211 MAC integration
27 | - RX and TX monitor mode support
28 | - Hardware Distributed Coordination Function (DCF) allows quick turn-around time ACKs
29 | - High-performance equalizer – implements Zero Forcing (ZF) and optionally Decision Feedback Equalizer (DFE)
30 |
31 | ## Modulation schemes
32 | - DSSS - CCK
33 | - OFDM - 20MHz (6Mbps, 9Mbps, 12Mbps, 18Mbps, 24Mbps, 36Mbps, 48Mbps, 54Mbps)
34 |
35 | ## Modulation constellations
36 | - DSSS-CCK DBPSK
37 | - OFDM-BPSK
38 | - OFDM-QPSK
39 | - OFDM-16-QAM
40 | - OFDM-64-QAM
41 |
42 | ## Contact information
43 | Email: bladeRF@nuand.com
44 |
45 | Slack: See Slack section on this [page](https://www.nuand.com/support/)
46 |
--------------------------------------------------------------------------------
/fpga/ip/altera/fft64/fft64.qsys:
--------------------------------------------------------------------------------
1 |
2 |
3 |
10 |
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 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
--------------------------------------------------------------------------------
/fpga/ip/altera/fft64/generate.sh:
--------------------------------------------------------------------------------
1 | qsys-generate --sim --synthesis=VHDL ./fft64.qsys
2 |
--------------------------------------------------------------------------------
/fpga/ip/altera/viterbi_decoder/generate.sh:
--------------------------------------------------------------------------------
1 | qsys-generate --sim --synthesis=VHDL viterbi_decoder.qsys
2 |
--------------------------------------------------------------------------------
/fpga/ip/altera/viterbi_decoder/viterbi_decoder.qsys:
--------------------------------------------------------------------------------
1 |
2 |
3 |
10 |
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 |
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 |
--------------------------------------------------------------------------------
/fpga/ip/altera/wlan_pll/generate.sh:
--------------------------------------------------------------------------------
1 | ip-generate --file-set=QUARTUS_SYNTH --component-name=altera_pll --output-name=wlan_pll \
2 | --component-param=gui_reference_clock_frequency="40MHz" \
3 | --component-param=gui_output_clock_frequency0="80MHz" \
4 | --component-param=gui_phase_shift0="0ps" \
5 | --component-param=gui_duty_cycle0="50%"
6 |
--------------------------------------------------------------------------------
/fpga/ip/generate.sh:
--------------------------------------------------------------------------------
1 | for i in */*/generate.sh; do echo "Running $i"; (cd `dirname $i`; sh generate.sh); done
2 |
--------------------------------------------------------------------------------
/fpga/ip/nuand/fft/model/Makefile:
--------------------------------------------------------------------------------
1 | all: dft idft
2 |
3 | dft: dft.c
4 | gcc -o dft dft.c -g3 -lm
5 |
6 | idft: idft.c
7 | gcc -o idft idft.c -g3 -lm
8 |
--------------------------------------------------------------------------------
/fpga/ip/nuand/fft/model/dft.c:
--------------------------------------------------------------------------------
1 | // This file is part of bladeRF-wiphy.
2 | //
3 | // Copyright (C) 2021 Nuand, LLC.
4 | //
5 | // This program is free software; you can redistribute it and/or modify
6 | // it under the terms of the GNU General Public License as published by
7 | // the Free Software Foundation; either version 2 of the License, or
8 | // (at your option) any later version.
9 | //
10 | // This program is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | // GNU General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU General Public License along
16 | // with this program; if not, write to the Free Software Foundation, Inc.,
17 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 |
19 | #include
20 | #include
21 |
22 |
23 | int flip_bits(unsigned in, int bits) {
24 | unsigned ret = 0;
25 | int i;
26 | for (i = 0; i < bits; i++) {
27 | ret |= ( !!(in & (1 << i)) ) << (bits - i - 1);
28 | }
29 | printf("IN %d, OUT %d\n", in, ret);
30 | return ret;
31 | }
32 |
33 | unsigned rotate_left(unsigned in, int width, int num) {
34 | unsigned ret = 0;
35 | unsigned bottom = 0;
36 | unsigned mask = 0;
37 | bottom = in;
38 | //printf("#1 = %d\n", bottom);
39 | bottom >>= (width - num);
40 | //printf("#2 = %d\n", bottom);
41 | mask = ((1 << (num+1)) - 1);
42 | //printf("mask = %d\n", mask);
43 | bottom &= mask;
44 | //printf("BOTTOM = %d\n", bottom);
45 |
46 | ret = in;
47 | ret <<= num;
48 | ret = ret & ((1 << width) - 1);
49 | //printf("TOP = %d\n", ret);
50 |
51 | ret |= bottom;
52 | return(ret);
53 | }
54 |
55 | struct c_sample {
56 | float i, q;
57 | };
58 |
59 | #define N 64
60 | #define N_POW 6
61 | #define FMT "%f"
62 |
63 | struct c_sample rfs_i[] = {
64 | { 402, 750}, { -439, 700}, { 909, -96}, {-7, -496}, {76, -711}, {764, 601}, {-192, 315}, {411, -633},
65 | {-540, -139}, {-360, -640}, {821, -172}, {160, 291}, {9, -678}, {-679, -241}, {69, -293}, {565, -172},
66 | {-356, 999}, {515, -19}, {438, -498}, {78, 693}, {-276, 209}, {-865, 131}, {465, 487}, {454, 35},
67 | {-480, 437}, {-324, -45}, {-86, -991}, {-471, 2}, {-805, -38}, {543, -621}, {170, 397}, {-797, 606},
68 | {546, 369}, {150, 591}, {-1095, -17}, {109, -684}, {760, -450}, {-573, -478}, {-66, -409}, {682, 484},
69 | {-862, 201}, {-695, -192}, {16, 819}, {-403, 172}, {-342, -660}, {443, 14}, {544, -389}, {-734, -339},
70 | {-366, -141}, {381, -626}, {280, 382}, {624, 235}, {-218, 980}, {333, 54}, {333, 506}, {-944, 114},
71 | {46, 566}, {305, -48}, {457, -20}, {-56, 740}, {-919, 197}, {522, 295}, {-2, 20}, {438, -712}
72 | };
73 |
74 | void gen_sample(int n, struct c_sample *ptr) {
75 | int r, idx;
76 | for (r = 0; r < n; r++) {
77 | idx = flip_bits(r, N_POW);
78 | ptr[idx] = rfs_i[r];
79 | printf("Wrote %d to c[%d] = " FMT " + j*" FMT "\n", r, idx, ptr[idx].i, ptr[idx].q);
80 | }
81 | }
82 |
83 | void butter_fly(struct c_sample *A, struct c_sample *B, struct c_sample *TW)
84 | {
85 | struct c_sample mix, t_A, t_B;
86 | // A = a_i + j * a_q
87 | // B = b_i + j * b_q
88 |
89 | // C = A X B = (a_i * b_i + a_i * j * b_q + j * a_q * b_i + j * a_q * j * b_q)
90 | // C = ( a_i * b_i - a_q * b_q) + j ( a_i * b_q + a_q + b_i )
91 | // C_i = a_i * b_i - a_q * b_q
92 | // C_q = a_i * b_q + a_q * b_i
93 |
94 |
95 | mix.i = (B->i * TW->i - B->q * TW->q) /(32768);//>> 15;
96 | mix.q = (B->i * TW->q + B->q * TW->i) /(32768);//>> 15;
97 |
98 | //A->i *= 1;
99 | //A->q *= 1;
100 | //B->i *= 1;
101 | //B->q *= 1;
102 |
103 | t_A.i = A->i + mix.i;
104 | t_A.q = A->q + mix.q;
105 |
106 | t_B.i = A->i - mix.i;
107 | t_B.q = A->q - mix.q;
108 |
109 | printf("A: " FMT " + j* " FMT " B: " FMT " + j* " FMT " TW: " FMT " + j* " FMT "\n", A->i, A->q, B->i, B->q, TW->i, TW->q);
110 | printf("mix: " FMT " + j* " FMT "\n", mix.i, mix.q);
111 |
112 | *A = t_A;
113 | *B = t_B;
114 | printf("A: " FMT " + j* " FMT " B: " FMT " + j* " FMT "\n\n", A->i, A->q, B->i, B->q);
115 | }
116 |
117 |
118 | int W_i[N/2];
119 | int W_q[N/2];
120 | int main() {
121 | float ti, tq;
122 | int i, j;
123 | struct c_sample s_a[N], s_b[N], s_tw[N];
124 | gen_sample(N, s_a);
125 |
126 | #if 0
127 | for (i = 0; i < (N);i++) {
128 | printf("[%d] = " FMT " " FMT "\n", i, s_a[i].i, s_a[i].q);
129 | }
130 | #endif
131 | /*
132 | for (i = 0; i < (N/2);i++) {
133 | printf("%Lf, %Lf\n", sinl((2.0 * M_PI * (float)i) / N), cosl((2.0 * M_PI * (float)i) / N));
134 | }
135 | */
136 |
137 | for (i = 0; i < (N/2); i++) {
138 | ti = cosf((2.0 * M_PI * (float)i) / (float)N);
139 | s_tw[i].i = W_i[i] = ti * ((1<<15)-1);
140 | tq = sinf((2.0 * M_PI * (float)i) / (float)N);
141 | s_tw[i].q = W_q[i] = tq * ((1<<15)-1);
142 |
143 |
144 | printf("[%.2d] I= %.15f = 0x%.8x Q= %.15f = 0x%.8x\t\t" FMT ", " FMT "\n", i, ti, W_i[i], tq, W_q[i], s_tw[i].i, s_tw[i].q);
145 | }
146 |
147 | for (i = 0; i < N_POW; i++) {
148 | for (j = 0; j < (N/2); j++) {
149 | int a, b, tw;
150 | a = rotate_left(j * 2, N_POW, i);
151 | b = rotate_left(j * 2 + 1, N_POW, i);
152 | //tw = (j & ((1<< (i)) - 1)) << (N_POW-1-i); DIF
153 | tw = (j ) & ((1 << (N_POW - 1)) - 1) - ((1 << (N_POW - 1 - i)) -1);
154 |
155 | printf("Stage=%d A=%d,%d tw=%d\n", i, a, b, tw);
156 | if ( i == 0) {
157 | printf("\t%d,%d => A is timeidx = %d, B is timeidx = %d\n", a,b, flip_bits(a, N_POW), flip_bits(b, N_POW));
158 | }
159 | butter_fly(s_a + a, s_a + b, s_tw + tw );
160 |
161 | }
162 | printf("\n\n");
163 | }
164 |
165 | for (i = 0; i < N; i++) {
166 | printf("[%.2d] = " FMT " + j * " FMT "\n", i, s_a[i].i, s_a[i].q);
167 | }
168 | printf("\n\n");
169 | for (i = 0; i < N; i++) {
170 | printf("[%.2d] = %f\n", i, sqrt(s_a[i].i * s_a[i].i + s_a[i].q * s_a[i].q));
171 | }
172 | return 0;
173 | }
174 |
--------------------------------------------------------------------------------
/fpga/ip/nuand/fft/model/idft.c:
--------------------------------------------------------------------------------
1 | // This file is part of bladeRF-wiphy.
2 | //
3 | // Copyright (C) 2021 Nuand, LLC.
4 | //
5 | // This program is free software; you can redistribute it and/or modify
6 | // it under the terms of the GNU General Public License as published by
7 | // the Free Software Foundation; either version 2 of the License, or
8 | // (at your option) any later version.
9 | //
10 | // This program is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | // GNU General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU General Public License along
16 | // with this program; if not, write to the Free Software Foundation, Inc.,
17 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 |
19 | #include
20 | #include
21 |
22 |
23 | int flip_bits(unsigned in, int bits) {
24 | unsigned ret = 0;
25 | int i;
26 | for (i = 0; i < bits; i++) {
27 | ret |= ( !!(in & (1 << i)) ) << (bits - i - 1);
28 | }
29 | printf("IN %d, OUT %d\n", in, ret);
30 | return ret;
31 | }
32 |
33 | int f_s[]= {
34 | 0, 1, -1, -1, -1, 1, -1, 1, -1, -1, -1, 1, 1, -1, -1, 1, -1, 1, 1, -1, -1, -1, -1, -1, 1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, -1, 1, 1, 1, -1, 1, 1, -1, -1, -1, -1, 1, -1, -1, -1, -1, -1, 1, 1, -1, -1, 1, 1, -1 };
35 |
36 | unsigned rotate_left(unsigned in, int width, int num) {
37 | unsigned ret = 0;
38 | unsigned bottom = 0;
39 | unsigned mask = 0;
40 | bottom = in;
41 | //printf("#1 = %d\n", bottom);
42 | bottom >>= (width - num);
43 | //printf("#2 = %d\n", bottom);
44 | mask = ((1 << (num+1)) - 1);
45 | //printf("mask = %d\n", mask);
46 | bottom &= mask;
47 | //printf("BOTTOM = %d\n", bottom);
48 |
49 | ret = in;
50 | ret <<= num;
51 | ret = ret & ((1 << width) - 1);
52 | //printf("TOP = %d\n", ret);
53 |
54 | ret |= bottom;
55 | return(ret);
56 | }
57 |
58 | struct c_sample {
59 | long long int i, q;
60 | };
61 |
62 | #define N 64
63 | #define N_POW 6
64 | #define FMT "%lld"
65 |
66 | void gen_sample(int n, struct c_sample *ptr) {
67 | int r, idx;
68 | for (r = 0; r < n; r++) {
69 | idx = flip_bits(r, N_POW);
70 | ptr[idx].i = f_s[r] * 4096;
71 | ptr[idx].q = 0;
72 | printf("Wrote %d to c[%d] = " FMT " + j*" FMT "\n", r, idx, ptr[idx].i, ptr[idx].q);
73 | }
74 | }
75 |
76 | void butter_fly(struct c_sample *A, struct c_sample *B, struct c_sample *TW)
77 | {
78 | struct c_sample mix, t_A, t_B;
79 | // A = a_i + j * a_q
80 | // B = b_i + j * b_q
81 |
82 | // C = A X B = (a_i * b_i + a_i * j * b_q + j * a_q * b_i + j * a_q * j * b_q)
83 | // C = ( a_i * b_i - a_q * b_q) + j ( a_i * b_q + a_q + b_i )
84 | // C_i = a_i * b_i - a_q * b_q
85 | // C_q = a_i * b_q + a_q * b_i
86 |
87 |
88 | mix.i = (B->i * TW->i - B->q * TW->q) >> 15;
89 | mix.q = (B->i * TW->q + B->q * TW->i) >> 15;
90 |
91 | //A->i *= 1;
92 | //A->q *= 1;
93 | //B->i *= 1;
94 | //B->q *= 1;
95 |
96 | t_A.i = A->i + mix.i;
97 | t_A.q = A->q + mix.q;
98 |
99 | t_B.i = A->i - mix.i;
100 | t_B.q = A->q - mix.q;
101 |
102 | printf("A: " FMT " + j* " FMT " B: " FMT " + j* " FMT " TW: " FMT " + j* " FMT "\n", A->i, A->q, B->i, B->q, TW->i, TW->q);
103 | printf("mix: " FMT " + j* " FMT "\n", mix.i, mix.q);
104 |
105 | *A = t_A;
106 | *B = t_B;
107 | printf("A: " FMT " + j* " FMT " B: " FMT " + j* " FMT "\n\n", A->i, A->q, B->i, B->q);
108 | }
109 |
110 |
111 | int W_i[N/2];
112 | int W_q[N/2];
113 | int main() {
114 | float ti, tq;
115 | int i, j;
116 | struct c_sample s_a[N], s_b[N], s_tw[N];
117 | gen_sample(N, s_a);
118 |
119 | #if 0
120 | for (i = 0; i < (N);i++) {
121 | printf("[%d] = " FMT " " FMT "\n", i, s_a[i].i, s_a[i].q);
122 | }
123 | #endif
124 | /*
125 | for (i = 0; i < (N/2);i++) {
126 | printf("%Lf, %Lf\n", sinl((2.0 * M_PI * (float)i) / N), cosl((2.0 * M_PI * (float)i) / N));
127 | }
128 | */
129 |
130 | for (i = 0; i < (N/2); i++) {
131 | ti = cosf((2.0 * M_PI * (float)i) / (float)N);
132 | s_tw[i].i = W_i[i] = ti * ((1<<15)-1);
133 | tq = sinf((2.0 * M_PI * (float)i) / (float)N);
134 | s_tw[i].q = W_q[i] = tq * ((1<<15)-1);
135 |
136 |
137 | printf("[%.2d] I= %.15f = 0x%.8x Q= %.15f = 0x%.8x\t\t" FMT ", " FMT "\n", i, ti, W_i[i], tq, W_q[i], s_tw[i].i, s_tw[i].q);
138 | }
139 |
140 | for (i = 0; i < N_POW; i++) {
141 | for (j = 0; j < (N/2); j++) {
142 | int a, b, tw;
143 | a = rotate_left(j * 2, N_POW, i);
144 | b = rotate_left(j * 2 + 1, N_POW, i);
145 | //tw = (j & ((1<< (i)) - 1)) << (N_POW-1-i); DIF
146 | tw = (j) & ((1 << (N_POW - 1)) - 1) - ((1 << (N_POW - 1 - i)) -1);
147 |
148 | printf("Stage=%d A=%d,%d tw=%d\n", i, a, b, tw);
149 | if (i == 0) {
150 | printf("\t%d,%d => A is timeidx = %d, B is timeidx = %d\n", a,b, flip_bits(a, N_POW), flip_bits(b, N_POW));
151 | }
152 | butter_fly(s_a + a, s_a + b, s_tw + tw );
153 |
154 | }
155 | printf("\n\n");
156 | }
157 |
158 | for (i = 0; i < N; i++) {
159 | printf("[%.2d] = " FMT " + j * " FMT "\n", i, s_a[i].i/64, s_a[i].q/64);
160 | }
161 | printf("\n\n");
162 | for (i = 0; i < N; i++) {
163 | printf("[%.2d] = %f\n", i, sqrt(s_a[i].i * s_a[i].i + s_a[i].q * s_a[i].q));
164 | }
165 | return 0;
166 | }
167 |
--------------------------------------------------------------------------------
/fpga/ip/nuand/fft/vhdl/dual_port_ram.vhd:
--------------------------------------------------------------------------------
1 | -- This file is part of bladeRF-wiphy.
2 | --
3 | -- Copyright (C) 2021 Nuand, LLC.
4 | --
5 | -- This program is free software; you can redistribute it and/or modify
6 | -- it under the terms of the GNU General Public License as published by
7 | -- the Free Software Foundation; either version 2 of the License, or
8 | -- (at your option) any later version.
9 | --
10 | -- This program is distributed in the hope that it will be useful,
11 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | -- GNU General Public License for more details.
14 | --
15 | -- You should have received a copy of the GNU General Public License along
16 | -- with this program; if not, write to the Free Software Foundation, Inc.,
17 | -- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 |
19 | library ieee;
20 | use ieee.std_logic_1164.all;
21 | use ieee.numeric_std.all;
22 |
23 | entity dual_port_ram is
24 | generic(
25 | ADDR_BITS : in natural := 6;
26 | DATA_BITS : in natural := 32
27 | );
28 | port(
29 | clock : in std_logic;
30 | reset : in std_logic;
31 |
32 | acc : in std_logic;
33 | solo : in std_logic;
34 | write : in std_logic;
35 |
36 | addr_a : in std_logic_vector(ADDR_BITS-1 downto 0);
37 | in_a : in std_logic_vector(DATA_BITS-1 downto 0);
38 | data_a : out std_logic_vector(DATA_BITS-1 downto 0);
39 |
40 | addr_b : in std_logic_vector(ADDR_BITS-1 downto 0);
41 | in_b : in std_logic_vector(DATA_BITS-1 downto 0);
42 | data_b : out std_logic_vector(DATA_BITS-1 downto 0)
43 | );
44 | end entity;
45 |
46 | architecture arch of dual_port_ram is
47 | type ram_t is array(natural range <>) of std_logic_vector(DATA_BITS-1 downto 0);
48 |
49 | signal ram : ram_t((2**ADDR_BITS-1) downto 0);
50 | begin
51 | sync : process(clock, reset)
52 | variable add_a, add_b : integer;
53 | begin
54 | if (reset = '1') then
55 | for i in ram'range loop
56 | ram(i) <= ( others => '0' );
57 | end loop;
58 | elsif (rising_edge(clock)) then
59 | if (acc = '1') then
60 | add_a := to_integer(unsigned(addr_a));
61 | add_b := to_integer(unsigned(addr_b));
62 |
63 | if (write = '1') then
64 | ram(add_a) <= in_a;
65 | data_a <= in_a;
66 | if (solo = '0') then
67 | ram(add_b) <= in_b;
68 | data_b <= in_b;
69 | else
70 | data_b <= ( others => '0' );
71 | end if;
72 | else
73 | data_a <= ram(add_a);
74 | if (solo = '0') then
75 | data_b <= ram(add_b);
76 | else
77 | data_b <= ( others => '0' );
78 | end if;
79 | end if;
80 | end if;
81 |
82 | end if;
83 | end process;
84 | end architecture;
85 |
86 | architecture synth of dual_port_ram is
87 | type ram_t is array(natural range <>) of std_logic_vector(DATA_BITS-1 downto 0);
88 |
89 | shared variable ram : ram_t((2**ADDR_BITS-1) downto 0);
90 | begin
91 | synca : process(clock, reset)
92 | variable addra : integer;
93 | begin
94 | if (rising_edge(clock)) then
95 | addra := to_integer(unsigned(addr_a));
96 | if (write = '1') then
97 | ram(addra) := in_a;
98 | end if;
99 | data_a <= ram(addra);
100 | end if;
101 | end process;
102 |
103 | syncb : process(clock, reset)
104 | variable addrb : integer;
105 | begin
106 | if (rising_edge(clock)) then
107 | addrb := to_integer(unsigned(addr_b));
108 | if (write = '1') then
109 | ram(addrb) := in_b;
110 | end if;
111 | data_b <= ram(addrb);
112 | end if;
113 | end process;
114 | end architecture synth;
115 |
--------------------------------------------------------------------------------
/fpga/ip/nuand/fft/vhdl/fft_top.vhd:
--------------------------------------------------------------------------------
1 | -- This file is part of bladeRF-wiphy.
2 | --
3 | -- Copyright (C) 2021 Nuand, LLC.
4 | --
5 | -- This program is free software; you can redistribute it and/or modify
6 | -- it under the terms of the GNU General Public License as published by
7 | -- the Free Software Foundation; either version 2 of the License, or
8 | -- (at your option) any later version.
9 | --
10 | -- This program is distributed in the hope that it will be useful,
11 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | -- GNU General Public License for more details.
14 | --
15 | -- You should have received a copy of the GNU General Public License along
16 | -- with this program; if not, write to the Free Software Foundation, Inc.,
17 | -- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 |
19 | library ieee;
20 | use ieee.std_logic_1164.all;
21 | use ieee.numeric_std.all;
22 | use ieee.math_real.all;
23 | library pll;
24 | use pll.all;
25 | entity fft_top is
26 | generic(
27 | BITS : in natural := 16
28 | );
29 | port(
30 | clk : in std_logic;
31 | reset : in std_logic;
32 |
33 | inverse : in std_logic;
34 | in_real : in std_logic_vector(BITS-1 downto 0);
35 | in_imag : in std_logic_vector(BITS-1 downto 0);
36 | in_valid : in std_logic;
37 | in_sop : in std_logic;
38 | in_eop : in std_logic;
39 |
40 | out_real : out std_logic_vector(BITS-1 downto 0);
41 | out_imag : out std_logic_vector(BITS-1 downto 0);
42 | out_error : out std_logic;
43 | out_valid : out std_logic;
44 | out_sop : out std_logic;
45 | out_eop : out std_logic
46 | );
47 | end entity;
48 |
49 | architecture arch of fft_top is
50 | signal clock : std_logic;
51 | begin
52 |
53 | U_pll : entity pll.pll
54 | port map(
55 | refclk => clk,
56 | rst => '0',
57 | outclk_0 => clock,
58 | locked => open
59 | );
60 |
61 | U_fft : entity work.fft(mult)
62 | generic map(
63 | N => 64,
64 | BITS => 16
65 | )
66 | port map(
67 | clock => clock,
68 | reset => reset,
69 |
70 | inverse => inverse,
71 | in_real => in_real,
72 | in_imag => in_imag,
73 | in_valid => in_valid,
74 | in_sop => in_sop,
75 | in_eop => in_eop,
76 |
77 | out_real => out_real,
78 | out_imag => out_imag,
79 | out_error => out_error,
80 | out_valid => out_valid,
81 | out_sop => out_sop,
82 | out_eop => out_eop
83 | );
84 |
85 |
86 |
87 | end architecture;
88 |
--------------------------------------------------------------------------------
/fpga/ip/nuand/fft/vhdl/tb/compile.do:
--------------------------------------------------------------------------------
1 | vcom -work work -2008 ../dual_port_ram.vhd
2 | vcom -work work -2008 ../fft.vhd
3 | vcom -work work -2008 fft_tb.vhd
4 |
--------------------------------------------------------------------------------
/fpga/ip/nuand/fft/vhdl/tb/fft_tb.vhd:
--------------------------------------------------------------------------------
1 | -- This file is part of bladeRF-wiphy.
2 | --
3 | -- Copyright (C) 2021 Nuand, LLC.
4 | --
5 | -- This program is free software; you can redistribute it and/or modify
6 | -- it under the terms of the GNU General Public License as published by
7 | -- the Free Software Foundation; either version 2 of the License, or
8 | -- (at your option) any later version.
9 | --
10 | -- This program is distributed in the hope that it will be useful,
11 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | -- GNU General Public License for more details.
14 | --
15 | -- You should have received a copy of the GNU General Public License along
16 | -- with this program; if not, write to the Free Software Foundation, Inc.,
17 | -- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 |
19 | library ieee;
20 | use ieee.std_logic_1164.all;
21 | use ieee.numeric_std.all;
22 |
23 | entity fft_tb is
24 | end entity;
25 |
26 | architecture arch of fft_tb is
27 | signal clock : std_logic := '0';
28 | signal reset : std_logic;
29 |
30 | signal in_real : std_logic_vector(15 downto 0);
31 | signal in_imag : std_logic_vector(15 downto 0);
32 | signal in_valid : std_logic;
33 | signal in_sop : std_logic;
34 | signal in_eop : std_logic;
35 |
36 | type lut_t is array(natural range <>) of integer;
37 |
38 | signal lut : lut_t(0 to 127) := (
39 | 750, 402, 700, -439, -96, 909, -496, -7, -711, 76, 601, 764, 315, -192, -633, 411,
40 | -139, -540, -640, -360, -172, 821, 291, 160, -678, 9, -241, -679, -293, 69, -172, 565,
41 | 999, -356, -19, 515, -498, 438, 693, 78, 209, -276, 131, -865, 487, 465, 35, 454,
42 | 437, -480, -45, -324, -991, -86, 2, -471, -38, -805, -621, 543, 397, 170, 606, -797,
43 | 369, 546, 591, 150, -17, -1095, -684, 109, -450, 760, -478, -573, -409, -66, 484, 682,
44 | 201, -826, -192, -695, 819, 16, 172, -403, -660, -342, 14, 443, -389, 544, -339, -734,
45 | -141, -366, -626, 381, 382, 280, 235, 624, -980, -218, 54, 333, 506, 333, 114, -944,
46 | 566, 46, -48, 305, -20, 457, 740, -56, 197, -919, 295, 522, 20, -2, -712, 438
47 | );
48 |
49 | signal ilut : lut_t(0 to 63) := (
50 | 0, 1, -1, -1, -1, 1, -1, 1, -1, -1, -1, 1, 1, -1, -1, 1, -1, 1, 1, -1, -1, -1, -1,
51 | -1, 1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, -1, 1, 1, 1, -1, 1, 1, -1,
52 | -1, -1, -1, 1, -1, -1, -1, -1, -1, 1, 1, -1, -1, 1, 1, -1 );
53 |
54 |
55 |
56 |
57 | constant N : integer := 64;
58 | begin
59 | clock <= not clock after 6.25 ns;
60 | reset <= '1', '0' after 50 ns;
61 |
62 | process
63 | begin
64 | in_real <= ( others => '0' );
65 | in_imag <= ( others => '0' );
66 | in_valid <= '0';
67 | in_sop <= '0';
68 | in_eop <= '0';
69 | wait for 100 ns;
70 | for iz in 0 to 80 loop
71 | for i in 0 to N-1 loop
72 | wait until rising_edge(clock);
73 | in_real <= std_logic_vector(to_signed(4096*ilut(i), in_real'high + 1));
74 | in_imag <= ( others => '0' ); --std_logic_vector(to_signed(lut(i*2+1), in_real'high + 1));
75 | in_valid <= '1';
76 | if (i = 0) then
77 | in_sop <= '1';
78 | else
79 | in_sop <= '0';
80 | end if;
81 |
82 | if (i = N-1) then
83 | in_eop <= '1';
84 | else
85 | in_eop <= '0';
86 | end if;
87 | end loop;
88 |
89 | wait until rising_edge(clock);
90 | in_valid <= '0';
91 | in_sop <= '0';
92 | in_eop <= '0';
93 | wait for 500 ns;
94 | end loop;
95 | wait for 5 ms;
96 | end process;
97 |
98 | U_uut: entity work.fft(mult)
99 | generic map(
100 | N => N
101 | )
102 | port map(
103 | clock => clock,
104 | reset => reset,
105 |
106 | inverse => '1',
107 | in_real => in_real,
108 | in_imag => in_imag,
109 | in_valid => in_valid,
110 | in_sop => in_sop,
111 | in_eop => in_eop,
112 |
113 | out_real => open,
114 | out_imag => open,
115 | out_error => open,
116 | out_valid => open
117 | );
118 |
119 | end architecture;
120 |
121 |
--------------------------------------------------------------------------------
/fpga/ip/nuand/nco.vhd:
--------------------------------------------------------------------------------
1 | -- This file is part of bladeRF-wiphy.
2 | --
3 | -- Copyright (C) 2020 Nuand, LLC.
4 | --
5 | -- This program is free software; you can redistribute it and/or modify
6 | -- it under the terms of the GNU General Public License as published by
7 | -- the Free Software Foundation; either version 2 of the License, or
8 | -- (at your option) any later version.
9 | --
10 | -- This program is distributed in the hope that it will be useful,
11 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | -- GNU General Public License for more details.
14 | --
15 | -- You should have received a copy of the GNU General Public License along
16 | -- with this program; if not, write to the Free Software Foundation, Inc.,
17 | -- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 |
19 | library ieee ;
20 | use ieee.std_logic_1164.all ;
21 | use ieee.numeric_std.all ;
22 |
23 | package nco_p is
24 |
25 | type nco_input_t is record
26 | dphase : signed(15 downto 0) ;
27 | valid : std_logic ;
28 | end record ;
29 |
30 | type nco_output_t is record
31 | re : signed(15 downto 0) ;
32 | im : signed(15 downto 0) ;
33 | valid : std_logic ;
34 | end record ;
35 |
36 | end package ; -- nco_p
37 |
38 | library ieee ;
39 | use ieee.std_logic_1164.all ;
40 | use ieee.numeric_std.all ;
41 |
42 | library work ;
43 | use work.cordic_p.all ;
44 | use work.nco_p.all ;
45 |
46 | entity nco is
47 | port (
48 | clock : in std_logic ;
49 | reset : in std_logic ;
50 | inputs : in nco_input_t ;
51 | outputs : out nco_output_t
52 | ) ;
53 | end entity ; -- nco
54 |
55 | architecture arch of nco is
56 |
57 | signal phase : signed(15 downto 0) ;
58 |
59 | signal cordic_inputs : cordic_xyz_t ;
60 | signal cordic_outputs : cordic_xyz_t ;
61 |
62 | begin
63 |
64 | accumulate_phase : process(clock, reset)
65 | variable temp : signed(15 downto 0) ;
66 | begin
67 | if( reset = '1' ) then
68 | phase <= (others =>'0') ;
69 | elsif( rising_edge( clock ) ) then
70 | if( inputs.valid = '1' ) then
71 | temp := phase + inputs.dphase ;
72 | if( temp > 16384 ) then
73 | temp := temp - 32768 ;
74 | elsif( temp < -16384 ) then
75 | temp := temp + 32768 ;
76 | end if ;
77 | phase <= temp ;
78 | end if ;
79 | end if ;
80 | end process ;
81 |
82 | cordic_inputs <= ( x => to_signed(1234,16), y => to_signed(0,16), z => phase, valid => inputs.valid ) ;
83 |
84 | U_cordic : entity work.cordic
85 | port map (
86 | clock => clock,
87 | reset => reset,
88 | mode => CORDIC_ROTATION,
89 | inputs => cordic_inputs,
90 | outputs => cordic_outputs
91 | ) ;
92 |
93 | outputs.re <= cordic_outputs.x ;
94 | outputs.im <= cordic_outputs.y ;
95 | outputs.valid <= cordic_outputs.valid ;
96 |
97 | end architecture ; -- arch
98 |
--------------------------------------------------------------------------------
/fpga/ip/nuand/viterbi_decoder/model/out.c:
--------------------------------------------------------------------------------
1 | // This file is part of bladeRF-wiphy.
2 | //
3 | // Copyright (C) 2021 Nuand, LLC.
4 | //
5 | // This program is free software; you can redistribute it and/or modify
6 | // it under the terms of the GNU General Public License as published by
7 | // the Free Software Foundation; either version 2 of the License, or
8 | // (at your option) any later version.
9 | //
10 | // This program is distributed in the hope that it will be useful,
11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | // GNU General Public License for more details.
14 | //
15 | // You should have received a copy of the GNU General Public License along
16 | // with this program; if not, write to the Free Software Foundation, Inc.,
17 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 |
19 | #include
20 | #include
21 | #include
22 | #include
23 | #include
24 |
25 | #define K 7
26 | #define C_A 91
27 | #define C_B 121
28 |
29 | #define BIT(y) ( (state >> y) & 1)
30 |
31 | #define T_BIT(y) ( (t_state >> y) & 1)
32 |
33 | int main(int argc, char *argv[]) {
34 | unsigned t_state;
35 | unsigned next_state;
36 | uint8_t t_bit_a, t_bit_b;
37 | for (t_state = 0; t_state <= 0x3f; t_state++) {
38 | // bit is 0?
39 | t_bit_a = T_BIT(5) ^ T_BIT(4) ^ T_BIT(2) ^ T_BIT(1) ^ 0;
40 | t_bit_b = T_BIT(5) ^ T_BIT(2) ^ T_BIT(1) ^ T_BIT(0) ^ 0;
41 | next_state = (t_state << 1) & 0x3f;
42 | printf("S[%d] -- bit=%d coded=%d,%d -- D[%d]\n", t_state, 0, t_bit_a, t_bit_b, next_state);
43 |
44 | // bit is 1?
45 | t_bit_a = T_BIT(5) ^ T_BIT(4) ^ T_BIT(2) ^ T_BIT(1) ^ 1;
46 | t_bit_b = T_BIT(5) ^ T_BIT(2) ^ T_BIT(1) ^ T_BIT(0) ^ 1;
47 | next_state = ((t_state << 1) & 0x3f) | 1;
48 | printf("S[%d] -- bit=%d coded=%d,%d -- D[%d]\n", t_state, 1, t_bit_a, t_bit_b, next_state);
49 | }
50 | return 0;
51 | }
52 |
--------------------------------------------------------------------------------
/fpga/ip/nuand/viterbi_decoder/vhdl/branch_compare.vhd:
--------------------------------------------------------------------------------
1 | -- This file is part of bladeRF-wiphy.
2 | --
3 | -- Copyright (C) 2021 Nuand, LLC.
4 | --
5 | -- This program is free software; you can redistribute it and/or modify
6 | -- it under the terms of the GNU General Public License as published by
7 | -- the Free Software Foundation; either version 2 of the License, or
8 | -- (at your option) any later version.
9 | --
10 | -- This program is distributed in the hope that it will be useful,
11 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | -- GNU General Public License for more details.
14 | --
15 | -- You should have received a copy of the GNU General Public License along
16 | -- with this program; if not, write to the Free Software Foundation, Inc.,
17 | -- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 |
19 | library ieee;
20 | use ieee.std_logic_1164.all;
21 | use ieee.numeric_std.all;
22 |
23 | library work;
24 | use work.viterbi_p.all;
25 |
26 | entity branch_compare is
27 | generic(
28 | RESET_ACTIVE : boolean := false;
29 | REG_UNCODED : boolean := false
30 | );
31 | port(
32 | clock : in std_logic;
33 | reset : in std_logic;
34 |
35 | bm_a : in unsigned(15 downto 0);
36 | bm_b : in unsigned(15 downto 0);
37 | bm_valid : in std_logic;
38 |
39 | path_in_a : in path_t;
40 | path_in_b : in path_t;
41 |
42 | branch : in branch_inputs_t;
43 | path_out : out path_t;
44 |
45 | win : out std_logic
46 | );
47 | end entity;
48 |
49 | architecture arch of branch_compare is
50 | begin
51 |
52 | process(reset, clock)
53 | variable cost_a, cost_b : unsigned(path_in_a.cost'range);
54 | begin
55 | if (reset = '1') then
56 | path_out <= NULL_PATH_RST(RESET_ACTIVE);
57 | win <= '0';
58 | elsif (rising_edge(clock)) then
59 | if (bm_valid = '1') then
60 | cost_a := path_in_a.cost + bm_a;
61 | cost_b := path_in_b.cost + bm_b;
62 |
63 | if ((path_in_a.cost = (path_in_a.cost'range => '1')) and
64 | (path_in_b.cost = (path_in_b.cost'range => '1'))) then
65 | win <= '0';
66 | path_out.cost <= ( others => '1' );
67 | elsif (path_in_a.cost = (path_in_a.cost'range => '1')) then
68 | win <= '1';
69 | path_out.cost <= cost_b;
70 | elsif (path_in_b.cost = (path_in_b.cost'range => '1')) then
71 | win <= '0';
72 | path_out.cost <= cost_a;
73 | else
74 | if (cost_b < cost_a) then
75 | win <= '1';
76 | path_out.cost <= cost_b;
77 | else
78 | win <= '0';
79 | path_out.cost <= cost_a;
80 | end if;
81 | end if;
82 | end if;
83 | end if;
84 | end process;
85 | end architecture;
86 |
--------------------------------------------------------------------------------
/fpga/ip/nuand/viterbi_decoder/vhdl/comp2.vhd:
--------------------------------------------------------------------------------
1 | -- This file is part of bladeRF-wiphy.
2 | --
3 | -- Copyright (C) 2021 Nuand, LLC.
4 | --
5 | -- This program is free software; you can redistribute it and/or modify
6 | -- it under the terms of the GNU General Public License as published by
7 | -- the Free Software Foundation; either version 2 of the License, or
8 | -- (at your option) any later version.
9 | --
10 | -- This program is distributed in the hope that it will be useful,
11 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | -- GNU General Public License for more details.
14 | --
15 | -- You should have received a copy of the GNU General Public License along
16 | -- with this program; if not, write to the Free Software Foundation, Inc.,
17 | -- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 |
19 | library ieee;
20 | use ieee.std_logic_1164.all;
21 | use ieee.numeric_std.all;
22 |
23 | library work;
24 | use work.viterbi_p.all;
25 |
26 | entity comp2 is
27 | port(
28 | clock : in std_logic;
29 | reset : in std_logic;
30 |
31 | path_name_a : in path_name_t;
32 | path_name_b : in path_name_t;
33 | path_valid : in std_logic;
34 |
35 | path_name_out : out path_name_t
36 | );
37 | end entity;
38 |
39 | architecture arch of comp2 is
40 | begin
41 | process(clock, reset)
42 | begin
43 | if (reset = '1') then
44 | path_name_out.name <= (others => '0');
45 | path_name_out.path <= NULL_PATH_T;
46 | elsif (rising_edge(clock)) then
47 | if (path_valid = '1') then
48 | if (path_name_b.path.cost < path_name_a.path.cost) then
49 | path_name_out <= path_name_b;
50 | else
51 | path_name_out <= path_name_a;
52 | end if;
53 | end if;
54 | end if;
55 | end process;
56 | end architecture;
57 |
--------------------------------------------------------------------------------
/fpga/ip/nuand/viterbi_decoder/vhdl/r2_comparator.vhd:
--------------------------------------------------------------------------------
1 | -- This file is part of bladeRF-wiphy.
2 | --
3 | -- Copyright (C) 2021 Nuand, LLC.
4 | --
5 | -- This program is free software; you can redistribute it and/or modify
6 | -- it under the terms of the GNU General Public License as published by
7 | -- the Free Software Foundation; either version 2 of the License, or
8 | -- (at your option) any later version.
9 | --
10 | -- This program is distributed in the hope that it will be useful,
11 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | -- GNU General Public License for more details.
14 | --
15 | -- You should have received a copy of the GNU General Public License along
16 | -- with this program; if not, write to the Free Software Foundation, Inc.,
17 | -- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 |
19 | library ieee;
20 | use ieee.std_logic_1164.all;
21 | use ieee.numeric_std.all;
22 |
23 | library work;
24 | use work.viterbi_p.all;
25 |
26 | entity r2_comparator is
27 | generic(
28 | NUM_PATHS : in natural := 64;
29 | STATE_BITS : in natural := 6
30 | );
31 | port(
32 | clock : in std_logic;
33 | reset : in std_logic;
34 |
35 | paths : in path_arr_t(NUM_PATHS-1 downto 0);
36 | path_valid : in std_logic;
37 |
38 | label_out : out unsigned(STATE_BITS-1 downto 0);
39 | valid_out : out std_logic
40 | );
41 | end entity;
42 |
43 | architecture arch of r2_comparator is
44 | type path_name_arr_arr_t is array(natural range <>) of path_name_arr_t(NUM_PATHS-1 downto 0);
45 |
46 | signal r2_matrix : path_name_arr_arr_t(STATE_BITS downto 0);
47 |
48 | signal valid_out_r : std_logic_vector(STATE_BITS - 1 downto 1);
49 | begin
50 | gen_init_path: for i in paths'range generate
51 | r2_matrix(0)(i).path <= paths(i);
52 | r2_matrix(0)(i).name <= to_unsigned(i, 6);
53 | end generate;
54 |
55 | process(clock, reset)
56 | begin
57 | if (reset = '1') then
58 | valid_out_r <= ( others => '0' );
59 | valid_out <= '0';
60 | elsif (rising_edge(clock)) then
61 | if (path_valid = '1') then
62 | valid_out_r <= path_valid & valid_out_r(valid_out_r'high downto 2);
63 | valid_out <= valid_out_r(1);
64 | else
65 | valid_out <= '0';
66 | end if;
67 | end if;
68 | end process;
69 |
70 | gen_cs: for cs_i in 1 to STATE_BITS generate
71 | gen_rs: for rs_i in 0 to NUM_PATHS/(2**cs_i)-1 generate
72 | U_comp2 : entity work.comp2
73 | port map(
74 | clock => clock,
75 | reset => reset,
76 |
77 | path_name_a => r2_matrix(cs_i-1)(rs_i * 2),
78 | path_name_b => r2_matrix(cs_i-1)(rs_i * 2 + 1),
79 | path_valid => path_valid,
80 | path_name_out => r2_matrix(cs_i)(rs_i)
81 | );
82 | end generate;
83 | end generate;
84 |
85 | label_out <= r2_matrix(r2_matrix'high)(0).name;
86 |
87 | end architecture;
88 |
--------------------------------------------------------------------------------
/fpga/ip/nuand/viterbi_decoder/vhdl/tb/compile.do:
--------------------------------------------------------------------------------
1 | vcom -work work -2008 ../viterbi_p.vhd
2 | vcom -work work -2008 ../tracer.vhd
3 | vcom -work work -2008 ../comp2.vhd
4 | vcom -work work -2008 ../r2_comparator.vhd
5 | vcom -work work -2008 ../branch_compare.vhd
6 | vcom -work work -2008 ../traceback.vhd
7 | vcom -work work -2008 ../viterbi_decoder.vhd
8 | vcom -work work -2008 viterbi_decoder_tb.vhd
9 | vcom -work work -2008 r2_comparator_tb.vhd
10 |
--------------------------------------------------------------------------------
/fpga/ip/nuand/viterbi_decoder/vhdl/tb/r2_comparator_tb.vhd:
--------------------------------------------------------------------------------
1 | -- This file is part of bladeRF-wiphy.
2 | --
3 | -- Copyright (C) 2021 Nuand, LLC.
4 | --
5 | -- This program is free software; you can redistribute it and/or modify
6 | -- it under the terms of the GNU General Public License as published by
7 | -- the Free Software Foundation; either version 2 of the License, or
8 | -- (at your option) any later version.
9 | --
10 | -- This program is distributed in the hope that it will be useful,
11 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | -- GNU General Public License for more details.
14 | --
15 | -- You should have received a copy of the GNU General Public License along
16 | -- with this program; if not, write to the Free Software Foundation, Inc.,
17 | -- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 |
19 | library ieee;
20 | use ieee.std_logic_1164.all;
21 | use ieee.numeric_std.all;
22 |
23 | library work;
24 | use work.viterbi_p.all;
25 |
26 | entity r2_comparator_tb is
27 | end entity;
28 |
29 | architecture behv of r2_comparator_tb is
30 | signal clock : std_logic := '0';
31 | signal reset : std_logic;
32 | signal valid : std_logic;
33 | signal paths : path_arr_t(63 downto 0);
34 |
35 | begin
36 | clock <= not clock after 10 ns;
37 | reset <= '1', '0' after 100 ns;
38 | valid <= '0', '1' after 198 ns, '0' after 548 ns;
39 |
40 | process
41 | variable i : integer;
42 | variable t_cost : integer;
43 | begin
44 | for i in paths'range loop
45 | if (i = 51) then
46 | t_cost := 10;
47 | else
48 | t_cost := 100 + i;
49 | end if;
50 | paths(i).cost <= to_unsigned(t_cost, paths(i).cost'high + 1);
51 | paths(i).active <= '0';
52 | end loop;
53 | wait;
54 | end process;
55 |
56 |
57 | U_uut: entity work.r2_comparator
58 | port map(
59 | clock => clock,
60 | reset => reset,
61 |
62 | paths => paths,
63 | path_valid => valid,
64 |
65 | label_out => open,
66 | valid_out => open
67 | );
68 | end architecture;
69 |
70 |
--------------------------------------------------------------------------------
/fpga/ip/nuand/viterbi_decoder/vhdl/traceback.vhd:
--------------------------------------------------------------------------------
1 | -- This file is part of bladeRF-wiphy.
2 | --
3 | -- Copyright (C) 2021 Nuand, LLC.
4 | --
5 | -- This program is free software; you can redistribute it and/or modify
6 | -- it under the terms of the GNU General Public License as published by
7 | -- the Free Software Foundation; either version 2 of the License, or
8 | -- (at your option) any later version.
9 | --
10 | -- This program is distributed in the hope that it will be useful,
11 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | -- GNU General Public License for more details.
14 | --
15 | -- You should have received a copy of the GNU General Public License along
16 | -- with this program; if not, write to the Free Software Foundation, Inc.,
17 | -- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 |
19 | library ieee;
20 | use ieee.std_logic_1164.all;
21 | use ieee.numeric_std.all;
22 |
23 | library work;
24 | use work.viterbi_p.all;
25 |
26 | entity traceback is
27 | generic(
28 | STATE_BITS : in integer;
29 | NUM_STATES : in integer;
30 | TB_LEN : in integer
31 | );
32 | port(
33 | clock : in std_logic;
34 | reset : in std_logic;
35 |
36 | acs_reg : in std_logic_vector(NUM_STATES-1 downto 0);
37 | acs_valid : in std_logic;
38 |
39 | best_idx : in unsigned(STATE_BITS-1 downto 0);
40 | best_valid : in std_logic;
41 |
42 | bit_out : out std_logic;
43 | valid_out : out std_logic
44 | );
45 | end entity;
46 |
47 | architecture arch of traceback is
48 | type history_t is array(7 + TB_LEN*2 downto 0) of std_logic_vector(NUM_STATES-1 downto 0);
49 |
50 | type fsm_t is (IDLE, START_TRACER);
51 |
52 | type state_t is record
53 | fsm : fsm_t;
54 | loaded : std_logic;
55 | history : history_t;
56 | acs_count : natural range 0 to TB_LEN+STATE_BITS*2;
57 | acs_enough : std_logic;
58 | bit_out : std_logic;
59 | valid_out : std_logic;
60 | end record;
61 |
62 | function NULL_STATE_T return state_t is
63 | variable ret : state_t;
64 | begin
65 | ret.fsm := IDLE;
66 | ret.loaded := '0';
67 | for i in ret.history'range loop
68 | ret.history(i) := ( others => '0' );
69 | end loop;
70 | ret.acs_count := 0;
71 | ret.acs_enough := '0';
72 | ret.bit_out := '0';
73 | ret.valid_out := '0';
74 | return(ret);
75 | end function;
76 |
77 | signal current, future : state_t := NULL_STATE_T;
78 |
79 | type trace_state_t is array(TB_LEN downto 0) of unsigned(STATE_BITS-1 downto 0);
80 |
81 | signal trace_state : trace_state_t;
82 | signal trace_state_valid : std_logic_vector(TB_LEN downto 0);
83 | begin
84 | sync : process(clock, reset)
85 | begin
86 | if (reset = '1') then
87 | current <= NULL_STATE_T;
88 | elsif (rising_edge(clock)) then
89 | current <= future;
90 | end if;
91 | end process;
92 |
93 | trace_state(0) <= best_idx;
94 | trace_state_valid(0) <= current.acs_enough;
95 |
96 | gen_tracers: for i in 0 to TB_LEN-1 generate
97 | U_tracer: entity work.tracer
98 | generic map(
99 | STATE_BITS => STATE_BITS,
100 | NUM_STATES => NUM_STATES
101 | )
102 | port map(
103 | clock => clock,
104 | reset => reset,
105 |
106 | state_in => trace_state(i),
107 | state_valid => trace_state_valid(i),
108 | acs_reg => current.history(6 + 2 * i),
109 | acs_valid => acs_valid,
110 |
111 | state_out => trace_state(i+1),
112 | valid_out => trace_state_valid(i+1)
113 | );
114 | end generate;
115 |
116 |
117 | bit_out <= current.bit_out;
118 | valid_out <= current.valid_out;
119 |
120 | comb : process(all)
121 | begin
122 | future <= current;
123 |
124 | future.bit_out <= '0';
125 | future.valid_out <= '0';
126 |
127 | if (acs_valid = '1') then
128 | if (current.acs_enough = '0') then
129 | if (current.acs_count = TB_LEN + 6 + 5) then
130 | future.acs_enough <= '1';
131 | else
132 | future.acs_count <= current.acs_count + 1;
133 | end if;
134 | end if;
135 | future.history <= current.history(current.history'high-1 downto 0) & acs_reg;
136 | end if;
137 |
138 | case current.fsm is
139 | when IDLE =>
140 | if (current.acs_enough = '1' and acs_valid = '1') then
141 | future.fsm <= START_TRACER;
142 | end if;
143 | when START_TRACER =>
144 | if (acs_valid = '1') then
145 | -- the bit that is about to be shifted out is actually the uncoded bit
146 | -- the new bit that is shifted in is from the current branch, the historical ACS reg basically determines the LSB of the new state
147 | future.bit_out <= trace_state(TB_LEN)(5);
148 | future.valid_out <= trace_state_valid(TB_LEN);
149 | end if;
150 | when others =>
151 | future <= NULL_STATE_T;
152 | end case;
153 | end process;
154 |
155 | end architecture;
156 |
--------------------------------------------------------------------------------
/fpga/ip/nuand/viterbi_decoder/vhdl/tracer.vhd:
--------------------------------------------------------------------------------
1 | -- This file is part of bladeRF-wiphy.
2 | --
3 | -- Copyright (C) 2021 Nuand, LLC.
4 | --
5 | -- This program is free software; you can redistribute it and/or modify
6 | -- it under the terms of the GNU General Public License as published by
7 | -- the Free Software Foundation; either version 2 of the License, or
8 | -- (at your option) any later version.
9 | --
10 | -- This program is distributed in the hope that it will be useful,
11 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | -- GNU General Public License for more details.
14 | --
15 | -- You should have received a copy of the GNU General Public License along
16 | -- with this program; if not, write to the Free Software Foundation, Inc.,
17 | -- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 |
19 | library ieee;
20 | use ieee.std_logic_1164.all;
21 | use ieee.numeric_std.all;
22 |
23 | library work;
24 | use work.viterbi_p.all;
25 |
26 | entity tracer is
27 | generic(
28 | STATE_BITS : in integer;
29 | NUM_STATES : in integer
30 | );
31 | port(
32 | clock : in std_logic;
33 | reset : in std_logic;
34 |
35 | state_in : in unsigned(STATE_BITS-1 downto 0);
36 | state_valid : in std_logic;
37 | acs_reg : in std_logic_vector(NUM_STATES-1 downto 0);
38 | acs_valid : in std_logic;
39 |
40 | state_out : out unsigned(STATE_BITS-1 downto 0);
41 | valid_out : out std_logic
42 | );
43 | end entity;
44 |
45 | architecture arch of tracer is
46 | begin
47 | process(clock, reset)
48 | variable s_bit : std_logic;
49 | begin
50 | if (reset='1') then
51 | state_out <= ( others => '0' );
52 | valid_out <= '0';
53 | elsif (rising_edge(clock)) then
54 | s_bit := acs_reg(to_integer(state_in));
55 | if (acs_valid = '1') then
56 | state_out <= s_bit & state_in(state_in'high downto 1);
57 | valid_out <= state_valid;
58 | end if;
59 | end if;
60 | end process;
61 | end architecture;
62 |
--------------------------------------------------------------------------------
/fpga/ip/nuand/viterbi_decoder/vhdl/viterbi_p.vhd:
--------------------------------------------------------------------------------
1 | -- This file is part of bladeRF-wiphy.
2 | --
3 | -- Copyright (C) 2021 Nuand, LLC.
4 | --
5 | -- This program is free software; you can redistribute it and/or modify
6 | -- it under the terms of the GNU General Public License as published by
7 | -- the Free Software Foundation; either version 2 of the License, or
8 | -- (at your option) any later version.
9 | --
10 | -- This program is distributed in the hope that it will be useful,
11 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | -- GNU General Public License for more details.
14 | --
15 | -- You should have received a copy of the GNU General Public License along
16 | -- with this program; if not, write to the Free Software Foundation, Inc.,
17 | -- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 |
19 | library ieee;
20 | use ieee.std_logic_1164.all;
21 | use ieee.numeric_std.all;
22 |
23 | package viterbi_p is
24 | type path_t is record
25 | --- path metric stuff
26 | cost : unsigned(23 downto 0);
27 | active : std_logic;
28 | end record;
29 | type path_arr_t is array(natural range <>) of path_t;
30 |
31 | type path_name_t is record
32 | path : path_t;
33 | name : unsigned(5 downto 0);
34 | end record;
35 |
36 | type path_name_arr_t is array(natural range <>) of path_name_t;
37 |
38 |
39 | type branch_t is record
40 | -- starting conditions
41 | start_state : natural;
42 | u_bit : std_logic;
43 |
44 | -- internal state keeping
45 | bit_s : std_logic;
46 | set : boolean;
47 |
48 | -- output
49 | bit_a : std_logic;
50 | bit_b : std_logic;
51 | bm_idx : integer;
52 |
53 | -- final state
54 | prev_state : integer;
55 | next_state : integer;
56 | end record;
57 |
58 | type branch_inputs_t is array(1 downto 0) of branch_t;
59 |
60 | type bsd_t is array(natural range <>) of unsigned(7 downto 0);
61 |
62 | type bm_t is array(natural range <>) of unsigned(15 downto 0);
63 |
64 | function NULL_PATH_RST(init_state : boolean) return path_t;
65 | function NULL_PATH_T return path_t;
66 | end package;
67 |
68 | package body viterbi_p is
69 | function NULL_PATH_RST(init_state : boolean) return path_t is
70 | variable ret : path_t;
71 | begin
72 | if (init_state) then
73 | ret.cost := ( others => '0' );
74 | else
75 | ret.cost := ( others => '1' );
76 | end if;
77 | ret.active := '0';
78 | return ret;
79 | end function;
80 |
81 | function NULL_PATH_T return path_t is
82 | begin
83 | return NULL_PATH_RST(false);
84 | end function;
85 | end package body;
86 |
--------------------------------------------------------------------------------
/fpga/modelsim/wlan.do:
--------------------------------------------------------------------------------
1 | # Library
2 | vlib wlan
3 |
4 | if { ! [info exists wlan_path] } {
5 | set wlan_path "."
6 | }
7 |
8 | set modelsim 1
9 |
10 | vlib nuand
11 | vcom -work nuand -2008 [file join $wlan_path ../../../bladeRF/hdl/fpga/ip/nuand/synthesis/fifo_readwrite_p.vhd ]
12 |
13 | # altera ip simulation models
14 | vlib fft64
15 |
16 | set QSYS_SIMDIR [file normalize [ file join $wlan_path ../ip/altera/fft64/fft64/simulation/ ] ]
17 | source [file normalize [ file join $wlan_path $QSYS_SIMDIR/mentor/msim_setup.tcl ] ]
18 | dev_com
19 | com
20 | vmap fft64 libraries/fft_ii_0/
21 |
22 | vlog -work fft64 [ file join $wlan_path ../ip/altera/fft64/fft64/simulation/fft64.v ]
23 | set hexfiles [glob [file join $wlan_path "../ip/altera/fft64/fft64/simulation/submodules/*.hex"] ]
24 | foreach f $hexfiles {
25 | file copy -force $f .
26 | }
27 |
28 | vlib viterbi_decoder
29 | set QSYS_SIMDIR [file normalize [ file join $wlan_path ../ip/altera/viterbi_decoder/viterbi_decoder/simulation/ ] ]
30 | source [file normalize [ file join $wlan_path $QSYS_SIMDIR/mentor/msim_setup.tcl ] ]
31 | dev_com
32 | com
33 | vmap viterbi_decoder libraries/viterbi_ii_0/
34 |
35 | vlog -work viterbi_decoder [ file join $wlan_path ../ip/altera/viterbi_decoder/viterbi_decoder/simulation/viterbi_decoder.v ]
36 | vlog -work viterbi_decoder [ file join $wlan_path ../ip/altera/viterbi_decoder/viterbi_decoder/simulation/submodules/viterbi_decoder_viterbi_ii_0.v ]
37 |
38 |
39 | vlib wlan_pll
40 | vlog -work wlan_pll [ file join $wlan_path ../ip/altera/wlan_pll/wlan_pll/wlan_pll.v ]
41 |
42 | source [file normalize [ file join $wlan_path ../common/wlan_files.tcl ] ]
43 |
44 | # Common packages
45 | foreach f $wlan_common {
46 | vcom -work wlan -2008 $f
47 | }
48 |
49 | # TX Synthesis
50 | foreach f $wlan_synthesis_tx {
51 | vcom -work wlan -2008 $f
52 | }
53 |
54 | # RX Synthesis
55 | foreach f $wlan_synthesis_rx {
56 | vcom -work wlan -2008 $f
57 | }
58 |
59 | # Top Level Synthesis
60 | foreach f $wlan_synthesis_top {
61 | vcom -work wlan -2008 $f
62 | }
63 |
64 | # Simulation
65 | foreach f $wlan_sim {
66 | vcom -work wlan -2008 $f
67 | }
68 |
69 | proc wlan_sim_entity { entity } {
70 | vsim -t ps -L work -L work_lib -L fft_ii_0 -L altera_ver -L lpm_ver -L sgate_ver -L altera_mf_ver -L wlan -L fft64 -L viterbi_decoder -L altera_lnsim_ver $entity
71 | }
72 |
73 | alias tb_wlan_rx {
74 | wlan_sim_entity wlan_rx_tb
75 | }
76 |
--------------------------------------------------------------------------------
/fpga/quartus/wlan.qip:
--------------------------------------------------------------------------------
1 | # Altera FFT IP
2 | set_global_assignment -name QIP_FILE [file normalize "../../../../../bladeRF-wiphy/fpga/ip/altera/fft64/fft64/synthesis/fft64.qip"]
3 | set_global_assignment -name QIP_FILE [file normalize "../../../../../bladeRF-wiphy/fpga/ip/altera/viterbi_decoder/viterbi_decoder/synthesis/viterbi_decoder.qip"]
4 | set_global_assignment -library "wlan_pll" -name VERILOG_FILE [file normalize "../../../../../bladeRF-wiphy/fpga/ip/altera/wlan_pll/wlan_pll/wlan_pll.v"]
5 | set_global_assignment -library "wlan_pll" -name QIP_FILE [file normalize "../../../../../bladeRF-wiphy/fpga/ip/altera/wlan_pll/wlan_pll/wlan_pll.qip"]
6 |
7 | set modelsim 0
8 |
9 | # Nuand WLAN IP files
10 | source [file normalize [file join $::quartus(qip_path) ../common/wlan_files.tcl]]
11 | foreach f $wlan_common {
12 | set_global_assignment -library "wlan" -name VHDL_FILE [file normalize [file join $::quartus(qip_path) $f]] -hdl_version VHDL_2008
13 | }
14 |
15 | foreach f $wlan_synthesis_tx {
16 | set_global_assignment -library "wlan" -name VHDL_FILE [file normalize [file join $::quartus(qip_path) $f]] -hdl_version VHDL_2008
17 | }
18 |
19 | foreach f $wlan_synthesis_rx {
20 | set_global_assignment -library "wlan" -name VHDL_FILE [file normalize [file join $::quartus(qip_path) $f]] -hdl_version VHDL_2008
21 | }
22 |
23 | foreach f $wlan_synthesis_top {
24 | set_global_assignment -library "wlan" -name VHDL_FILE [file normalize [file join $::quartus(qip_path) $f]] -hdl_version VHDL_2008
25 | }
26 |
27 |
--------------------------------------------------------------------------------
/fpga/vhdl/clock_sync_logic.vhd:
--------------------------------------------------------------------------------
1 | -- This file is part of bladeRF-wiphy.
2 | --
3 | -- Copyright (C) 2020 Nuand, LLC.
4 | --
5 | -- This program is free software; you can redistribute it and/or modify
6 | -- it under the terms of the GNU General Public License as published by
7 | -- the Free Software Foundation; either version 2 of the License, or
8 | -- (at your option) any later version.
9 | --
10 | -- This program is distributed in the hope that it will be useful,
11 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | -- GNU General Public License for more details.
14 | --
15 | -- You should have received a copy of the GNU General Public License along
16 | -- with this program; if not, write to the Free Software Foundation, Inc.,
17 | -- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 |
19 | library ieee ;
20 | use ieee.std_logic_1164.all ;
21 | use ieee.numeric_std.all ;
22 |
23 | library wlan ;
24 | use wlan.wlan_rx_p.all ;
25 |
26 | entity clock_sync_logic is
27 | port (
28 | from_signal : in std_logic ;
29 |
30 | to_clock : in std_logic ;
31 | to_reset : in std_logic ;
32 |
33 | to_signal : out std_logic
34 | ) ;
35 | end entity;
36 |
37 | architecture arch of clock_sync_logic is
38 |
39 | signal t_sig_r : std_logic ;
40 | signal t_sig_rr : std_logic ;
41 |
42 | attribute ALTERA_ATTRIBUTE : string;
43 |
44 | attribute ALTERA_ATTRIBUTE of arch: architecture is "-name SDC_STATEMENT ""set_false_path -to [get_registers *clock_sync_logic|*_r* ] "" ";
45 |
46 | begin
47 |
48 | process(all)
49 | begin
50 | if( to_reset = '1' ) then
51 | t_sig_rr <= '0' ;
52 | t_sig_r <= '0' ;
53 | to_signal <= '0' ;
54 | elsif( rising_edge( to_clock ) ) then
55 | t_sig_r <= from_signal ;
56 | t_sig_rr <= t_sig_r ;
57 | if( t_sig_rr = '0' and t_sig_r = '1' ) then
58 | to_signal <= '1' ;
59 | else
60 | to_signal <= '0' ;
61 | end if ;
62 | end if ;
63 | end process ;
64 |
65 | end architecture ;
66 |
--------------------------------------------------------------------------------
/fpga/vhdl/clock_sync_logic_vector.vhd:
--------------------------------------------------------------------------------
1 | -- This file is part of bladeRF-wiphy.
2 | --
3 | -- Copyright (C) 2020 Nuand, LLC.
4 | --
5 | -- This program is free software; you can redistribute it and/or modify
6 | -- it under the terms of the GNU General Public License as published by
7 | -- the Free Software Foundation; either version 2 of the License, or
8 | -- (at your option) any later version.
9 | --
10 | -- This program is distributed in the hope that it will be useful,
11 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | -- GNU General Public License for more details.
14 | --
15 | -- You should have received a copy of the GNU General Public License along
16 | -- with this program; if not, write to the Free Software Foundation, Inc.,
17 | -- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 |
19 | library ieee ;
20 | use ieee.std_logic_1164.all ;
21 | use ieee.numeric_std.all ;
22 |
23 | library wlan ;
24 | use wlan.wlan_rx_p.all ;
25 |
26 | entity clock_sync_logic_vector is
27 | generic (
28 | LEN : integer := 8
29 | ) ;
30 | port (
31 | from_signal : in std_logic_vector(LEN-1 downto 0) ;
32 |
33 | to_clock : in std_logic ;
34 | to_reset : in std_logic ;
35 |
36 | to_signal : out std_logic_vector(LEN-1 downto 0)
37 | ) ;
38 | end entity;
39 |
40 | architecture arch of clock_sync_logic_vector is
41 |
42 | signal t_sig_r : std_logic_vector(LEN-1 downto 0) ;
43 |
44 | attribute ALTERA_ATTRIBUTE : string;
45 |
46 | attribute ALTERA_ATTRIBUTE of arch: architecture is "-name SDC_STATEMENT ""set_false_path -to [get_registers *clock_sync_logic_vector|*_r* ] "" ";
47 |
48 | begin
49 |
50 | process(all)
51 | begin
52 | if( to_reset = '1' ) then
53 | t_sig_r <= ( others => '0' ) ;
54 | to_signal <= ( others => '0' ) ;
55 | elsif( rising_edge( to_clock ) ) then
56 | t_sig_r <= from_signal ;
57 | to_signal <= t_sig_r ;
58 | end if ;
59 | end process ;
60 | end architecture ;
61 |
--------------------------------------------------------------------------------
/fpga/vhdl/clock_sync_params.vhd:
--------------------------------------------------------------------------------
1 | -- This file is part of bladeRF-wiphy.
2 | --
3 | -- Copyright (C) 2020 Nuand, LLC.
4 | --
5 | -- This program is free software; you can redistribute it and/or modify
6 | -- it under the terms of the GNU General Public License as published by
7 | -- the Free Software Foundation; either version 2 of the License, or
8 | -- (at your option) any later version.
9 | --
10 | -- This program is distributed in the hope that it will be useful,
11 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | -- GNU General Public License for more details.
14 | --
15 | -- You should have received a copy of the GNU General Public License along
16 | -- with this program; if not, write to the Free Software Foundation, Inc.,
17 | -- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 |
19 | library ieee ;
20 | use ieee.std_logic_1164.all ;
21 | use ieee.numeric_std.all ;
22 |
23 | library wlan ;
24 | use wlan.wlan_rx_p.all ;
25 |
26 | entity clock_sync_params is
27 | port (
28 | from_signal : in wlan_rx_params_t ;
29 |
30 | to_clock : in std_logic ;
31 | to_reset : in std_logic ;
32 |
33 | to_signal : out wlan_rx_params_t
34 | ) ;
35 | end entity;
36 |
37 | architecture arch of clock_sync_params is
38 |
39 | signal t_sig_r : wlan_rx_params_t ;
40 |
41 | attribute ALTERA_ATTRIBUTE : string;
42 |
43 | attribute ALTERA_ATTRIBUTE of arch: architecture is "-name SDC_STATEMENT ""set_false_path -to [get_registers *clock_sync_params|*_r* ] "" ";
44 |
45 | begin
46 |
47 | process(all)
48 | begin
49 | if( to_reset = '1' ) then
50 | t_sig_r <= NULL_PARAMS ;
51 | to_signal <= NULL_PARAMS ;
52 | elsif( rising_edge( to_clock ) ) then
53 | t_sig_r <= from_signal ;
54 | to_signal <= t_sig_r ;
55 | end if ;
56 | end process ;
57 |
58 | end architecture ;
59 |
--------------------------------------------------------------------------------
/fpga/vhdl/tb/wlan_ack_generator_tb.vhd:
--------------------------------------------------------------------------------
1 | -- This file is part of bladeRF-wiphy.
2 | --
3 | -- Copyright (C) 2020 Nuand, LLC.
4 | --
5 | -- This program is free software; you can redistribute it and/or modify
6 | -- it under the terms of the GNU General Public License as published by
7 | -- the Free Software Foundation; either version 2 of the License, or
8 | -- (at your option) any later version.
9 | --
10 | -- This program is distributed in the hope that it will be useful,
11 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | -- GNU General Public License for more details.
14 | --
15 | -- You should have received a copy of the GNU General Public License along
16 | -- with this program; if not, write to the Free Software Foundation, Inc.,
17 | -- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 |
19 | library ieee ;
20 | use ieee.std_logic_1164.all ;
21 | use ieee.numeric_std.all ;
22 |
23 | library wlan ;
24 | use wlan.wlan_rx_p.all ;
25 |
26 | entity wlan_ack_generator_tb is
27 | end entity ;
28 |
29 | architecture arch of wlan_ack_generator_tb is
30 |
31 | signal wclock : std_logic := '1' ;
32 | signal wreset : std_logic := '1' ;
33 |
34 | signal rclock : std_logic := '1' ;
35 | signal rreset : std_logic := '1' ;
36 |
37 | signal ack_valid : std_logic := '0' ;
38 |
39 | signal fifo_re : std_logic := '0' ;
40 |
41 | begin
42 |
43 | wclock <= not wclock after 5 ns ;
44 | wreset <= '1', '0' after 55 ns ;
45 |
46 | rclock <= not rclock after 6 ns ;
47 | rreset <= '1', '0' after 55 ns ;
48 |
49 | ack_valid <= '0', '1' after 72 ns, '0' after 82 ns ;
50 |
51 | fifo_re <= '0', '1' after 400 ns, '0' after 412 ns ;
52 | U_ack_gen : entity wlan.wlan_ack_generator
53 | port map (
54 | wclock => wclock,
55 | wreset => wreset,
56 |
57 | ack_mac => x"1234567890ab",
58 | ack_valid => ack_valid,
59 |
60 | rclock => rclock,
61 | rreset => rreset,
62 |
63 | fifo_data => open,
64 | fifo_re => fifo_re,
65 | done_tx => '1',
66 |
67 | ack_ready => open
68 | ) ;
69 |
70 | end architecture ;
71 |
--------------------------------------------------------------------------------
/fpga/vhdl/tb/wlan_acquisition_tb.vhd:
--------------------------------------------------------------------------------
1 | -- This file is part of bladeRF-wiphy.
2 | --
3 | -- Copyright (C) 2020 Nuand, LLC.
4 | --
5 | -- This program is free software; you can redistribute it and/or modify
6 | -- it under the terms of the GNU General Public License as published by
7 | -- the Free Software Foundation; either version 2 of the License, or
8 | -- (at your option) any later version.
9 | --
10 | -- This program is distributed in the hope that it will be useful,
11 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | -- GNU General Public License for more details.
14 | --
15 | -- You should have received a copy of the GNU General Public License along
16 | -- with this program; if not, write to the Free Software Foundation, Inc.,
17 | -- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 |
19 | library ieee ;
20 | use ieee.std_logic_1164.all ;
21 | use ieee.numeric_std.all ;
22 | use ieee.math_real.all ;
23 |
24 | library wlan ;
25 | use wlan.wlan_p.all ;
26 | use wlan.wlan_rx_p.all ;
27 |
28 | library wlan;
29 | entity wlan_acquisition_tb is
30 | end entity ;
31 |
32 | architecture arch of wlan_acquisition_tb is
33 |
34 | signal clock : std_logic := '0' ;
35 | signal sample : wlan_sample_t ;
36 | signal fopen : std_logic;
37 | signal reset : std_logic;
38 |
39 | signal i_sum : signed(63 downto 0);
40 | signal q_sum : signed(63 downto 0);
41 | signal sum : signed(127 downto 0);
42 |
43 | signal acquired_packet : std_logic ;
44 | signal p_mag : signed(23 downto 0) ;
45 |
46 | type SAMPLE_ARRAY is array (integer range <>) of wlan_sample_t;
47 | signal samples : SAMPLE_ARRAY(0 to 159);
48 |
49 | begin
50 |
51 | clock <= not clock after 10 ns;
52 | reset <= '1', '0' after 50 ns ;
53 | fopen <= '0', '1' after 100 ns;
54 |
55 | U_sample_loader: entity wlan.wlan_sample_loader
56 | generic map (
57 | FILENAME => "tx"
58 | ) port map (
59 | clock => clock,
60 | fopen => fopen,
61 | sample => sample
62 | );
63 |
64 | U_csma : entity wlan.wlan_csma
65 | port map (
66 | clock => clock,
67 | reset => reset,
68 |
69 | in_sample => sample,
70 | quiet => open
71 | ) ;
72 | U_acquisition : entity wlan.wlan_acquisition
73 | port map (
74 | clock => clock,
75 | reset => reset,
76 |
77 | in_sample => sample,
78 | acquired => acquired_packet,
79 | p_mag => p_mag,
80 |
81 | quiet => '0',
82 | burst => '0',
83 |
84 | out_sample => open
85 | );
86 |
87 | tb : process(clock)
88 | variable tsum : signed(127 downto 0);
89 | variable isum : signed(63 downto 0);
90 | variable qsum : signed(63 downto 0);
91 | begin
92 | if( rising_edge( clock ) ) then
93 | if( sample.valid = '1' ) then
94 | for i in 0 to samples'high - 1 loop
95 | samples(i+1) <= samples(i);
96 | end loop ;
97 | samples(0) <= sample;
98 |
99 | isum := (others => '0');
100 | qsum := (others => '0');
101 | for i in 0 to 79 loop
102 | isum := isum + samples(i).i * samples(i + 80).i + samples(i).q * samples(i + 80).q;
103 | qsum := qsum - samples(i).i * samples(i + 80).q + samples(i).q * samples(i + 80).i;
104 | end loop ;
105 | i_sum <= isum;
106 | q_sum <= qsum;
107 | tsum := isum * isum + qsum * qsum;
108 | sum <= tsum;
109 | end if;
110 | end if ;
111 | end process ;
112 |
113 | end architecture ;
114 |
115 |
--------------------------------------------------------------------------------
/fpga/vhdl/tb/wlan_bsd_tb.vhd:
--------------------------------------------------------------------------------
1 | -- This file is part of bladeRF-wiphy.
2 | --
3 | -- Copyright (C) 2020 Nuand, LLC.
4 | --
5 | -- This program is free software; you can redistribute it and/or modify
6 | -- it under the terms of the GNU General Public License as published by
7 | -- the Free Software Foundation; either version 2 of the License, or
8 | -- (at your option) any later version.
9 | --
10 | -- This program is distributed in the hope that it will be useful,
11 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | -- GNU General Public License for more details.
14 | --
15 | -- You should have received a copy of the GNU General Public License along
16 | -- with this program; if not, write to the Free Software Foundation, Inc.,
17 | -- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 |
19 | library ieee ;
20 | use ieee.std_logic_1164.all ;
21 | use ieee.numeric_std.all ;
22 |
23 | library wlan ;
24 | use wlan.wlan_p.all ;
25 |
26 | entity wlan_bsd_tb is
27 | end entity ;
28 |
29 | architecture arch of wlan_bsd_tb is
30 |
31 | signal clock : std_logic := '1' ;
32 | signal reset : std_logic := '1' ;
33 |
34 | signal init : std_logic := '0' ;
35 |
36 | signal modulation : wlan_modulation_t := WLAN_BPSK ;
37 |
38 | signal data : std_logic_vector(287 downto 0) := (others =>'0') ;
39 | signal data_valid : std_logic := '0' ;
40 |
41 | signal mod_start : std_logic ;
42 | signal mod_end : std_logic ;
43 | signal mod_sample : wlan_sample_t ;
44 |
45 | signal bsds : wlan_bsds_t ;
46 |
47 | procedure nop( signal clock : in std_logic ; count : in natural ) is
48 | begin
49 | for i in 1 to count loop
50 | wait until rising_edge(clock) ;
51 | end loop ;
52 | end procedure ;
53 |
54 | begin
55 |
56 | clock <= not clock after 1 ns ;
57 |
58 | U_modulator : entity work.wlan_modulator
59 | port map (
60 | clock => clock,
61 | reset => reset,
62 |
63 | init => init,
64 |
65 | data => data,
66 | modulation => modulation,
67 | in_valid => data_valid,
68 |
69 | ifft_ready => '1',
70 |
71 | symbol_start => mod_start,
72 | symbol_end => mod_end,
73 | symbol_sample => mod_sample
74 | ) ;
75 |
76 | U_bsd : entity work.wlan_bsd
77 | port map (
78 | clock => clock,
79 | reset => reset,
80 |
81 | modulation => modulation,
82 |
83 | in_sample => mod_sample,
84 |
85 | bsds => bsds
86 | ) ;
87 |
88 | tb : process
89 | begin
90 | reset <= '1' ;
91 | nop( clock, 10 ) ;
92 |
93 | reset <= '0' ;
94 | nop( clock, 10 ) ;
95 |
96 | init <= '1' ;
97 | nop( clock, 1 ) ;
98 | init <= '0' ;
99 | nop( clock, 1 ) ;
100 |
101 | -- Run through modulations and populate data
102 | for m in 0 to wlan_modulation_t'pos(WLAN_64QAM) loop
103 | modulation <= wlan_modulation_t'val(m) ;
104 | data <= (others =>'0') ;
105 | data_valid <= '1' ;
106 | nop( clock, 1 ) ;
107 | data_valid <= '0' ;
108 | wait until rising_edge(clock) and mod_start = '1' ;
109 | wait until rising_edge(clock) and mod_end = '1' ;
110 | nop( clock, 10 ) ;
111 | end loop ;
112 |
113 | nop( clock, 100 ) ;
114 | report "-- End of Simulation --" severity failure ;
115 | end process ;
116 |
117 | end architecture ;
118 |
119 |
--------------------------------------------------------------------------------
/fpga/vhdl/tb/wlan_clock_tb.vhd:
--------------------------------------------------------------------------------
1 | -- This file is part of bladeRF-wiphy.
2 | --
3 | -- Copyright (C) 2020 Nuand, LLC.
4 | --
5 | -- This program is free software; you can redistribute it and/or modify
6 | -- it under the terms of the GNU General Public License as published by
7 | -- the Free Software Foundation; either version 2 of the License, or
8 | -- (at your option) any later version.
9 | --
10 | -- This program is distributed in the hope that it will be useful,
11 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | -- GNU General Public License for more details.
14 | --
15 | -- You should have received a copy of the GNU General Public License along
16 | -- with this program; if not, write to the Free Software Foundation, Inc.,
17 | -- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 |
19 | library ieee ;
20 | use ieee.std_logic_1164.all ;
21 | use ieee.numeric_std.all ;
22 |
23 | library wlan ;
24 | use wlan.wlan_p.all ;
25 | use wlan.wlan_rx_p.all ;
26 |
27 | library altera_mf ;
28 | use altera_mf.altera_mf_components.all ;
29 |
30 | library wlan_pll ;
31 |
32 |
33 | entity wlan_clock_tb is
34 | end entity ;
35 |
36 | architecture arch of wlan_clock_tb is
37 |
38 | signal wclock : std_logic := '1' ;
39 | signal wreset : std_logic := '1' ;
40 | signal wdata : unsigned(7 downto 0) := ( others => '0' ) ;
41 | signal wvalid : std_logic := '1' ;
42 | signal wfull : std_logic := '1' ;
43 |
44 | signal rclock : std_logic := '1' ;
45 | signal rreset : std_logic := '1' ;
46 | signal rempty : std_logic := '1' ;
47 | signal rdata : std_logic_vector(7 downto 0) := ( others => '0' ) ;
48 |
49 | signal ack_valid : std_logic := '0' ;
50 |
51 | signal fifo_re : std_logic := '0' ;
52 |
53 | signal alt : std_logic := '0' ;
54 |
55 | begin
56 | wclock <= not wclock after 20 ns;
57 | rclock <= not rclock after 10 ns;
58 |
59 | process(wclock)
60 | begin
61 | if( rising_edge( wclock ) ) then
62 | alt <= not alt;
63 | if (alt = '0' ) then
64 | wdata <= wdata + 1;
65 | end if;
66 | end if;
67 | end process;
68 |
69 | U_rx_data_dc_fifo: dcfifo
70 | generic map (
71 | lpm_width => 8,
72 | lpm_widthu => 6,
73 | lpm_numwords => 32,
74 | lpm_showahead => "ON"
75 | )
76 | port map (
77 | wrclk => wclock,
78 | wrreq => alt and not wfull,
79 | data => std_logic_vector(wdata),
80 |
81 | wrfull => wfull,
82 | wrempty => open,
83 | wrusedw => open,
84 |
85 | rdclk => rclock,
86 | rdreq => not rempty,
87 | q => rdata,
88 |
89 | rdfull => open,
90 | rdempty => rempty,
91 | rdusedw => open
92 | ) ;
93 |
94 |
95 | end architecture ;
96 |
--------------------------------------------------------------------------------
/fpga/vhdl/tb/wlan_dsss_plcp_crc_tb.vhd:
--------------------------------------------------------------------------------
1 | -- This file is part of bladeRF-wiphy.
2 | --
3 | -- Copyright (C) 2020 Nuand, LLC.
4 | --
5 | -- This program is free software; you can redistribute it and/or modify
6 | -- it under the terms of the GNU General Public License as published by
7 | -- the Free Software Foundation; either version 2 of the License, or
8 | -- (at your option) any later version.
9 | --
10 | -- This program is distributed in the hope that it will be useful,
11 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | -- GNU General Public License for more details.
14 | --
15 | -- You should have received a copy of the GNU General Public License along
16 | -- with this program; if not, write to the Free Software Foundation, Inc.,
17 | -- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 |
19 | library ieee ;
20 | use ieee.std_logic_1164.all ;
21 | use ieee.numeric_std.all ;
22 |
23 | library wlan ;
24 | use wlan.wlan_rx_p.all ;
25 |
26 | entity wlan_dsss_plcp_crc_tb is
27 | end entity ;
28 |
29 | architecture arch of wlan_dsss_plcp_crc_tb is
30 |
31 | signal clock : std_logic := '1' ;
32 | signal reset : std_logic := '1' ;
33 |
34 | signal in_data : std_logic := '1' ;
35 |
36 | begin
37 |
38 | clock <= not clock after 5 ns ;
39 | reset <= '1', '0' after 55 ns ;
40 | in_data <= '0',
41 | '1' after 65 ns,
42 | '0' after 75 ns,
43 | '1' after 85 ns,
44 | '0' after 95 ns;
45 |
46 |
47 | U_plcp_crc : entity wlan.wlan_dsss_plcp_crc
48 | port map (
49 | clock => clock,
50 | reset => reset,
51 |
52 | in_data => in_data,
53 | in_valid => '1',
54 | crc => open
55 | ) ;
56 |
57 | end architecture ;
58 |
--------------------------------------------------------------------------------
/fpga/vhdl/tb/wlan_interleaver_tb.vhd:
--------------------------------------------------------------------------------
1 | -- This file is part of bladeRF-wiphy.
2 | --
3 | -- Copyright (C) 2020 Nuand, LLC.
4 | --
5 | -- This program is free software; you can redistribute it and/or modify
6 | -- it under the terms of the GNU General Public License as published by
7 | -- the Free Software Foundation; either version 2 of the License, or
8 | -- (at your option) any later version.
9 | --
10 | -- This program is distributed in the hope that it will be useful,
11 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | -- GNU General Public License for more details.
14 | --
15 | -- You should have received a copy of the GNU General Public License along
16 | -- with this program; if not, write to the Free Software Foundation, Inc.,
17 | -- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 |
19 | library ieee ;
20 | use ieee.std_logic_1164.all ;
21 | use ieee.numeric_std.all ;
22 |
23 | library work ;
24 | use work.wlan_p.all ;
25 | use work.wlan_interleaver_p.all ;
26 |
27 | library std ;
28 | use std.textio.all ;
29 |
30 | entity wlan_interleaver_tb is
31 | end entity ;
32 |
33 | architecture arch of wlan_interleaver_tb is
34 |
35 | procedure print( table : integer_array_t ; n : natural ) is
36 | begin
37 | for i in 0 to n-1 loop
38 | write(output, integer'image(i) & " -> " & integer'image(table(i)) & CR ) ;
39 | end loop ;
40 | end procedure ;
41 |
42 | begin
43 |
44 | tb : process
45 | variable l : line ;
46 | begin
47 |
48 | write( output, "-- BPSK Table --" & CR ) ;
49 | print( WLAN_INTERLEAVER_BPSK, 48 ) ;
50 | wait ;
51 |
52 | end process ;
53 |
54 | end architecture ;
55 |
56 |
--------------------------------------------------------------------------------
/fpga/vhdl/tb/wlan_lfsr_tb.vhd:
--------------------------------------------------------------------------------
1 | -- This file is part of bladeRF-wiphy.
2 | --
3 | -- Copyright (C) 2020 Nuand, LLC.
4 | --
5 | -- This program is free software; you can redistribute it and/or modify
6 | -- it under the terms of the GNU General Public License as published by
7 | -- the Free Software Foundation; either version 2 of the License, or
8 | -- (at your option) any later version.
9 | --
10 | -- This program is distributed in the hope that it will be useful,
11 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | -- GNU General Public License for more details.
14 | --
15 | -- You should have received a copy of the GNU General Public License along
16 | -- with this program; if not, write to the Free Software Foundation, Inc.,
17 | -- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 |
19 | library ieee ;
20 | use ieee.std_logic_1164.all ;
21 | use ieee.numeric_std.all ;
22 |
23 | library work ;
24 | use work.wlan_p.all ;
25 | use work.wlan_tables_p.all ;
26 |
27 | entity wlan_lfsr_tb is
28 | end entity ;
29 |
30 | architecture arch of wlan_lfsr_tb is
31 |
32 | signal clock : std_logic := '1' ;
33 | signal reset : std_logic := '1' ;
34 |
35 | signal init : unsigned(6 downto 0) := (others =>'1') ;
36 | signal init_valid : std_logic := '0' ;
37 |
38 | signal advance : std_logic := '0' ;
39 | signal data : std_logic_vector(7 downto 0) ;
40 | signal data_valid : std_logic ;
41 |
42 | function reverse(x : in std_logic_vector) return std_logic_vector is
43 | variable rv : std_logic_vector(x'range) ;
44 | begin
45 | for i in x'range loop
46 | rv(rv'high-i) := x(i) ;
47 | end loop ;
48 | return rv ;
49 | end function ;
50 |
51 | begin
52 |
53 | clock <= not clock after 0.5 ns ;
54 |
55 | U_lfsr : entity work.wlan_lfsr
56 | generic map (
57 | WIDTH => data'length
58 | ) port map (
59 | clock => clock,
60 | reset => reset,
61 |
62 | init => init,
63 | init_valid => init_valid,
64 |
65 | advance => advance,
66 | data => data,
67 | data_valid => data_valid
68 | ) ;
69 |
70 | tb : process
71 | begin
72 | nop( clock, 100 ) ;
73 | reset <= '0' ;
74 |
75 | nop( clock, 100 ) ;
76 |
77 | init <= "1011101" ; -- L-14 from standard
78 | init_valid <= '1' ;
79 | nop( clock, 1 ) ;
80 |
81 | init_valid <= '0' ;
82 | nop( clock, 100 ) ;
83 |
84 | for i in TABLE_L_13'range loop
85 | advance <= '1' ;
86 | nop( clock, 1 ) ;
87 | end loop ;
88 |
89 | advance <= '0' ;
90 | nop( clock, 100 ) ;
91 |
92 | report "-- End of Simulation --" severity failure ;
93 |
94 | end process ;
95 |
96 | verification : process
97 | variable indata : std_logic_vector(data'range) ;
98 | variable result : std_logic_vector(data'range) ;
99 | variable rev_result : std_logic_vector(data'range) ;
100 | begin
101 | result := (others =>'0') ;
102 | indata := (others =>'0') ;
103 | rev_result := (others =>'0') ;
104 | for i in 0 to TABLE_L_15'high loop
105 | wait until rising_edge(clock) and data_valid = '1' ;
106 | indata := std_logic_vector(to_unsigned(TABLE_L_13(i),data'length));
107 | result := data xor indata ;
108 | -- Location of tail bits that have to be 0 going into Viterbi Encoder
109 | if( i = 102 ) then
110 | result(5 downto 0) := (others =>'0') ;
111 | end if ;
112 | rev_result := reverse(result) ;
113 | assert rev_result = std_logic_vector(to_unsigned(TABLE_L_15(i),result'length))
114 | report "Incorrect scrambling sequence at index " & integer'image(i)
115 | severity error ;
116 | end loop ;
117 | wait ;
118 | end process ;
119 |
120 | end architecture ;
121 |
122 |
--------------------------------------------------------------------------------
/fpga/vhdl/tb/wlan_modulator_tb.vhd:
--------------------------------------------------------------------------------
1 | -- This file is part of bladeRF-wiphy.
2 | --
3 | -- Copyright (C) 2020 Nuand, LLC.
4 | --
5 | -- This program is free software; you can redistribute it and/or modify
6 | -- it under the terms of the GNU General Public License as published by
7 | -- the Free Software Foundation; either version 2 of the License, or
8 | -- (at your option) any later version.
9 | --
10 | -- This program is distributed in the hope that it will be useful,
11 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | -- GNU General Public License for more details.
14 | --
15 | -- You should have received a copy of the GNU General Public License along
16 | -- with this program; if not, write to the Free Software Foundation, Inc.,
17 | -- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 |
19 | library ieee ;
20 | use ieee.std_logic_1164.all ;
21 | use ieee.numeric_std.all ;
22 |
23 | library work ;
24 | use work.wlan_p.all ;
25 | use work.wlan_tables_p.all ;
26 |
27 | entity wlan_modulator_tb is
28 | end entity ;
29 |
30 | architecture arch of wlan_modulator_tb is
31 |
32 | signal clock : std_logic := '1' ;
33 | signal reset : std_logic := '1' ;
34 |
35 | signal init : std_logic := '0' ;
36 |
37 | signal data : std_logic_vector(287 downto 0) := TABLE_L_19 ;
38 | signal modulation : wlan_modulation_t := WLAN_16QAM ;
39 | signal in_valid : std_logic := '0' ;
40 |
41 | signal symbol_start : std_logic ;
42 | signal symbol_end : std_logic ;
43 | signal symbol_sample : wlan_sample_t ;
44 |
45 | signal ifft_sample : wlan_sample_t ;
46 | signal ifft_valid_cp : std_logic ;
47 | signal ifft_done : std_logic ;
48 |
49 | begin
50 |
51 | clock <= not clock after (0.5 sec / 40.0e6) ;
52 |
53 | U_modulator : entity work.wlan_modulator
54 | port map (
55 | clock => clock,
56 | reset => reset,
57 |
58 | init => init,
59 |
60 | data => data,
61 | modulation => modulation,
62 | in_valid => in_valid,
63 |
64 | ifft_ready => '1',
65 |
66 | symbol_start => symbol_start,
67 | symbol_end => symbol_end,
68 | symbol_sample => symbol_sample
69 | ) ;
70 |
71 | U_ifft : entity work.wlan_ifft64
72 | port map (
73 | clock => clock,
74 | reset => reset,
75 |
76 | symbol_start => symbol_start,
77 | symbol_end => symbol_end,
78 | in_sample => symbol_sample,
79 |
80 | out_sample => ifft_sample,
81 | out_valid_cp => ifft_valid_cp,
82 | done => ifft_done
83 | ) ;
84 |
85 | tb : process
86 | begin
87 | reset <= '1' ;
88 | nop( clock, 100 ) ;
89 |
90 | reset <= '0' ;
91 | nop( clock, 100 ) ;
92 |
93 | init <= '1' ;
94 | nop( clock, 1 ) ;
95 | init <= '0' ;
96 | nop( clock, 10 ) ;
97 |
98 | for i in 1 to 10 loop
99 | in_valid <= '1' ;
100 | nop( clock, 1 ) ;
101 | in_valid <= '0' ;
102 | nop( clock, 1 ) ;
103 | wait until rising_edge(clock) and symbol_end = '1' ;
104 | nop( clock, 1 ) ;
105 | end loop ;
106 |
107 | nop( clock, 1000 ) ;
108 | report "-- End of Simulation --" severity failure ;
109 | end process ;
110 |
111 | end architecture ;
112 |
113 |
--------------------------------------------------------------------------------
/fpga/vhdl/tb/wlan_peak_finder_tb.vhd:
--------------------------------------------------------------------------------
1 | -- This file is part of bladeRF-wiphy.
2 | --
3 | -- Copyright (C) 2020 Nuand, LLC.
4 | --
5 | -- This program is free software; you can redistribute it and/or modify
6 | -- it under the terms of the GNU General Public License as published by
7 | -- the Free Software Foundation; either version 2 of the License, or
8 | -- (at your option) any later version.
9 | --
10 | -- This program is distributed in the hope that it will be useful,
11 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | -- GNU General Public License for more details.
14 | --
15 | -- You should have received a copy of the GNU General Public License along
16 | -- with this program; if not, write to the Free Software Foundation, Inc.,
17 | -- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 |
19 | library ieee ;
20 | use ieee.std_logic_1164.all ;
21 | use ieee.numeric_std.all ;
22 |
23 | library work ;
24 | use work.wlan_p.all ;
25 | use work.wlan_tables_p.all ;
26 |
27 | entity wlan_peak_finder_tb is
28 | end entity ;
29 |
30 | architecture arch of wlan_peak_finder_tb is
31 |
32 | signal clock : std_logic := '1' ;
33 | signal reset : std_logic := '1' ;
34 |
35 | signal init : unsigned(6 downto 0) := (others =>'1') ;
36 | signal init_valid : std_logic := '0' ;
37 |
38 | signal advance : std_logic := '0' ;
39 | signal data : std_logic_vector(7 downto 0) ;
40 | signal data_valid : std_logic ;
41 |
42 | signal sample : unsigned( 127 downto 0 ) ;
43 | signal inc : std_logic := '1';
44 | begin
45 |
46 | clock <= not clock after 0.5 ns ;
47 | reset <= '1', '0' after 10 ns;
48 | U_peak_finder : entity work.wlan_peak_finder
49 | port map (
50 | clock => clock,
51 | reset => reset,
52 |
53 | sample => sample,
54 | sample_valid=> '1',
55 | peak => open
56 | ) ;
57 |
58 | process(clock)
59 | begin
60 | if( reset = '1' ) then
61 | sample <= (others => '0') ;
62 | elsif( rising_edge( clock ) ) then
63 | if( inc = '1' ) then
64 | sample <= sample + 1 ;
65 | if (sample = 45) then
66 | inc <= '0';
67 | end if;
68 | else
69 | sample <= sample - 1 ;
70 | end if;
71 | end if;
72 | end process;
73 |
74 | end architecture ;
75 |
76 |
77 |
--------------------------------------------------------------------------------
/fpga/vhdl/tb/wlan_sample_loader.vhd:
--------------------------------------------------------------------------------
1 | -- This file is part of bladeRF-wiphy.
2 | --
3 | -- Copyright (C) 2020 Nuand, LLC.
4 | --
5 | -- This program is free software; you can redistribute it and/or modify
6 | -- it under the terms of the GNU General Public License as published by
7 | -- the Free Software Foundation; either version 2 of the License, or
8 | -- (at your option) any later version.
9 | --
10 | -- This program is distributed in the hope that it will be useful,
11 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | -- GNU General Public License for more details.
14 | --
15 | -- You should have received a copy of the GNU General Public License along
16 | -- with this program; if not, write to the Free Software Foundation, Inc.,
17 | -- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 |
19 | library ieee ;
20 | use ieee.std_logic_1164.all ;
21 | use ieee.numeric_std.all ;
22 |
23 | library std ;
24 | use std.textio.all ;
25 |
26 | library wlan ;
27 | use wlan.wlan_p.all ;
28 |
29 | entity wlan_sample_loader is
30 | generic (
31 | FILENAME : string := "tx"
32 | ) ;
33 | port (
34 | clock : in std_logic ;
35 | fopen : in std_logic ;
36 | sample : out wlan_sample_t ;
37 | ad_ctrl : out std_logic_vector( 7 downto 0 )
38 | ) ;
39 | end entity ;
40 |
41 | architecture arch of wlan_sample_loader is
42 |
43 | begin
44 |
45 | save : process
46 | file f : text ;
47 | variable l : line ;
48 | variable li : integer ;
49 | variable comma : character ;
50 | variable status : file_open_status ;
51 | variable fcount : natural := 0 ;
52 | variable scount : natural := 0 ;
53 | function fname( b : string ; count : natural ) return string is
54 | begin
55 | return b & "-" & integer'image(count) & ".csv" ;
56 | end function ;
57 | begin
58 | wait until rising_edge(clock) and fopen = '1' ;
59 | file_open(status, f, fname( FILENAME, fcount ), read_mode) ;
60 | assert status = OPEN_OK
61 | report "Could not open file: " & fname( FILENAME, fcount )
62 | severity failure ;
63 | scount := 0 ;
64 | while true loop
65 | sample.valid <= '0';
66 | wait until rising_edge(clock) ;
67 | readline( f, l );
68 | read( l, li );
69 | sample.i <= to_signed(li, sample.i'length);
70 |
71 | read( l, comma );
72 |
73 | read( l, li );
74 | sample.q <= to_signed(li, sample.q'length);
75 | sample.valid <= '1';
76 |
77 | read( l, comma );
78 | read( l, li );
79 | ad_ctrl <= std_logic_vector(to_signed(li, ad_ctrl'length));
80 | wait until rising_edge(clock) ;
81 | scount := scount + 1 ;
82 | if( endfile( f ) ) then
83 | file_close( f ) ;
84 | write( output, "Read " & integer'image(scount) & " samples from " & fname( FILENAME, fcount ) & CR ) ;
85 | fcount := fcount + 1 ;
86 | exit ;
87 | end if ;
88 | end loop ;
89 | end process ;
90 |
91 | end architecture ;
92 |
93 |
--------------------------------------------------------------------------------
/fpga/vhdl/tb/wlan_sample_saver.vhd:
--------------------------------------------------------------------------------
1 | -- This file is part of bladeRF-wiphy.
2 | --
3 | -- Copyright (C) 2020 Nuand, LLC.
4 | --
5 | -- This program is free software; you can redistribute it and/or modify
6 | -- it under the terms of the GNU General Public License as published by
7 | -- the Free Software Foundation; either version 2 of the License, or
8 | -- (at your option) any later version.
9 | --
10 | -- This program is distributed in the hope that it will be useful,
11 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | -- GNU General Public License for more details.
14 | --
15 | -- You should have received a copy of the GNU General Public License along
16 | -- with this program; if not, write to the Free Software Foundation, Inc.,
17 | -- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 |
19 | library ieee ;
20 | use ieee.std_logic_1164.all ;
21 | use ieee.numeric_std.all ;
22 |
23 | library std ;
24 | use std.textio.all ;
25 |
26 | library work ;
27 | use work.wlan_p.all ;
28 |
29 | entity wlan_sample_saver is
30 | generic (
31 | FILENAME : string := "samples"
32 | ) ;
33 | port (
34 | clock : in std_logic ;
35 | fopen : in std_logic ;
36 | sample : in wlan_sample_t ;
37 | done : in std_logic
38 | ) ;
39 | end entity ;
40 |
41 | architecture arch of wlan_sample_saver is
42 |
43 | begin
44 |
45 | save : process
46 | file f : text ;
47 | variable l : line ;
48 | variable status : file_open_status ;
49 | variable fcount : natural := 0 ;
50 | variable scount : natural := 0 ;
51 | function fname( b : string ; count : natural ) return string is
52 | begin
53 | return b & "-" & integer'image(count) & ".csv" ;
54 | end function ;
55 | begin
56 | wait until rising_edge(clock) and fopen = '1' ;
57 | file_open(status, f, fname( FILENAME, fcount ), write_mode) ;
58 | assert status = OPEN_OK
59 | report "Could not open file: " & fname( FILENAME, fcount )
60 | severity failure ;
61 | scount := 0 ;
62 | while true loop
63 | wait until rising_edge(clock) and sample.valid = '1' ;
64 | write( l, to_integer(sample.i) ) ;
65 | write( l, ',' ) ;
66 | write( l, to_integer(sample.q) ) ;
67 | writeline( f, l ) ;
68 | flush( f ) ;
69 | scount := scount + 1 ;
70 | if( done = '1' ) then
71 | file_close( f ) ;
72 | write( output, "Wrote " & integer'image(scount) & " samples to " & fname( FILENAME, fcount ) & CR ) ;
73 | fcount := fcount + 1 ;
74 | exit ;
75 | end if ;
76 | end loop ;
77 | end process ;
78 |
79 | end architecture ;
80 |
81 |
--------------------------------------------------------------------------------
/fpga/vhdl/tb/wlan_symbol_shaper_tb.vhd:
--------------------------------------------------------------------------------
1 | -- This file is part of bladeRF-wiphy.
2 | --
3 | -- Copyright (C) 2020 Nuand, LLC.
4 | --
5 | -- This program is free software; you can redistribute it and/or modify
6 | -- it under the terms of the GNU General Public License as published by
7 | -- the Free Software Foundation; either version 2 of the License, or
8 | -- (at your option) any later version.
9 | --
10 | -- This program is distributed in the hope that it will be useful,
11 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | -- GNU General Public License for more details.
14 | --
15 | -- You should have received a copy of the GNU General Public License along
16 | -- with this program; if not, write to the Free Software Foundation, Inc.,
17 | -- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 |
19 | library ieee ;
20 | use ieee.std_logic_1164.all ;
21 | use ieee.numeric_std.all ;
22 |
23 | library work ;
24 | use work.wlan_p.all ;
25 |
26 | entity wlan_symbol_shaper_tb is
27 | end entity ;
28 |
29 | architecture arch of wlan_symbol_shaper_tb is
30 |
31 | signal clock : std_logic := '1' ;
32 | signal reset : std_logic := '1' ;
33 |
34 | signal cp_i : signed(15 downto 0) := (others =>'0') ;
35 | signal cp_q : signed(15 downto 0) := (others =>'0') ;
36 | signal cp_re : std_logic ;
37 | signal cp_empty : std_logic := '1' ;
38 |
39 | signal sample_i : signed(15 downto 0) := (others =>'0') ;
40 | signal sample_q : signed(15 downto 0) := (others =>'0') ;
41 | signal sample_re : std_logic ;
42 | signal sample_empty : std_logic := '1' ;
43 |
44 | signal out_sample : wlan_sample_t ;
45 | signal done : std_logic ;
46 |
47 | begin
48 |
49 | clock <= not clock after (0.5 / 40.0e6) * 1 sec ;
50 |
51 | U_shaper : entity work.wlan_symbol_shaper
52 | port map (
53 | clock => clock,
54 | reset => reset,
55 |
56 | cp_i => cp_i,
57 | cp_q => cp_q,
58 | cp_re => cp_re,
59 | cp_empty => cp_empty,
60 |
61 | sample_i => sample_i,
62 | sample_q => sample_q,
63 | sample_re => sample_re,
64 | sample_empty => sample_empty,
65 |
66 | out_sample => out_sample,
67 | done => done
68 | ) ;
69 |
70 | tb : process
71 | begin
72 | reset <= '1' ;
73 | nop(clock, 100) ;
74 |
75 | reset <= '0' ;
76 | nop(clock, 100) ;
77 |
78 | nop(clock,10000) ;
79 |
80 | report "-- End of Simulation --" severity failure ;
81 | end process ;
82 |
83 | emulate_cp : process
84 | variable count : natural := 1 ;
85 | begin
86 | wait until rising_edge(clock) and reset = '0' ;
87 | nop(clock, 100) ;
88 | cp_empty <= '0' ;
89 | -- Long sequence CP
90 | cp_i <= to_signed(1, cp_i'length) ;
91 | cp_q <= to_signed(1, cp_q'length) ;
92 | for i in 1 to 32 loop
93 | wait until rising_edge(clock) and cp_re = '1' ;
94 | end loop ;
95 |
96 | -- 10 data symbols
97 | for i in 1 to 10 loop
98 | cp_i <= cp_i + 1 ;
99 | cp_q <= cp_q + 1 ;
100 | for i in 1 to 16 loop
101 | wait until rising_edge(clock) and cp_re = '1' ;
102 | end loop ;
103 | end loop ;
104 |
105 | -- 11th data symbol is the last
106 | cp_i <= cp_i + 1 ;
107 | cp_q <= cp_q + 1 ;
108 | for i in 1 to 15 loop
109 | wait until rising_edge(clock) and cp_re = '1' ;
110 | end loop ;
111 | cp_empty <= '1' ;
112 | wait until rising_edge(clock) and cp_re = '1' ;
113 | nop(clock, 100) ;
114 | wait ;
115 | end process ;
116 |
117 | emulate_sample : process
118 | variable count : natural := 0 ;
119 | begin
120 | wait until rising_edge(clock) and reset = '0' ;
121 | nop(clock, 100) ;
122 | -- Short sequence
123 | count := 160 ;
124 | sample_empty <= '0' ;
125 | sample_i <= to_signed(0, sample_i'length) ;
126 | sample_q <= to_signed(0, sample_q'length) ;
127 | for i in 1 to 160 loop
128 | wait until rising_edge(clock) and sample_re = '1' ;
129 | end loop ;
130 | -- Long sequence
131 | sample_i <= sample_i + 1 ;
132 | sample_q <= sample_q + 1 ;
133 | for i in 1 to 128 loop
134 | wait until rising_edge(clock) and sample_re = '1' ;
135 | end loop ;
136 |
137 | -- 10 data symbols
138 | for i in 1 to 10 loop
139 | sample_i <= sample_i + 1 ;
140 | sample_q <= sample_q + 1 ;
141 | for i in 1 to 64 loop
142 | wait until rising_edge(clock) and sample_re = '1' ;
143 | end loop ;
144 | end loop ;
145 |
146 | -- 11th symbol is the last one
147 | sample_i <= sample_i + 1 ;
148 | sample_q <= sample_q + 1 ;
149 | for i in 1 to 63 loop
150 | wait until rising_edge(clock) and sample_re = '1' ;
151 | end loop ;
152 | sample_empty <= '1' ;
153 | wait until rising_edge(clock) and sample_re = '1' ;
154 |
155 | nop(clock, 100) ;
156 | wait ;
157 | end process ;
158 |
159 | end architecture ;
160 |
161 |
--------------------------------------------------------------------------------
/fpga/vhdl/tb/wlan_tb.vhd:
--------------------------------------------------------------------------------
1 | -- This file is part of bladeRF-wiphy.
2 | --
3 | -- Copyright (C) 2020 Nuand, LLC.
4 | --
5 | -- This program is free software; you can redistribute it and/or modify
6 | -- it under the terms of the GNU General Public License as published by
7 | -- the Free Software Foundation; either version 2 of the License, or
8 | -- (at your option) any later version.
9 | --
10 | -- This program is distributed in the hope that it will be useful,
11 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | -- GNU General Public License for more details.
14 | --
15 | -- You should have received a copy of the GNU General Public License along
16 | -- with this program; if not, write to the Free Software Foundation, Inc.,
17 | -- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 |
19 | library ieee ;
20 | use ieee.std_logic_1164.all ;
21 | use ieee.numeric_std.all ;
22 | use ieee.math_real.all ;
23 |
24 | library work ;
25 | use work.wlan_p.all ;
26 | use work.wlan_rx_p.all ;
27 | use work.wlan_tx_p.all ;
28 |
29 | entity wlan_tb is
30 | end entity ;
31 |
32 | architecture arch of wlan_tb is
33 |
34 | begin
35 |
36 | end architecture ;
37 |
38 |
--------------------------------------------------------------------------------
/fpga/vhdl/tb/wlan_tx_long_tb.vhd:
--------------------------------------------------------------------------------
1 | -- This file is part of bladeRF-wiphy.
2 | --
3 | -- Copyright (C) 2020 Nuand, LLC.
4 | --
5 | -- This program is free software; you can redistribute it and/or modify
6 | -- it under the terms of the GNU General Public License as published by
7 | -- the Free Software Foundation; either version 2 of the License, or
8 | -- (at your option) any later version.
9 | --
10 | -- This program is distributed in the hope that it will be useful,
11 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | -- GNU General Public License for more details.
14 | --
15 | -- You should have received a copy of the GNU General Public License along
16 | -- with this program; if not, write to the Free Software Foundation, Inc.,
17 | -- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 |
19 | library ieee ;
20 | use ieee.std_logic_1164.all ;
21 | use ieee.numeric_std.all ;
22 |
23 | library work ;
24 | use work.wlan_p.all ;
25 | use work.wlan_tx_p.all ;
26 |
27 | entity wlan_tx_long_tb is
28 | end entity ;
29 |
30 | architecture arch of wlan_tx_long_tb is
31 |
32 | signal clock : std_logic := '1' ;
33 | signal reset : std_logic := '1' ;
34 | signal start : std_logic := '0' ;
35 | signal done : std_logic ;
36 | signal sample : wlan_sample_t ;
37 | signal valid_cp : std_logic ;
38 |
39 | begin
40 |
41 | clock <= not clock after 1 ns ;
42 |
43 | U_tx_long : entity work.wlan_tx_long
44 | port map (
45 | clock => clock,
46 | reset => reset,
47 | start => start,
48 | done => done,
49 | out_sample => sample,
50 | out_valid_cp => valid_cp
51 | ) ;
52 |
53 | tb : process
54 | begin
55 | reset <= '1' ;
56 | nop(clock, 100) ;
57 |
58 | reset <= '0' ;
59 | nop(clock, 100) ;
60 |
61 | start <= '1' ;
62 | nop(clock, 1) ;
63 | start <= '0' ;
64 | nop(clock, 1) ;
65 |
66 | nop(clock, 1000 ) ;
67 |
68 | report "-- End of Simulation --" severity failure ;
69 | end process ;
70 |
71 | end architecture ;
72 |
73 |
--------------------------------------------------------------------------------
/fpga/vhdl/tb/wlan_tx_short_tb.vhd:
--------------------------------------------------------------------------------
1 | -- This file is part of bladeRF-wiphy.
2 | --
3 | -- Copyright (C) 2020 Nuand, LLC.
4 | --
5 | -- This program is free software; you can redistribute it and/or modify
6 | -- it under the terms of the GNU General Public License as published by
7 | -- the Free Software Foundation; either version 2 of the License, or
8 | -- (at your option) any later version.
9 | --
10 | -- This program is distributed in the hope that it will be useful,
11 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | -- GNU General Public License for more details.
14 | --
15 | -- You should have received a copy of the GNU General Public License along
16 | -- with this program; if not, write to the Free Software Foundation, Inc.,
17 | -- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 |
19 | library ieee ;
20 | use ieee.std_logic_1164.all ;
21 | use ieee.numeric_std.all ;
22 |
23 | library work ;
24 | use work.wlan_p.all ;
25 | use work.wlan_tx_p.all ;
26 |
27 | entity wlan_tx_short_tb is
28 | end entity ;
29 |
30 | architecture arch of wlan_tx_short_tb is
31 |
32 | signal clock : std_logic := '1' ;
33 | signal reset : std_logic := '1' ;
34 | signal start : std_logic := '0' ;
35 | signal done : std_logic ;
36 | signal sample : wlan_sample_t ;
37 |
38 | begin
39 |
40 | clock <= not clock after 1 ns ;
41 |
42 | U_tx_short : entity work.wlan_tx_short
43 | port map (
44 | clock => clock,
45 | reset => reset,
46 | start => start,
47 | done => done,
48 | out_sample => sample
49 | ) ;
50 |
51 | tb : process
52 | begin
53 | reset <= '1' ;
54 | nop(clock, 100) ;
55 |
56 | reset <= '0' ;
57 | nop(clock, 100) ;
58 |
59 | start <= '1' ;
60 | nop(clock, 1) ;
61 | start <= '0' ;
62 | nop(clock, 1) ;
63 |
64 | nop(clock, 1000 ) ;
65 |
66 | report "-- End of Simulation --" severity failure ;
67 | end process ;
68 |
69 | end architecture ;
70 |
71 |
--------------------------------------------------------------------------------
/fpga/vhdl/wlan_ack_generator.vhd:
--------------------------------------------------------------------------------
1 | -- This file is part of bladeRF-wiphy.
2 | --
3 | -- Copyright (C) 2020 Nuand, LLC.
4 | --
5 | -- This program is free software; you can redistribute it and/or modify
6 | -- it under the terms of the GNU General Public License as published by
7 | -- the Free Software Foundation; either version 2 of the License, or
8 | -- (at your option) any later version.
9 | --
10 | -- This program is distributed in the hope that it will be useful,
11 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | -- GNU General Public License for more details.
14 | --
15 | -- You should have received a copy of the GNU General Public License along
16 | -- with this program; if not, write to the Free Software Foundation, Inc.,
17 | -- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 |
19 | library ieee ;
20 | use ieee.std_logic_1164.all ;
21 | use ieee.numeric_std.all ;
22 |
23 | library wlan;
24 | use wlan.wlan_p.all ;
25 | use wlan.wlan_tx_p.all ;
26 | use wlan.wlan_rx_p.all ;
27 |
28 | library altera_mf ;
29 | use altera_mf.altera_mf_components.all ;
30 |
31 | entity wlan_ack_generator is
32 | port (
33 | wclock : in std_logic ;
34 | wreset : in std_logic ;
35 |
36 | ack_mac : in std_logic_vector( 47 downto 0 );
37 | ack_valid : in std_logic ;
38 |
39 | rclock : in std_logic ;
40 | rreset : in std_logic ;
41 |
42 | fifo_data : out std_logic_vector( 7 downto 0 );
43 | fifo_re : in std_logic ;
44 | done_tx : in std_logic ;
45 |
46 | ack_ready : out std_logic
47 | ) ;
48 | end entity ;
49 |
50 | architecture arch of wlan_ack_generator is
51 | signal wfull : std_logic ;
52 | signal rempty : std_logic ;
53 | signal rread : std_logic ;
54 |
55 | type fsm_t is (IDLE, READ, DONE);
56 |
57 | type state_t is record
58 | fsm : fsm_t;
59 | payload : std_logic_vector( 79 downto 0 );
60 | rread : std_logic ;
61 | byte_idx : natural range 0 to 10 ;
62 | end record ;
63 |
64 | signal current_state : state_t;
65 | signal future_state : state_t;
66 |
67 | function NULL_STATE return state_t is
68 | variable rv : state_t;
69 | begin
70 | rv.fsm := IDLE ;
71 | rv.payload := (others => '0' ) ;
72 | rv.rread := '0' ;
73 | rv.byte_idx := 0 ;
74 |
75 | return rv ;
76 | end function ;
77 |
78 | signal mac_address : std_logic_vector( 47 downto 0 );
79 | begin
80 |
81 | U_mac_dc_fifo: dcfifo
82 | generic map (
83 | lpm_width => 48,
84 | lpm_widthu => 4,
85 | lpm_numwords => 16,
86 | lpm_showahead => "ON"
87 | )
88 | port map (
89 | aclr => wreset or rreset,
90 |
91 | wrclk => wclock,
92 | wrreq => ack_valid and not wfull,
93 | data => ack_mac,
94 |
95 | wrfull => wfull,
96 | wrempty => open,
97 | wrusedw => open,
98 |
99 | rdclk => rclock,
100 | rdreq => rread,
101 | q => mac_address,
102 |
103 | rdfull => open,
104 | rdempty => rempty,
105 | rdusedw => open
106 | ) ;
107 |
108 | ack_ready <= not rempty;
109 | fifo_data <= current_state.payload(79 downto 72);
110 | rread <= current_state.rread;
111 |
112 | process(all)
113 | begin
114 | future_state <= current_state ;
115 |
116 | future_state.rread <= '0';
117 |
118 | case current_state.fsm is
119 |
120 | when IDLE =>
121 | future_state.payload <= x"D400" & x"0000" & mac_address;
122 | if( fifo_re = '1' and rempty = '0' ) then
123 | future_state.fsm <= READ ;
124 | future_state.byte_idx <= 0 ;
125 | future_state.rread <= '1' ;
126 | future_state.payload <= current_state.payload(71 downto 0) & x"00";
127 | else
128 | future_state.payload <= x"D400" & x"0000" & mac_address;
129 | end if;
130 |
131 | when READ =>
132 | if( fifo_re = '1' ) then
133 | future_state.byte_idx <= current_state.byte_idx + 1;
134 | future_state.payload <= current_state.payload(71 downto 0) & x"00";
135 | if( current_state.byte_idx = 9 ) then
136 | future_state.fsm <= DONE ;
137 | end if;
138 | end if;
139 |
140 | when DONE =>
141 | if (done_tx = '1') then
142 | future_state.fsm <= IDLE ;
143 | end if ;
144 | future_state.byte_idx <= 0 ;
145 |
146 | when others =>
147 | future_state <= NULL_STATE ;
148 |
149 | end case;
150 |
151 | end process;
152 |
153 | process(rclock, rreset)
154 | begin
155 | if( rreset = '1' ) then
156 | current_state <= NULL_STATE ;
157 | elsif( rising_edge( rclock ) ) then
158 | current_state <= future_state ;
159 | end if;
160 | end process;
161 |
162 | end architecture ;
163 |
164 |
--------------------------------------------------------------------------------
/fpga/vhdl/wlan_cfo_correction.vhd:
--------------------------------------------------------------------------------
1 | -- This file is part of bladeRF-wiphy.
2 | --
3 | -- Copyright (C) 2020 Nuand, LLC.
4 | --
5 | -- This program is free software; you can redistribute it and/or modify
6 | -- it under the terms of the GNU General Public License as published by
7 | -- the Free Software Foundation; either version 2 of the License, or
8 | -- (at your option) any later version.
9 | --
10 | -- This program is distributed in the hope that it will be useful,
11 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | -- GNU General Public License for more details.
14 | --
15 | -- You should have received a copy of the GNU General Public License along
16 | -- with this program; if not, write to the Free Software Foundation, Inc.,
17 | -- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 |
19 | library ieee ;
20 | use ieee.std_logic_1164.all ;
21 | use ieee.numeric_std.all ;
22 | use ieee.math_real.all ;
23 |
24 | library wlan ;
25 | use wlan.wlan_p.all ;
26 | use wlan.wlan_rx_p.all ;
27 | use wlan.cordic_p.all ;
28 | use wlan.nco_p.all ;
29 |
30 | entity wlan_cfo_correction is
31 | port (
32 | clock : in std_logic ;
33 | reset : in std_logic ;
34 |
35 | dphase : in signed( 15 downto 0 ) ;
36 | dphase_valid : in std_logic ;
37 |
38 | p_mag : in signed( 23 downto 0 ) ;
39 | p_mag_valid : in std_logic ;
40 |
41 | in_sample : in wlan_sample_t ;
42 | out_sample : out wlan_sample_t
43 | ) ;
44 | end entity;
45 |
46 | architecture arch of wlan_cfo_correction is
47 | signal nco_inputs : nco_input_t ;
48 | signal nco_outputs : nco_output_t ;
49 | begin
50 |
51 | U_nco : entity work.nco
52 | port map (
53 | clock => clock,
54 | reset => reset,
55 | inputs => nco_inputs,
56 | outputs => nco_outputs
57 | ) ;
58 |
59 | process( clock )
60 | begin
61 | if( rising_edge( clock ) ) then
62 | nco_inputs.valid <= in_sample.valid ;
63 | out_sample.valid <= in_sample.valid ;
64 | if( in_sample.valid = '1' ) then
65 | if( p_mag_valid = '0' ) then
66 | out_sample.i <= in_sample.i ;
67 | out_sample.q <= in_sample.q ;
68 | else
69 | out_sample.i <= resize( shift_right( in_sample.i * p_mag , 15 ), 16 ) ;
70 | out_sample.q <= resize( shift_right( in_sample.q * p_mag , 15 ), 16 ) ;
71 | end if ;
72 | end if ;
73 | end if ;
74 | end process ;
75 | end architecture ;
76 |
--------------------------------------------------------------------------------
/fpga/vhdl/wlan_correlator.vhd:
--------------------------------------------------------------------------------
1 | -- This file is part of bladeRF-wiphy.
2 | --
3 | -- Copyright (C) 2020 Nuand, LLC.
4 | --
5 | -- This program is free software; you can redistribute it and/or modify
6 | -- it under the terms of the GNU General Public License as published by
7 | -- the Free Software Foundation; either version 2 of the License, or
8 | -- (at your option) any later version.
9 | --
10 | -- This program is distributed in the hope that it will be useful,
11 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | -- GNU General Public License for more details.
14 | --
15 | -- You should have received a copy of the GNU General Public License along
16 | -- with this program; if not, write to the Free Software Foundation, Inc.,
17 | -- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 |
19 | library ieee ;
20 | use ieee.std_logic_1164.all ;
21 | use ieee.numeric_std.all ;
22 |
23 | library wlan ;
24 | use wlan.wlan_p.all ;
25 | use wlan.wlan_rx_p.all ;
26 |
27 | entity wlan_correlator is
28 | port (
29 | clock : in std_logic ;
30 | reset : in std_logic ;
31 |
32 | sample : in wlan_sample_t ;
33 | value : out signed( 31 downto 0 )
34 | ) ;
35 | end entity ;
36 |
37 | architecture arch of wlan_correlator is
38 |
39 | constant preamble : sample_array_t( 15 downto 0 ) := (
40 | (valid => '1', i => to_signed( 269, 16), q => to_signed( 269, 16)),
41 | (valid => '1', i => to_signed(-775, 16), q => to_signed( 14, 16)),
42 | (valid => '1', i => to_signed( -79, 16), q => to_signed(-460, 16)),
43 | (valid => '1', i => to_signed( 835, 16), q => to_signed( -74, 16)),
44 | (valid => '1', i => to_signed( 538, 16), q => to_signed( 0, 16)),
45 | (valid => '1', i => to_signed( 835, 16), q => to_signed( -74, 16)),
46 | (valid => '1', i => to_signed( -79, 16), q => to_signed(-460, 16)),
47 | (valid => '1', i => to_signed(-775, 16), q => to_signed( 14, 16)),
48 | (valid => '1', i => to_signed( 269, 16), q => to_signed( 269, 16)),
49 | (valid => '1', i => to_signed( 14, 16), q => to_signed(-775, 16)),
50 | (valid => '1', i => to_signed(-460, 16), q => to_signed( -79, 16)),
51 | (valid => '1', i => to_signed( -74, 16), q => to_signed( 835, 16)),
52 | (valid => '1', i => to_signed( 0, 16), q => to_signed( 538, 16)),
53 | (valid => '1', i => to_signed( -74, 16), q => to_signed( 835, 16)),
54 | (valid => '1', i => to_signed(-460, 16), q => to_signed( -79, 16)),
55 | (valid => '1', i => to_signed( 14, 16), q => to_signed(-775, 16))
56 | );
57 |
58 | type correlator_result_t is record
59 | i : signed(15 downto 0) ;
60 | q : signed(15 downto 0) ;
61 | valid : std_logic ;
62 | end record ;
63 |
64 | type eq_array_t is array(natural range <>) of correlator_result_t ;
65 | signal accum : eq_array_t(15 downto 0);
66 |
67 | begin
68 |
69 | process( clock )
70 | variable isum : signed( 100 downto 0 ) ;
71 | variable qsum : signed( 100 downto 0 ) ;
72 | begin
73 | if( reset = '1' ) then
74 | value <= ( others => '0' ) ;
75 | elsif( rising_edge( clock ) ) then
76 | if( sample.valid = '1' ) then
77 | for i in accum'range loop
78 | if i = accum'high then
79 | accum(i).i <= resize(shift_right(preamble(i).i*sample.i + preamble(i).q*sample.q, 14),16);
80 | accum(i).q <= resize(shift_right(- preamble(i).q*sample.i + preamble(i).i*sample.q, 14),16);
81 | else
82 | accum(i).i <= resize(accum(i+1).i + shift_right(preamble(i).i*sample.i + preamble(i).q*sample.q, 14),16);
83 | accum(i).q <= resize(accum(i+1).q + shift_right(- preamble(i).q*sample.i + preamble(i).i*sample.q, 14),16);
84 | end if;
85 | end loop;
86 | value <= resize(accum(0).i * accum(0).i + accum(0).q * accum(0).q,32);
87 |
88 | end if ;
89 | end if ;
90 | end process ;
91 |
92 | end architecture ;
93 |
--------------------------------------------------------------------------------
/fpga/vhdl/wlan_csma.vhd:
--------------------------------------------------------------------------------
1 | -- This file is part of bladeRF-wiphy.
2 | --
3 | -- Copyright (C) 2020 Nuand, LLC.
4 | --
5 | -- This program is free software; you can redistribute it and/or modify
6 | -- it under the terms of the GNU General Public License as published by
7 | -- the Free Software Foundation; either version 2 of the License, or
8 | -- (at your option) any later version.
9 | --
10 | -- This program is distributed in the hope that it will be useful,
11 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | -- GNU General Public License for more details.
14 | --
15 | -- You should have received a copy of the GNU General Public License along
16 | -- with this program; if not, write to the Free Software Foundation, Inc.,
17 | -- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 |
19 | library ieee ;
20 | use ieee.std_logic_1164.all ;
21 | use ieee.numeric_std.all ;
22 |
23 | library wlan ;
24 | use wlan.wlan_p.all ;
25 | use wlan.wlan_rx_p.all ;
26 |
27 | entity wlan_csma is
28 | port (
29 | clock : in std_logic ;
30 | reset : in std_logic ;
31 |
32 | in_sample : in wlan_sample_t ;
33 |
34 | quiet : out std_logic
35 | ) ;
36 | end entity ;
37 |
38 | architecture arch of wlan_csma is
39 | type fsm_t is (IDLE, CAPTURE_PHY_NOISE, CSMA) ;
40 |
41 | type unsigned_array_t is array (natural range 0 to 79) of unsigned( 31 downto 0 ) ;
42 | type state_t is record
43 | fsm : fsm_t ;
44 | quiet : std_logic ;
45 | timer : unsigned( 23 downto 0 ) ;
46 | powersum : unsigned( 31 downto 0 ) ;
47 | min_phy_noise : unsigned( 31 downto 0 ) ;
48 | history : unsigned_array_t ;
49 | end record ;
50 |
51 | function NULL_STATE return state_t is
52 | variable rv : state_t ;
53 | begin
54 | rv.fsm := IDLE ;
55 | rv.timer := ( others => '0' ) ;
56 | rv.min_phy_noise := ( others => '1' ) ;
57 | rv.powersum := ( others => '0' ) ;
58 | for i in rv.history'range loop
59 | rv.history(i) := ( others => '0' ) ;
60 | end loop ;
61 | return rv ;
62 | end function ;
63 |
64 | signal current, future : state_t := NULL_STATE ;
65 |
66 | begin
67 |
68 | quiet <= current.quiet ;
69 |
70 | sync : process( clock )
71 | begin
72 | if( reset = '1' ) then
73 | current <= NULL_STATE ;
74 | elsif( rising_edge( clock ) ) then
75 | current <= future ;
76 | end if ;
77 | end process ;
78 |
79 | comb: process(all)
80 | begin
81 | future <= current ;
82 |
83 | case current.fsm is
84 | when IDLE =>
85 | future.fsm <= CAPTURE_PHY_NOISE ;
86 | future.quiet <= '0' ;
87 | when CAPTURE_PHY_NOISE =>
88 | future.quiet <= '0' ;
89 | --if( current.timer > 100000 ) then
90 | if( current.timer > 110 ) then
91 | future.fsm <= CSMA ;
92 | future.powersum <= ( others => '0' ) ;
93 | for i in future.history'range loop
94 | future.history(i) <= ( others => '0' ) ;
95 | end loop ;
96 | future.timer <= ( others => '0' ) ;
97 | end if ;
98 |
99 | if( in_sample.valid = '1' ) then
100 | future.timer <= current.timer + 1 ;
101 | for i in 0 to current.history'high - 1 loop
102 | future.history( i + 1 ) <= current.history( i ) ;
103 | end loop ;
104 | future.history(0) <= unsigned(resize(in_sample.i * in_sample.i + in_sample.q * in_sample.q, 32 ));
105 | future.powersum <= current.powersum + current.history(0)
106 | - current.history(79);
107 | if( current.timer > 100 ) then
108 | if( current.powersum < current.min_phy_noise ) then
109 | future.min_phy_noise <= current.powersum ;
110 | end if ;
111 | end if ;
112 | end if ;
113 | when CSMA =>
114 | if( in_sample.valid = '1' ) then
115 | for i in 0 to current.history'high - 1 loop
116 | future.history( i + 1 ) <= current.history( i ) ;
117 | end loop ;
118 | future.history(0) <= unsigned(resize(in_sample.i * in_sample.i + in_sample.q * in_sample.q, 32 ));
119 | future.powersum <= current.powersum + current.history(0)
120 | - current.history(9);
121 |
122 | if( current.timer > 20 ) then
123 | if( (current.min_phy_noise / 8 ) * 4 > current.powersum ) then
124 | future.quiet <= '1' ;
125 | else
126 | future.quiet <= '0' ;
127 | end if ;
128 | else
129 | future.timer <= current.timer + 1 ;
130 | end if ;
131 | end if ;
132 | end case ;
133 | end process ;
134 | end architecture ;
135 |
--------------------------------------------------------------------------------
/fpga/vhdl/wlan_deinterleaver.vhd:
--------------------------------------------------------------------------------
1 | -- This file is part of bladeRF-wiphy.
2 | --
3 | -- Copyright (C) 2020 Nuand, LLC.
4 | --
5 | -- This program is free software; you can redistribute it and/or modify
6 | -- it under the terms of the GNU General Public License as published by
7 | -- the Free Software Foundation; either version 2 of the License, or
8 | -- (at your option) any later version.
9 | --
10 | -- This program is distributed in the hope that it will be useful,
11 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | -- GNU General Public License for more details.
14 | --
15 | -- You should have received a copy of the GNU General Public License along
16 | -- with this program; if not, write to the Free Software Foundation, Inc.,
17 | -- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 |
19 | library ieee ;
20 | use ieee.std_logic_1164.all ;
21 | use ieee.numeric_std.all ;
22 |
23 | library work ;
24 | use work.wlan_p.all ;
25 | use work.wlan_interleaver_p.all ;
26 |
27 | entity wlan_deinterleaver is
28 | port (
29 | clock : in std_logic ;
30 | reset : in std_logic ;
31 |
32 | modulation : in wlan_modulation_t ;
33 | data : in bsd_array_t(287 downto 0) ;
34 | in_valid : in std_logic ;
35 |
36 | depuncturer_empty : in std_logic ;
37 |
38 | deinterleaved_mod : out wlan_modulation_t ;
39 | deinterleaved : out bsd_array_t(287 downto 0) ;
40 | deinterleaved_valid : out std_logic
41 | ) ;
42 | end entity ;
43 |
44 | architecture arch of wlan_deinterleaver is
45 | signal data_new : std_logic ;
46 | signal data_r : bsd_array_t(287 downto 0) ;
47 | begin
48 |
49 | permute_bits : process(clock, reset)
50 | begin
51 | if( reset = '1' ) then
52 | deinterleaved <= (others =>(others =>'0')) ;
53 | deinterleaved_mod <= WLAN_BPSK ;
54 | deinterleaved_valid <= '0' ;
55 | data_new <= '0' ;
56 | elsif( rising_edge(clock) ) then
57 | deinterleaved_valid <= '0' ;
58 | if( in_valid = '1' ) then
59 | data_r <= data ;
60 | data_new <= '1' ;
61 | end if;
62 | if( depuncturer_empty = '1' and data_new = '1' ) then
63 | data_new <= '0' ;
64 | deinterleaved_valid <= '1' ;
65 | deinterleaved <= deinterleave(modulation, data) ;
66 | if( modulation = WLAN_BPSK ) then
67 | deinterleaved( 287 downto 48 ) <= (others =>(others => '0' )) ;
68 | end if ;
69 | deinterleaved_mod <= modulation ;
70 | end if ;
71 | end if ;
72 | end process ;
73 |
74 | end architecture ;
75 |
76 |
--------------------------------------------------------------------------------
/fpga/vhdl/wlan_delay_correlator.vhd:
--------------------------------------------------------------------------------
1 | -- This file is part of bladeRF-wiphy.
2 | --
3 | -- Copyright (C) 2020 Nuand, LLC.
4 | --
5 | -- This program is free software; you can redistribute it and/or modify
6 | -- it under the terms of the GNU General Public License as published by
7 | -- the Free Software Foundation; either version 2 of the License, or
8 | -- (at your option) any later version.
9 | --
10 | -- This program is distributed in the hope that it will be useful,
11 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | -- GNU General Public License for more details.
14 | --
15 | -- You should have received a copy of the GNU General Public License along
16 | -- with this program; if not, write to the Free Software Foundation, Inc.,
17 | -- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 |
19 | library ieee ;
20 | use ieee.std_logic_1164.all ;
21 | use ieee.numeric_std.all ;
22 |
23 | library wlan ;
24 | use wlan.wlan_p.all ;
25 | use wlan.wlan_rx_p.all ;
26 |
27 | entity wlan_delay_correlator is
28 | generic (
29 | SAMPLE_DELTA : integer
30 | ) ;
31 | port (
32 | clock : in std_logic ;
33 | reset : in std_logic ;
34 |
35 | sample : in wlan_sample_t ;
36 | value : out signed( 127 downto 0 )
37 | ) ;
38 | end entity ;
39 |
40 | architecture arch of wlan_delay_correlator is
41 |
42 | signal samples : sample_array_t( 0 to SAMPLE_DELTA * 2 - 1 ) ;
43 |
44 | begin
45 |
46 | process( clock )
47 | variable isum : signed( 63 downto 0 ) ;
48 | variable qsum : signed( 63 downto 0 ) ;
49 | begin
50 | if( rising_edge( clock ) ) then
51 | if( sample.valid = '1' ) then
52 | for i in 0 to samples'high - 1 loop
53 | samples(i+1) <= samples(i) ;
54 | end loop ;
55 | samples(0) <= sample ;
56 |
57 | isum := (others => '0') ;
58 | qsum := (others => '0') ;
59 | for i in 0 to SAMPLE_DELTA - 1 loop
60 | isum := isum + samples(i).i * samples(i + SAMPLE_DELTA).i +
61 | samples(i).q * samples(i + SAMPLE_DELTA).q ;
62 | qsum := qsum - samples(i).i * samples(i + SAMPLE_DELTA).q +
63 | samples(i).q * samples(i + SAMPLE_DELTA).i ;
64 | end loop ;
65 | value <= isum * isum + qsum * qsum ;
66 | end if ;
67 | end if ;
68 | end process ;
69 |
70 | end architecture ;
71 |
72 |
--------------------------------------------------------------------------------
/fpga/vhdl/wlan_divide.vhd:
--------------------------------------------------------------------------------
1 | -- This file is part of bladeRF-wiphy.
2 | --
3 | -- Copyright (C) 2020 Nuand, LLC.
4 | --
5 | -- This program is free software; you can redistribute it and/or modify
6 | -- it under the terms of the GNU General Public License as published by
7 | -- the Free Software Foundation; either version 2 of the License, or
8 | -- (at your option) any later version.
9 | --
10 | -- This program is distributed in the hope that it will be useful,
11 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | -- GNU General Public License for more details.
14 | --
15 | -- You should have received a copy of the GNU General Public License along
16 | -- with this program; if not, write to the Free Software Foundation, Inc.,
17 | -- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 |
19 | library ieee ;
20 | use ieee.std_logic_1164.all ;
21 | use ieee.numeric_std.all ;
22 |
23 | library lpm ;
24 | use lpm.lpm_components.all ;
25 |
26 | entity wlan_divide is
27 | generic (
28 | SAMPLE_WIDTH : natural ;
29 | DENOM_WIDTH : natural ;
30 | NUM_PIPELINE : natural
31 | ) ;
32 | port (
33 | clock : in std_logic ;
34 | reset : in std_logic ;
35 |
36 | in_i : in signed(SAMPLE_WIDTH-1 downto 0) ;
37 | in_q : in signed(SAMPLE_WIDTH-1 downto 0) ;
38 | in_denom : in unsigned(DENOM_WIDTH-1 downto 0) ;
39 | in_valid : in std_logic ;
40 | in_done : in std_logic ;
41 |
42 | out_i : out signed(SAMPLE_WIDTH-1 downto 0) ;
43 | out_q : out signed(SAMPLE_WIDTH-1 downto 0) ;
44 | out_valid : out std_logic ;
45 | out_done : out std_logic
46 | ) ;
47 | end entity ;
48 |
49 | architecture altera of wlan_divide is
50 |
51 | signal done : std_logic_vector(NUM_PIPELINE-1 downto 0) ;
52 | signal valid : std_logic_vector(NUM_PIPELINE-1 downto 0) ;
53 |
54 | begin
55 |
56 | register_valids_and_done : process(clock, reset)
57 | begin
58 | if( reset = '1' ) then
59 | done <= (others =>'0') ;
60 | valid <= (others =>'0') ;
61 | elsif( rising_edge(clock) ) then
62 | done <= done(done'high-1 downto 0) & in_done ;
63 | valid <= valid(valid'high-1 downto 0) & in_valid ;
64 | end if ;
65 | end process ;
66 |
67 | out_done <= done(done'high) ;
68 | out_valid <= valid(valid'high) ;
69 |
70 | div_i : lpm_divide
71 | generic map (
72 | lpm_nrepresentation => "SIGNED",
73 | lpm_drepresentation => "UNSIGNED",
74 | lpm_hint => "LPM_REMAINDERPOSITIVE=TRUE",
75 | lpm_pipeline => NUM_PIPELINE,
76 | lpm_type => "LPM_DIVIDE",
77 | lpm_widthd => DENOM_WIDTH,
78 | lpm_widthn => SAMPLE_WIDTH
79 | ) port map (
80 | clock => clock,
81 | aclr => reset,
82 | numer => std_logic_vector(in_i),
83 | denom => std_logic_vector(in_denom),
84 | remain => open,
85 | signed(quotient) => out_i
86 | ) ;
87 |
88 | div_q : lpm_divide
89 | generic map (
90 | lpm_nrepresentation => "SIGNED",
91 | lpm_drepresentation => "UNSIGNED",
92 | lpm_hint => "LPM_REMAINDERPOSITIVE=TRUE",
93 | lpm_pipeline => NUM_PIPELINE,
94 | lpm_type => "LPM_DIVIDE",
95 | lpm_widthd => DENOM_WIDTH,
96 | lpm_widthn => SAMPLE_WIDTH
97 | ) port map (
98 | clock => clock,
99 | aclr => reset,
100 | numer => std_logic_vector(in_q),
101 | denom => std_logic_vector(in_denom),
102 | remain => open,
103 | signed(quotient) => out_q
104 | ) ;
105 |
106 | end architecture ;
107 |
--------------------------------------------------------------------------------
/fpga/vhdl/wlan_dsss_demodulator.vhd:
--------------------------------------------------------------------------------
1 | -- This file is part of bladeRF-wiphy.
2 | --
3 | -- Copyright (C) 2020 Nuand, LLC.
4 | --
5 | -- This program is free software; you can redistribute it and/or modify
6 | -- it under the terms of the GNU General Public License as published by
7 | -- the Free Software Foundation; either version 2 of the License, or
8 | -- (at your option) any later version.
9 | --
10 | -- This program is distributed in the hope that it will be useful,
11 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | -- GNU General Public License for more details.
14 | --
15 | -- You should have received a copy of the GNU General Public License along
16 | -- with this program; if not, write to the Free Software Foundation, Inc.,
17 | -- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 |
19 | library ieee ;
20 | use ieee.std_logic_1164.all ;
21 | use ieee.numeric_std.all ;
22 |
23 | library wlan ;
24 | use wlan.wlan_p.all ;
25 | use wlan.wlan_rx_p.all ;
26 |
27 | entity wlan_dsss_demodulator is
28 | port (
29 | clock : in std_logic ;
30 | reset : in std_logic ;
31 |
32 | modulation : in wlan_modulation_t ;
33 |
34 | in_bin_idx : in natural ;
35 | despread : in wlan_sample_t ;
36 |
37 | out_bin_idx : out natural ;
38 | out_bits : out std_logic_vector( 1 downto 0 ) ;
39 | out_valid : out std_logic
40 | ) ;
41 | end entity ;
42 |
43 | architecture arch of wlan_dsss_demodulator is
44 |
45 | signal history : sample_array_t( 19 downto 0 );
46 |
47 | signal res_i : signed( 19 downto 0 ) ;
48 | signal a_i, a_q, b_i, b_q : signed(15 downto 0) ;
49 | signal res_q : signed( 19 downto 0 ) ;
50 |
51 | signal res_valid : std_logic ;
52 |
53 | signal coded_bits : std_logic_vector( 1 downto 0 ) ;
54 | signal coded_valid : std_logic ;
55 | signal coded_idx : natural ;
56 |
57 | signal decoded_bits : std_logic_vector( 19 downto 0 ) ;
58 | signal demod_bits : std_logic_vector( 19 downto 0 ) ;
59 |
60 | type bit_history_t is array(0 to 20) of std_logic_vector(7 downto 0) ;
61 | signal bit_history : bit_history_t ;
62 | begin
63 |
64 | -- demodulate bits
65 | process( clock )
66 | variable wtf : signed (19 downto 0 );
67 | begin
68 | if( reset = '1' ) then
69 | history <= ( others => NULL_SAMPLE ) ;
70 | coded_bits <= ( others => '0' ) ;
71 | coded_valid <= '0' ;
72 | coded_idx <= 0 ;
73 | demod_bits <= ( others => '0' ) ;
74 |
75 | elsif( rising_edge( clock ) ) then
76 | coded_valid <= '0' ;
77 |
78 | if( despread.valid = '1' ) then
79 | for i in 0 to history'high - 1 loop
80 | history(i+1) <= history(i) ;
81 | end loop ;
82 | history(0) <= despread ;
83 |
84 | if( modulation = WLAN_DBPSK ) then
85 | coded_idx <= in_bin_idx ;
86 | a_i <= despread.i;
87 | a_q <= history(19).i;
88 | b_i <= despread.q;
89 | b_q <= history(19).q;
90 | wtf := resize((shift_right(despread.i * history(19).i,4) + shift_right(despread.q * history(19).q,4)), 20);
91 | res_i <= wtf;
92 | if( wtf < 0 ) then
93 | demod_bits(in_bin_idx) <= '1' ;
94 | coded_bits(0) <= '1' ;
95 | else
96 | demod_bits(in_bin_idx) <= '0' ;
97 | coded_bits(0) <= '0' ;
98 | end if ;
99 | coded_valid <= '1' ;
100 | end if ;
101 | end if ;
102 |
103 | end if ;
104 | end process ;
105 |
106 | -- descramble decoded bits
107 | process( clock )
108 | begin
109 | if( reset = '1' ) then
110 | out_bin_idx <= 0 ;
111 | out_bits <= ( others => '0' ) ;
112 | out_valid <= '0' ;
113 | bit_history <= ( others => ( others => '0' ) ) ;
114 | decoded_bits<= ( others => '0' ) ;
115 | elsif( rising_edge( clock ) ) then
116 | out_valid <= '0' ;
117 | if( coded_valid = '1' ) then
118 | if( modulation = WLAN_DBPSK ) then
119 | -- save per bin descrambler register
120 | bit_history(coded_idx) <= bit_history(coded_idx)(6 downto 0) & coded_bits(0) ;
121 |
122 | -- descramble bit
123 | out_bits(0) <= coded_bits(0) xor bit_history(coded_idx)(3) xor bit_history(coded_idx)(6) ;
124 | decoded_bits(coded_idx) <= coded_bits(0) xor bit_history(coded_idx)(3) xor bit_history(coded_idx)(6) ;
125 | out_bin_idx <= coded_idx ;
126 | out_valid <= '1' ;
127 | end if ;
128 | end if ;
129 | end if ;
130 | end process ;
131 |
132 | end architecture ;
133 |
--------------------------------------------------------------------------------
/fpga/vhdl/wlan_dsss_despreader.vhd:
--------------------------------------------------------------------------------
1 | -- This file is part of bladeRF-wiphy.
2 | --
3 | -- Copyright (C) 2020 Nuand, LLC.
4 | --
5 | -- This program is free software; you can redistribute it and/or modify
6 | -- it under the terms of the GNU General Public License as published by
7 | -- the Free Software Foundation; either version 2 of the License, or
8 | -- (at your option) any later version.
9 | --
10 | -- This program is distributed in the hope that it will be useful,
11 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | -- GNU General Public License for more details.
14 | --
15 | -- You should have received a copy of the GNU General Public License along
16 | -- with this program; if not, write to the Free Software Foundation, Inc.,
17 | -- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 |
19 | library ieee ;
20 | use ieee.std_logic_1164.all ;
21 | use ieee.numeric_std.all ;
22 |
23 | library wlan ;
24 | use wlan.wlan_p.all ;
25 | use wlan.wlan_rx_p.all ;
26 |
27 | entity wlan_dsss_despreader is
28 | port (
29 | clock : in std_logic ;
30 | reset : in std_logic ;
31 |
32 | sample : in wlan_sample_t ;
33 | despread : out wlan_sample_t
34 | ) ;
35 | end entity ;
36 |
37 | architecture arch of wlan_dsss_despreader is
38 |
39 | constant preamble : sample_array_t( 19 downto 0 ) := (
40 | (valid => '1', i => to_signed( 128, 16), q => to_signed( 128, 16)),
41 | (valid => '1', i => to_signed( -14, 16), q => to_signed( -14, 16)),
42 | (valid => '1', i => to_signed(-135, 16), q => to_signed(-135, 16)),
43 | (valid => '1', i => to_signed( -20, 16), q => to_signed( -20, 16)),
44 | (valid => '1', i => to_signed( 197, 16), q => to_signed( 197, 16)),
45 | (valid => '1', i => to_signed( 210, 16), q => to_signed( 210, 16)),
46 | (valid => '1', i => to_signed( 1, 16), q => to_signed( 1, 16)),
47 | (valid => '1', i => to_signed(-135, 16), q => to_signed(-135, 16)),
48 | (valid => '1', i => to_signed( -34, 16), q => to_signed( -34, 16)),
49 | (valid => '1', i => to_signed( 120, 16), q => to_signed( 120, 16)),
50 | (valid => '1', i => to_signed( 147, 16), q => to_signed( 147, 16)),
51 | (valid => '1', i => to_signed( 128, 16), q => to_signed( 128, 16)),
52 | (valid => '1', i => to_signed( 148, 16), q => to_signed( 148, 16)),
53 | (valid => '1', i => to_signed( 102, 16), q => to_signed( 102, 16)),
54 | (valid => '1', i => to_signed( -54, 16), q => to_signed( -54, 16)),
55 | (valid => '1', i => to_signed(-159, 16), q => to_signed(-159, 16)),
56 | (valid => '1', i => to_signed(-142, 16), q => to_signed(-142, 16)),
57 | (valid => '1', i => to_signed(-119, 16), q => to_signed(-119, 16)),
58 | (valid => '1', i => to_signed(-130, 16), q => to_signed(-130, 16)),
59 | (valid => '1', i => to_signed( -86, 16), q => to_signed( -86, 16))
60 | );
61 |
62 | type despreader_result_t is record
63 | i : signed(15 downto 0) ;
64 | q : signed(15 downto 0) ;
65 | valid : std_logic ;
66 | end record ;
67 |
68 | type eq_array_t is array(natural range <>) of despreader_result_t ;
69 | signal accum : eq_array_t(19 downto 0);
70 |
71 | begin
72 |
73 | process( clock )
74 | begin
75 | if( reset = '1' ) then
76 | elsif( rising_edge( clock ) ) then
77 | despread.valid <= '0' ;
78 | if( sample.valid = '1' ) then
79 | for i in accum'range loop
80 | if i = accum'high then
81 | accum(i).i <= resize(shift_right(preamble(i).i*sample.i, 9), 16);
82 | accum(i).q <= resize(shift_right(preamble(i).q*sample.q, 9), 16);
83 | accum(i).valid <= '1';
84 | else
85 | accum(i).i <= resize(accum(i+1).i + shift_right(preamble(i).i*sample.i, 9), 16);
86 | accum(i).q <= resize(accum(i+1).q + shift_right(preamble(i).q*sample.q, 9), 16);
87 | accum(i).valid <= accum(i+1).valid;
88 | end if;
89 | end loop;
90 | despread.i <= accum(0).i ;
91 | despread.q <= accum(0).q ;
92 | despread.valid <= accum(0).valid ;
93 | end if ;
94 | end if ;
95 | end process ;
96 |
97 | end architecture ;
98 |
--------------------------------------------------------------------------------
/fpga/vhdl/wlan_dsss_p_norm.vhd:
--------------------------------------------------------------------------------
1 | -- This file is part of bladeRF-wiphy.
2 | --
3 | -- Copyright (C) 2020 Nuand, LLC.
4 | --
5 | -- This program is free software; you can redistribute it and/or modify
6 | -- it under the terms of the GNU General Public License as published by
7 | -- the Free Software Foundation; either version 2 of the License, or
8 | -- (at your option) any later version.
9 | --
10 | -- This program is distributed in the hope that it will be useful,
11 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | -- GNU General Public License for more details.
14 | --
15 | -- You should have received a copy of the GNU General Public License along
16 | -- with this program; if not, write to the Free Software Foundation, Inc.,
17 | -- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 |
19 | library ieee ;
20 | use ieee.std_logic_1164.all ;
21 | use ieee.numeric_std.all ;
22 | use ieee.math_real.all ;
23 |
24 | library wlan ;
25 | use wlan.wlan_p.all ;
26 | use wlan.wlan_rx_p.all ;
27 |
28 | entity wlan_dsss_p_norm is
29 | port (
30 | -- 40MHz clock and async asserted, sync deasserted reset
31 | clock : in std_logic ;
32 | reset : in std_logic ;
33 |
34 | in_sample : in wlan_sample_t ;
35 | p_normed : out wlan_sample_t
36 | ) ;
37 | end entity ;
38 |
39 | architecture arch of wlan_dsss_p_norm is
40 | signal pow_set : signed( 31 downto 0 ) ;
41 | signal iir : signed( 31 downto 0 ) ;
42 | signal dat : signed( 31 downto 0 ) ;
43 | signal log2 : unsigned ( 8 downto 0 ) ;
44 | signal ptemp : signed( 31 downto 0 ) ;
45 | signal p_mag : signed( 23 downto 0 ) ;
46 | signal timer : unsigned( 8 downto 0 ) ;
47 |
48 | signal second_blip : std_logic ;
49 |
50 | type unsigned_array_t is array (natural range 0 to 511) of signed( 23 downto 0 ) ;
51 |
52 | function calc_lut return unsigned_array_t is
53 | variable rv : unsigned_array_t ;
54 | variable i : real ;
55 | variable two : real ;
56 | begin
57 | for x in rv'range loop
58 | i := ( 24.0 - (real(x) / 16.0) ) / 2.0 + 12.0; -- i is in log2
59 | report integer'image(x) & " LUT " & real'image(i);
60 | two := 2 ** i ;
61 | if (real(two) > 5.7e5) then
62 | two := 5.7e5;
63 | end if;
64 | rv(x) := to_signed(integer(round(two)), 24) ;
65 | end loop ;
66 | return rv ;
67 | end;
68 | constant mult_lut : unsigned_array_t := calc_lut;
69 |
70 | function log2x( x : signed( 31 downto 0) )
71 | return unsigned is
72 | variable bits : unsigned( 8 downto 0 ) ;
73 | begin
74 | bits := (others => '0') ;
75 | for i in x'range loop
76 | if (x(i) = '1') then
77 | bits(8 downto 4) := to_unsigned(i, 5) ;
78 | if (real(i) < 4.0) then
79 | bits(3 downto 4 - i) := unsigned(x(i - 1 downto 0)) ;
80 | else
81 | bits(3 downto 0) := unsigned(x(i - 1 downto i - 4)) ;
82 | end if;
83 | exit ;
84 | end if ;
85 | end loop ;
86 | return bits ;
87 | end log2x ;
88 |
89 | function run_iir( x : signed( 31 downto 0); y : signed ( 31 downto 0) )
90 | return signed
91 | is
92 | variable ret : signed(31 downto 0) ;
93 | begin
94 | ret := resize( x - shift_right(x, 4) + shift_right(y, 4), 32 );
95 | return ret;
96 | end;
97 |
98 | begin
99 | process( clock )
100 | variable gain_req : std_logic ;
101 | begin
102 | if( reset = '1' ) then
103 | iir <= ( others => '0' ) ;
104 | ptemp <= ( others => '0' ) ;
105 | p_mag <= ( others => '0' ) ;
106 | timer <= ( others => '0' ) ;
107 | pow_set <= ( others => '0' ) ;
108 | second_blip <= '0' ;
109 | elsif( rising_edge( clock )) then
110 | p_mag <= signed(resize(mult_lut(to_integer(log2x(pow_set))), 24)) ;
111 | p_normed.valid <= '0' ;
112 | if (in_sample.valid = '1') then
113 | ptemp <= in_sample.i * in_sample.i + in_sample.q * in_sample.q ;
114 | iir <= run_iir(iir, ptemp) ;
115 |
116 | gain_req := '0' ;
117 | if( iir*2 < pow_set or iir > pow_set*2 ) then
118 | gain_req := '1' ;
119 | end if ;
120 |
121 | if( timer = 59 ) then
122 | timer <= ( others => '0' ) ;
123 | if( gain_req = '1' ) then
124 | second_blip <= '1' ;
125 | end if ;
126 | else
127 | timer <= timer + 1 ;
128 | end if;
129 |
130 | if( second_blip = '1' ) then
131 | if( gain_req = '1' ) then
132 | pow_set <= iir ;
133 | end if ;
134 | second_blip <= '0' ;
135 | end if ;
136 |
137 | p_normed.i <= resize(shift_right(in_sample.i * p_mag, 16), 16) ;
138 | p_normed.q <= resize(shift_right(in_sample.q * p_mag, 16), 16) ;
139 | p_normed.valid <= '1' ;
140 | end if ;
141 | end if ;
142 | end process ;
143 | end architecture ;
144 |
--------------------------------------------------------------------------------
/fpga/vhdl/wlan_dsss_plcp_crc.vhd:
--------------------------------------------------------------------------------
1 | -- This file is part of bladeRF-wiphy.
2 | --
3 | -- Copyright (C) 2020 Nuand, LLC.
4 | --
5 | -- This program is free software; you can redistribute it and/or modify
6 | -- it under the terms of the GNU General Public License as published by
7 | -- the Free Software Foundation; either version 2 of the License, or
8 | -- (at your option) any later version.
9 | --
10 | -- This program is distributed in the hope that it will be useful,
11 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | -- GNU General Public License for more details.
14 | --
15 | -- You should have received a copy of the GNU General Public License along
16 | -- with this program; if not, write to the Free Software Foundation, Inc.,
17 | -- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 |
19 | library ieee ;
20 | use ieee.std_logic_1164.all ;
21 | use ieee.numeric_std.all ;
22 |
23 | entity wlan_dsss_plcp_crc is
24 | port (
25 | clock : in std_logic ;
26 | reset : in std_logic ;
27 |
28 | in_data : in std_logic ;
29 | in_valid : in std_logic ;
30 |
31 | crc : out std_logic_vector(15 downto 0)
32 | ) ;
33 | end entity ;
34 |
35 | architecture arch of wlan_dsss_plcp_crc is
36 |
37 | signal crc_next : std_logic_vector(15 downto 0);
38 |
39 | begin
40 |
41 | process( reset, clock )
42 | begin
43 | if( reset = '1' ) then
44 | crc_next <= ( others => '1' ) ;
45 | elsif( rising_edge( clock ) ) then
46 | if (in_valid = '1' ) then
47 | crc_next(15) <= crc_next(14);
48 | crc_next(14) <= crc_next(13);
49 | crc_next(13) <= crc_next(12);
50 | crc_next(12) <= crc_next(11) xor crc_next(15) xor in_data;
51 | crc_next(11) <= crc_next(10);
52 | crc_next(10) <= crc_next(9);
53 | crc_next(9) <= crc_next(8);
54 | crc_next(8) <= crc_next(7);
55 | crc_next(7) <= crc_next(6);
56 | crc_next(6) <= crc_next(5);
57 | crc_next(5) <= crc_next(4) xor crc_next(15) xor in_data;
58 | crc_next(4) <= crc_next(3);
59 | crc_next(3) <= crc_next(2);
60 | crc_next(2) <= crc_next(1);
61 | crc_next(1) <= crc_next(0);
62 | crc_next(0) <= crc_next(15) xor in_data ;
63 | end if;
64 | end if;
65 | end process;
66 |
67 | crc <= crc_next xor x"FFFF";
68 |
69 | end architecture ;
70 |
71 |
--------------------------------------------------------------------------------
/fpga/vhdl/wlan_dsss_rx.vhd:
--------------------------------------------------------------------------------
1 | -- This file is part of bladeRF-wiphy.
2 | --
3 | -- Copyright (C) 2020 Nuand, LLC.
4 | --
5 | -- This program is free software; you can redistribute it and/or modify
6 | -- it under the terms of the GNU General Public License as published by
7 | -- the Free Software Foundation; either version 2 of the License, or
8 | -- (at your option) any later version.
9 | --
10 | -- This program is distributed in the hope that it will be useful,
11 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | -- GNU General Public License for more details.
14 | --
15 | -- You should have received a copy of the GNU General Public License along
16 | -- with this program; if not, write to the Free Software Foundation, Inc.,
17 | -- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 |
19 | library ieee ;
20 | use ieee.std_logic_1164.all ;
21 | use ieee.numeric_std.all ;
22 |
23 | library wlan ;
24 | use wlan.nco_p.all ;
25 | use wlan.wlan_p.all ;
26 | use wlan.wlan_rx_p.all ;
27 |
28 | library altera_mf ;
29 | use altera_mf.altera_mf_components.all ;
30 |
31 | library wlan_pll ;
32 |
33 | entity wlan_dsss_rx is
34 | port (
35 | -- 40MHz clock and async asserted, sync deasserted reset
36 | clock : in std_logic ;
37 | reset : in std_logic ;
38 |
39 | -- Baseband input signals
40 | sample : in wlan_sample_t ;
41 |
42 | params : out wlan_rx_params_t ;
43 | params_valid : out std_logic ;
44 |
45 | data : out std_logic_vector( 7 downto 0 ) ;
46 | data_valid : out std_logic ;
47 |
48 | framer_done : out std_logic ;
49 | crc_correct : out std_logic
50 | ) ;
51 | end entity ;
52 |
53 | architecture arch of wlan_dsss_rx is
54 | signal despread : wlan_sample_t ;
55 | signal p_norm_sample : wlan_sample_t ;
56 | signal modulation : wlan_modulation_t ;
57 | signal bin_idx : natural range 0 to 20 ;
58 | signal mode_bin : natural range 0 to 20 ;
59 |
60 | signal demod_bits : std_logic_vector( 1 downto 0 ) ;
61 | signal demod_idx : natural range 0 to 20 ;
62 | signal demod_valid : std_logic ;
63 |
64 | begin
65 | U_dsss_rx_controller : entity work.wlan_dsss_rx_controller
66 | port map (
67 | clock => clock,
68 | reset => reset,
69 |
70 | in_sample => sample,
71 | modulation => modulation,
72 | out_bin_idx => bin_idx
73 | ) ;
74 |
75 | U_dsss_p_norm : entity work.wlan_dsss_p_norm
76 | port map (
77 | clock => clock,
78 | reset => reset,
79 |
80 | in_sample => sample,
81 | p_normed => p_norm_sample
82 | ) ;
83 |
84 | U_dsss_despreader : entity work.wlan_dsss_despreader
85 | port map (
86 | clock => clock,
87 | reset => reset,
88 |
89 | sample => p_norm_sample,
90 | despread => despread
91 | ) ;
92 |
93 | U_dsss_peak_finder : entity work.wlan_dsss_peak_finder
94 | port map (
95 | clock => clock,
96 | reset => reset,
97 |
98 | despread => despread,
99 |
100 | bin_idx => bin_idx,
101 |
102 | out_mode_bin => mode_bin
103 | ) ;
104 |
105 | U_dsss_demodulator : entity work.wlan_dsss_demodulator
106 | port map (
107 | clock => clock,
108 | reset => reset,
109 |
110 | modulation => modulation,
111 |
112 | in_bin_idx => bin_idx,
113 | despread => despread,
114 |
115 | out_bin_idx => demod_idx,
116 | out_bits => demod_bits,
117 | out_valid => demod_valid
118 | ) ;
119 |
120 | U_dsss_rx_framer : entity work.wlan_dsss_rx_framer
121 | port map (
122 | clock => clock,
123 | reset => reset,
124 |
125 | mode_bin => mode_bin,
126 |
127 | demod_idx => demod_idx,
128 | demod_bits => demod_bits,
129 | demod_valid => demod_valid,
130 |
131 | params => params,
132 | params_valid => params_valid,
133 | data => data,
134 | data_valid => data_valid,
135 |
136 | framer_done => framer_done,
137 | crc_correct => crc_correct
138 | ) ;
139 |
140 | end architecture ;
141 |
--------------------------------------------------------------------------------
/fpga/vhdl/wlan_dsss_rx_controller.vhd:
--------------------------------------------------------------------------------
1 | -- This file is part of bladeRF-wiphy.
2 | --
3 | -- Copyright (C) 2020 Nuand, LLC.
4 | --
5 | -- This program is free software; you can redistribute it and/or modify
6 | -- it under the terms of the GNU General Public License as published by
7 | -- the Free Software Foundation; either version 2 of the License, or
8 | -- (at your option) any later version.
9 | --
10 | -- This program is distributed in the hope that it will be useful,
11 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | -- GNU General Public License for more details.
14 | --
15 | -- You should have received a copy of the GNU General Public License along
16 | -- with this program; if not, write to the Free Software Foundation, Inc.,
17 | -- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 |
19 | library ieee ;
20 | use ieee.std_logic_1164.all ;
21 | use ieee.numeric_std.all ;
22 |
23 | library wlan ;
24 | use wlan.wlan_p.all ;
25 | use wlan.wlan_rx_p.all ;
26 |
27 | entity wlan_dsss_rx_controller is
28 | port (
29 | clock : in std_logic ;
30 | reset : in std_logic ;
31 |
32 | in_sample : in wlan_sample_t ;
33 |
34 | modulation : out wlan_modulation_t;
35 | out_bin_idx : out natural
36 | ) ;
37 | end entity;
38 |
39 | architecture arch of wlan_dsss_rx_controller is
40 |
41 | type fsm_t is (IDLE) ;
42 |
43 | type state_t is record
44 | fsm : fsm_t ;
45 | bin_idx : natural range 0 to 20 ;
46 | end record ;
47 |
48 | function NULL_STATE return state_t is
49 | variable rv : state_t ;
50 | begin
51 | rv.fsm := IDLE ;
52 | rv.bin_idx := 0 ;
53 | return rv ;
54 | end function ;
55 |
56 | signal current, future : state_t := NULL_STATE ;
57 | begin
58 | out_bin_idx <= current.bin_idx ;
59 | modulation <= WLAN_DBPSK ;
60 |
61 | sync : process( clock )
62 | begin
63 | if( reset = '1' ) then
64 | current <= NULL_STATE ;
65 | elsif( rising_edge( clock ) ) then
66 | current <= future ;
67 | end if ;
68 | end process ;
69 |
70 | comb: process(all)
71 | begin
72 | future <= current ;
73 | if( in_sample.valid = '1' ) then
74 | if( current.bin_idx = 19 ) then
75 | future.bin_idx <= 0 ;
76 | else
77 | future.bin_idx <= current.bin_idx + 1 ;
78 | end if ;
79 | end if ;
80 | end process ;
81 | end architecture ;
82 |
--------------------------------------------------------------------------------
/fpga/vhdl/wlan_interleaver.vhd:
--------------------------------------------------------------------------------
1 | -- This file is part of bladeRF-wiphy.
2 | --
3 | -- Copyright (C) 2020 Nuand, LLC.
4 | --
5 | -- This program is free software; you can redistribute it and/or modify
6 | -- it under the terms of the GNU General Public License as published by
7 | -- the Free Software Foundation; either version 2 of the License, or
8 | -- (at your option) any later version.
9 | --
10 | -- This program is distributed in the hope that it will be useful,
11 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | -- GNU General Public License for more details.
14 | --
15 | -- You should have received a copy of the GNU General Public License along
16 | -- with this program; if not, write to the Free Software Foundation, Inc.,
17 | -- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 |
19 | library ieee ;
20 | use ieee.std_logic_1164.all ;
21 | use ieee.numeric_std.all ;
22 |
23 | library work ;
24 | use work.wlan_p.all ;
25 | use work.wlan_interleaver_p.all ;
26 |
27 | entity wlan_interleaver is
28 | port (
29 | clock : in std_logic ;
30 | reset : in std_logic ;
31 |
32 | modulation : in wlan_modulation_t ;
33 | data : in std_logic_vector(287 downto 0) ;
34 | in_valid : in std_logic ;
35 |
36 | interleaved : out std_logic_vector(287 downto 0) ;
37 | interleaved_mod : out wlan_modulation_t ;
38 | interleaved_valid : out std_logic
39 | ) ;
40 | end entity ;
41 |
42 | architecture arch of wlan_interleaver is
43 |
44 | begin
45 |
46 | permute_bits : process(clock, reset)
47 | begin
48 | if( reset = '1' ) then
49 | interleaved <= (others =>'0') ;
50 | interleaved_mod <= WLAN_BPSK ;
51 | interleaved_valid <= '0' ;
52 | elsif( rising_edge(clock) ) then
53 | interleaved_valid <= in_valid ;
54 | if( in_valid = '1' ) then
55 | interleaved <= interleave(modulation, data) ;
56 | interleaved_mod <= modulation ;
57 | end if ;
58 | end if ;
59 | end process ;
60 |
61 | end architecture ;
62 |
63 |
--------------------------------------------------------------------------------
/fpga/vhdl/wlan_interleaver_p.vhd:
--------------------------------------------------------------------------------
1 | -- This file is part of bladeRF-wiphy.
2 | --
3 | -- Copyright (C) 2020 Nuand, LLC.
4 | --
5 | -- This program is free software; you can redistribute it and/or modify
6 | -- it under the terms of the GNU General Public License as published by
7 | -- the Free Software Foundation; either version 2 of the License, or
8 | -- (at your option) any later version.
9 | --
10 | -- This program is distributed in the hope that it will be useful,
11 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | -- GNU General Public License for more details.
14 | --
15 | -- You should have received a copy of the GNU General Public License along
16 | -- with this program; if not, write to the Free Software Foundation, Inc.,
17 | -- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 |
19 | library ieee ;
20 | use ieee.std_logic_1164.all ;
21 | use ieee.math_real.all ;
22 |
23 | library work ;
24 | use work.wlan_p.all ;
25 |
26 | package wlan_interleaver_p is
27 |
28 | -- Deferred initialization in package body after function definition
29 | constant WLAN_INTERLEAVER_BPSK : integer_array_t ;
30 | constant WLAN_INTERLEAVER_QPSK : integer_array_t ;
31 | constant WLAN_INTERLEAVER_16QAM : integer_array_t ;
32 | constant WLAN_INTERLEAVER_64QAM : integer_array_t ;
33 |
34 | -- Interleaving occurs on bits
35 | function interleave( modulation : wlan_modulation_t ; x : std_logic_vector(287 downto 0) ) return std_logic_vector ;
36 |
37 | -- Deinterleaving occurs on bit soft decisions
38 | function deinterleave( modulation : wlan_modulation_t ; x : bsd_array_t(287 downto 0) ) return bsd_array_t ;
39 |
40 | end package ;
41 |
42 | package body wlan_interleaver_p is
43 |
44 | function get_table( modulation : wlan_modulation_t ) return integer_array_t is
45 | begin
46 | case modulation is
47 | when WLAN_BPSK => return WLAN_INTERLEAVER_BPSK ;
48 | when WLAN_QPSK => return WLAN_INTERLEAVER_QPSK ;
49 | when WLAN_16QAM => return WLAN_INTERLEAVER_16QAM ;
50 | when WLAN_64QAM => return WLAN_INTERLEAVER_64QAM ;
51 | when others => return WLAN_INTERLEAVER_BPSK ;
52 | end case ;
53 | report "get_table: Could not figure out modulation" severity failure ;
54 | end function ;
55 |
56 | function interleave( modulation : wlan_modulation_t ; x : std_logic_vector(287 downto 0) ) return std_logic_vector is
57 | variable t : integer_array_t(0 to 287) ;
58 | variable y : std_logic_vector(287 downto 0) := (others =>'-') ;
59 | begin
60 | t := get_table( modulation ) ;
61 | for i in t'range loop
62 | -- 0 only happens for the 0 entry, so stop there
63 | if( i > 0 and t(i) = 0 ) then
64 | exit ;
65 | else
66 | y(t(i)) := x(i) ;
67 | end if ;
68 | end loop ;
69 | return y ;
70 | end function ;
71 |
72 | function deinterleave( modulation : wlan_modulation_t ; x : bsd_array_t(287 downto 0) ) return bsd_array_t is
73 | variable t : integer_array_t(0 to 287) ;
74 | variable y : bsd_array_t(287 downto 0) ;
75 | begin
76 | y := (others => (others => '0' )) ;
77 | t := get_table( modulation ) ;
78 | for i in t'range loop
79 | -- Stop at the next 0 entry
80 | if( i > 0 and t(i) = 0 ) then
81 | exit ;
82 | else
83 | y(i) := x(t(i)) ;
84 | end if ;
85 | end loop ;
86 | return y ;
87 | end function ;
88 |
89 | function calculate_interleaver_table( modulation : wlan_modulation_t ) return integer_array_t is
90 | variable n_cbps : natural ;
91 | variable n_bpsc : natural ;
92 | variable i : natural ;
93 | variable j : natural ;
94 | variable s : natural ;
95 | variable rv : integer_array_t(0 to 287) := (others => 0) ;
96 | begin
97 | case modulation is
98 | when WLAN_BPSK =>
99 | n_bpsc := 1 ;
100 | n_cbps := 48 ;
101 | s := 1 ;
102 | when WLAN_QPSK =>
103 | n_bpsc := 2 ;
104 | n_cbps := 96 ;
105 | s := 1 ;
106 | when WLAN_16QAM =>
107 | n_bpsc := 4 ;
108 | n_cbps := 192 ;
109 | s := 2 ;
110 | when WLAN_64QAM =>
111 | n_bpsc := 6 ;
112 | n_cbps := 288 ;
113 | s := 3 ;
114 | when others =>
115 | end case ;
116 |
117 | for k in 0 to n_cbps-1 loop
118 | i := (n_cbps/16)*(k mod 16) + k/16 ;
119 | j := s*integer(floor(real(i)/real(s))) + ((i + n_cbps - (16*i)/n_cbps) mod s) ;
120 | rv(k) := j ;
121 | end loop ;
122 |
123 | return rv ;
124 | end function ;
125 |
126 | -- Deferred initialization of table
127 | constant WLAN_INTERLEAVER_BPSK : integer_array_t := calculate_interleaver_table( WLAN_BPSK ) ;
128 | constant WLAN_INTERLEAVER_QPSK : integer_array_t := calculate_interleaver_table( WLAN_QPSK ) ;
129 | constant WLAN_INTERLEAVER_16QAM : integer_array_t := calculate_interleaver_table( WLAN_16QAM ) ;
130 | constant WLAN_INTERLEAVER_64QAM : integer_array_t := calculate_interleaver_table( WLAN_64QAM ) ;
131 |
132 | end package body ;
133 |
134 |
--------------------------------------------------------------------------------
/fpga/vhdl/wlan_lfsr.vhd:
--------------------------------------------------------------------------------
1 | -- This file is part of bladeRF-wiphy.
2 | --
3 | -- Copyright (C) 2020 Nuand, LLC.
4 | --
5 | -- This program is free software; you can redistribute it and/or modify
6 | -- it under the terms of the GNU General Public License as published by
7 | -- the Free Software Foundation; either version 2 of the License, or
8 | -- (at your option) any later version.
9 | --
10 | -- This program is distributed in the hope that it will be useful,
11 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | -- GNU General Public License for more details.
14 | --
15 | -- You should have received a copy of the GNU General Public License along
16 | -- with this program; if not, write to the Free Software Foundation, Inc.,
17 | -- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 |
19 | library ieee ;
20 | use ieee.std_logic_1164.all ;
21 | use ieee.numeric_std.all ;
22 |
23 | entity wlan_lfsr is
24 | generic (
25 | WIDTH : positive := 8
26 | ) ;
27 | port (
28 | clock : in std_logic ;
29 | reset : in std_logic ;
30 |
31 | init : in unsigned(6 downto 0) ;
32 | init_valid : in std_logic ;
33 |
34 | advance : in std_logic ;
35 | data : out std_logic_vector(WIDTH-1 downto 0) ;
36 | data_valid : out std_logic
37 | ) ;
38 | end entity ;
39 |
40 | architecture arch of wlan_lfsr is
41 |
42 | signal state : unsigned(6 downto 0) := (others =>'0') ;
43 |
44 | begin
45 |
46 | lfsr : process(clock, reset)
47 | variable tempstate : unsigned(6 downto 0) := (others =>'0') ;
48 | begin
49 | if( reset = '1' ) then
50 | state <= (others =>'0') ;
51 | data <= (others =>'0') ;
52 | data_valid <= '0' ;
53 | tempstate := (others =>'0') ;
54 | elsif( rising_edge(clock) ) then
55 | data_valid <= '0' ;
56 | if( init_valid = '1' ) then
57 | tempstate := init ;
58 | -- Initialize output to the first word, like a look-ahead FIFO
59 | for i in 0 to data'high loop
60 | tempstate := tempstate(5 downto 0) & (tempstate(6) xor tempstate(3)) ;
61 | data(i) <= tempstate(0) ;
62 | end loop ;
63 | state <= tempstate ;
64 | else
65 | data_valid <= advance ;
66 | if( advance = '1' ) then
67 | tempstate := state ;
68 | for i in 0 to data'high loop
69 | tempstate := tempstate(5 downto 0) & (tempstate(6) xor tempstate(3)) ;
70 | data(i) <= tempstate(0) ;
71 | end loop ;
72 | state <= tempstate ;
73 | end if ;
74 | end if ;
75 | end if ;
76 | end process ;
77 |
78 | end architecture ;
79 |
80 |
--------------------------------------------------------------------------------
/fpga/vhdl/wlan_p_norm.vhd:
--------------------------------------------------------------------------------
1 | -- This file is part of bladeRF-wiphy.
2 | --
3 | -- Copyright (C) 2020 Nuand, LLC.
4 | --
5 | -- This program is free software; you can redistribute it and/or modify
6 | -- it under the terms of the GNU General Public License as published by
7 | -- the Free Software Foundation; either version 2 of the License, or
8 | -- (at your option) any later version.
9 | --
10 | -- This program is distributed in the hope that it will be useful,
11 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | -- GNU General Public License for more details.
14 | --
15 | -- You should have received a copy of the GNU General Public License along
16 | -- with this program; if not, write to the Free Software Foundation, Inc.,
17 | -- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 |
19 | library ieee ;
20 | use ieee.std_logic_1164.all ;
21 | use ieee.numeric_std.all ;
22 | use ieee.math_real.all ;
23 |
24 | library wlan ;
25 | use wlan.wlan_p.all ;
26 | use wlan.wlan_rx_p.all ;
27 |
28 | entity wlan_p_norm is
29 | port (
30 | -- 40MHz clock and async asserted, sync deasserted reset
31 | clock : in std_logic ;
32 | reset : in std_logic ;
33 | quiet : in std_logic ;
34 |
35 |
36 | sample : in wlan_sample_t ;
37 | p_normed : out wlan_sample_t ;
38 |
39 | p_mag : out signed( 23 downto 0 )
40 | ) ;
41 | end entity ;
42 |
43 | architecture arch of wlan_p_norm is
44 | signal iir : signed( 31 downto 0 ) ;
45 | signal saved_iir: signed( 31 downto 0 ) ;
46 | signal dat : signed( 31 downto 0 ) ;
47 | signal log2 : unsigned ( 8 downto 0 ) ;
48 | signal ptemp : signed( 31 downto 0 ) ;
49 | signal timer : unsigned( 8 downto 0 ) ;
50 | type unsigned_array_t is array (natural range 0 to 511) of signed( 23 downto 0 ) ;
51 |
52 | function calc_lut return unsigned_array_t is
53 | variable rv : unsigned_array_t ;
54 | variable i : real ;
55 | variable two : real ;
56 | begin
57 | for x in rv'range loop
58 | i := ( 24.0 - (real(x) / 16.0) ) / 2.0 + 12.0; -- i is in log2
59 | report integer'image(x) & " LUT " & real'image(i);
60 | -- if (i > 5.0) then
61 | -- i := 5.0;
62 | -- end if;
63 | two := 2 ** i ;
64 | if (real(two) > 5.7e5) then
65 | two := 5.7e5;
66 | end if;
67 | report integer'image(x) & " pow " & real'image(two);
68 | rv(x) := to_signed(integer(round(two)), 24) ;
69 | end loop ;
70 | return rv ;
71 | end;
72 | constant mult_lut : unsigned_array_t := calc_lut;
73 |
74 | function log2x( x : signed( 31 downto 0) )
75 | return unsigned is
76 | variable bits : unsigned( 8 downto 0 ) ;
77 | begin
78 | bits := (others => '0') ;
79 | for i in x'range loop
80 | if (x(i) = '1') then
81 | bits(8 downto 4) := to_unsigned(i, 5) ;
82 | if (real(i) < 4.0) then
83 | bits(3 downto 4 - i) := unsigned(x(i - 1 downto 0)) ;
84 | else
85 | bits(3 downto 0) := unsigned(x(i - 1 downto i - 4)) ;
86 | end if;
87 | -- bits(3 downto 0) <=
88 | exit ;
89 | end if ;
90 | end loop ;
91 | return bits ;
92 | end log2x ;
93 |
94 | function run_iir( x : signed( 31 downto 0); y : signed ( 31 downto 0) )
95 | return signed
96 | is
97 | variable amrea : signed(31 downto 0) ;
98 | begin
99 | amrea := resize( x - shift_right(x, 6) + shift_right(y, 6), 32 );
100 | return amrea;
101 | end;
102 | begin
103 | process( clock )
104 | variable t : signed( 31 downto 0 ) ;
105 | begin
106 | if( reset = '1' ) then
107 | iir <= ( others => '0' ) ;
108 | saved_iir <= ( others => '0' ) ;
109 | ptemp <= ( others => '0' ) ;
110 | timer <= ( others => '0' ) ;
111 | p_mag <= ( others => '0' ) ;
112 | elsif( rising_edge( clock )) then
113 | if( quiet = '1' ) then
114 | ptemp <= ( others => '0' ) ;
115 | timer <= ( others => '0' ) ;
116 | else
117 | if( timer < 200 ) then
118 | timer <= timer + 1 ;
119 | end if ;
120 | if( timer = 18 ) then
121 | iir <= ptemp;
122 | end if ;
123 | if( timer = 30 ) then
124 | saved_iir <= iir ;
125 | end if ;
126 | end if ;
127 | if (sample.valid = '1') then
128 | ptemp <= sample.i * sample.i + sample.q * sample.q ;
129 | iir <= run_iir(iir, ptemp) ;
130 | p_normed.i <= resize(shift_right(sample.i * mult_lut(to_integer(log2x(saved_iir))) ,12),16);
131 | p_normed.q <= resize(shift_right(sample.q * mult_lut(to_integer(log2x(saved_iir))) ,12),16);
132 | p_mag <= signed(resize(mult_lut(to_integer(log2x(saved_iir))), 24));
133 | --p_normed.q <= sample.q * mult_lut(log2x(t));
134 | --dat <= log2x(t) * ;
135 | log2 <= log2x(iir) ;
136 | end if ;
137 | if (timer < 30 ) then
138 | p_normed.valid <= '0' ;
139 | else
140 | p_normed.valid <= sample.valid ;
141 | end if ;
142 | end if ;
143 | end process ;
144 | end architecture ;
145 |
--------------------------------------------------------------------------------
/fpga/vhdl/wlan_peak_finder.vhd:
--------------------------------------------------------------------------------
1 | -- This file is part of bladeRF-wiphy.
2 | --
3 | -- Copyright (C) 2020 Nuand, LLC.
4 | --
5 | -- This program is free software; you can redistribute it and/or modify
6 | -- it under the terms of the GNU General Public License as published by
7 | -- the Free Software Foundation; either version 2 of the License, or
8 | -- (at your option) any later version.
9 | --
10 | -- This program is distributed in the hope that it will be useful,
11 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | -- GNU General Public License for more details.
14 | --
15 | -- You should have received a copy of the GNU General Public License along
16 | -- with this program; if not, write to the Free Software Foundation, Inc.,
17 | -- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 |
19 | library ieee ;
20 | use ieee.std_logic_1164.all ;
21 | use ieee.numeric_std.all ;
22 |
23 | library wlan ;
24 | use wlan.wlan_p.all ;
25 | use wlan.wlan_rx_p.all ;
26 |
27 | entity wlan_peak_finder is
28 | generic (
29 | SAMPLE_WINDOW : integer := 31
30 | ) ;
31 | port (
32 | clock : in std_logic ;
33 | reset : in std_logic ;
34 |
35 | sample : in unsigned(127 downto 0 ) ;
36 | sample_valid : in std_logic;
37 | peak : out std_logic
38 | ) ;
39 | end entity ;
40 |
41 | architecture arch of wlan_peak_finder is
42 |
43 | type peak_array_t is array(0 to SAMPLE_WINDOW-1) of unsigned(sample'range) ;
44 |
45 | signal samples : peak_array_t ;
46 |
47 | begin
48 |
49 | process( clock )
50 | variable highest : std_logic;
51 | begin
52 | if( rising_edge( clock ) ) then
53 | if( sample_valid = '1' ) then
54 | for i in 0 to samples'high - 1 loop
55 | samples(i+1) <= samples(i) ;
56 | end loop ;
57 | samples(0) <= sample ;
58 |
59 | highest := '1';
60 | for i in samples'range loop
61 | if (i /= 15 and samples(i) > samples(15)) then
62 | highest := '0';
63 | end if;
64 | end loop;
65 | if (samples(15) < 300000000) then
66 | highest := '0';
67 | end if;
68 |
69 | peak <= highest;
70 |
71 | end if ;
72 | end if ;
73 | end process ;
74 |
75 | end architecture ;
76 |
77 |
--------------------------------------------------------------------------------
/fpga/vhdl/wlan_rx_p.vhd:
--------------------------------------------------------------------------------
1 | -- This file is part of bladeRF-wiphy.
2 | --
3 | -- Copyright (C) 2020 Nuand, LLC.
4 | --
5 | -- This program is free software; you can redistribute it and/or modify
6 | -- it under the terms of the GNU General Public License as published by
7 | -- the Free Software Foundation; either version 2 of the License, or
8 | -- (at your option) any later version.
9 | --
10 | -- This program is distributed in the hope that it will be useful,
11 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | -- GNU General Public License for more details.
14 | --
15 | -- You should have received a copy of the GNU General Public License along
16 | -- with this program; if not, write to the Free Software Foundation, Inc.,
17 | -- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 |
19 | library ieee ;
20 | use ieee.std_logic_1164.all ;
21 | use ieee.numeric_std.all ;
22 | use ieee.math_real.all ;
23 |
24 | library work ;
25 | use work.wlan_p.all ;
26 |
27 | package wlan_rx_p is
28 |
29 | type wlan_rx_status_t is (RX_IDLE, RX_ACTIVE, RX_FAULT_SIGNAL_INVALID, RX_FAULT_OVERFLOW) ;
30 |
31 | type wlan_rx_vector_t is record
32 | length : positive range 1 to 4095 ;
33 | datarate : wlan_datarate_t ;
34 | bandwidth : wlan_bandwidth_t ;
35 | end record ;
36 |
37 | type wlan_rx_params_t is record
38 | n_bpsc : natural range 1 to 6 ;
39 | n_cbps : natural range 48 to 288 ;
40 | n_dbps : natural range 24 to 216 ;
41 | bandwidth : wlan_bandwidth_t ;
42 | modulation : wlan_modulation_t ;
43 | datarate : wlan_datarate_t ;
44 | length : natural range 1 to 4095 ;
45 | lfsr_init : unsigned(6 downto 0) ;
46 | num_data_symbols : natural range 1 to 12000 ;
47 | num_padding_bits : natural range 0 to 287 ;
48 | num_decoded_bits : natural range 0 to 32768 ;
49 | packet_valid : std_logic ;
50 | end record ;
51 |
52 | function NULL_PARAMS return wlan_rx_params_t ;
53 | function NULL_RX_VECTOR return wlan_rx_vector_t ;
54 |
55 | end package ;
56 |
57 | package body wlan_rx_p is
58 |
59 | function NULL_PARAMS return wlan_rx_params_t is
60 | variable rv : wlan_rx_params_t ;
61 | begin
62 | rv.n_bpsc := 1 ;
63 | rv.n_cbps := 48 ;
64 | rv.n_dbps := 24 ;
65 | rv.bandwidth := WLAN_BW_20 ;
66 | rv.modulation := WLAN_BPSK ;
67 | rv.datarate := WLAN_RATE_6 ;
68 | rv.length := 1 ;
69 | rv.lfsr_init := (others =>'1') ;
70 | rv.num_data_symbols := 1 ;
71 | rv.num_padding_bits := 0 ;
72 | return rv ;
73 | end function ;
74 |
75 | function NULL_RX_VECTOR return wlan_rx_vector_t is
76 | variable rv : wlan_rx_vector_t ;
77 | begin
78 | rv.length := 1 ;
79 | rv.datarate := WLAN_RATE_6 ;
80 | rv.bandwidth := WLAN_BW_20 ;
81 | return rv ;
82 | end function ;
83 |
84 | end package body ;
85 |
--------------------------------------------------------------------------------
/fpga/vhdl/wlan_sample_buffer.vhd:
--------------------------------------------------------------------------------
1 | -- This file is part of bladeRF-wiphy.
2 | --
3 | -- Copyright (C) 2020 Nuand, LLC.
4 | --
5 | -- This program is free software; you can redistribute it and/or modify
6 | -- it under the terms of the GNU General Public License as published by
7 | -- the Free Software Foundation; either version 2 of the License, or
8 | -- (at your option) any later version.
9 | --
10 | -- This program is distributed in the hope that it will be useful,
11 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | -- GNU General Public License for more details.
14 | --
15 | -- You should have received a copy of the GNU General Public License along
16 | -- with this program; if not, write to the Free Software Foundation, Inc.,
17 | -- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 |
19 | library ieee ;
20 | use ieee.std_logic_1164.all ;
21 | use ieee.numeric_std.all ;
22 |
23 | library work ;
24 | use work.wlan_p.all ;
25 |
26 | library altera_mf ;
27 | use altera_mf.altera_mf_components.all ;
28 |
29 | entity wlan_sample_buffer is
30 | port (
31 | clock : in std_logic ;
32 | reset : in std_logic ;
33 |
34 | -- Status
35 | room : out std_logic ;
36 |
37 | -- Short sequence inputs
38 | short : in wlan_sample_t ;
39 |
40 | -- Long sequence inputs
41 | long : in wlan_sample_t ;
42 |
43 | -- Symbol IFFT inputs
44 | symbol : in wlan_sample_t ;
45 |
46 | -- Sample FIFO outputs
47 | sample : out wlan_sample_t ;
48 | sample_i : out signed(15 downto 0) ;
49 | sample_q : out signed(15 downto 0) ;
50 | sample_re : in std_logic ;
51 | sample_empty : out std_logic
52 | ) ;
53 | end entity ;
54 |
55 | architecture arch of wlan_sample_buffer is
56 |
57 | signal fifo_write : std_logic ;
58 | signal fifo_read : std_logic ;
59 | signal fifo_input : std_logic_vector(31 downto 0) ;
60 | signal fifo_output : std_logic_vector(31 downto 0) ;
61 | signal fifo_empty : std_logic ;
62 | signal fifo_full : std_logic ;
63 | signal fifo_usedw : std_logic_vector(9 downto 0) ;
64 |
65 | signal mux_i : signed(15 downto 0) ;
66 | signal mux_q : signed(15 downto 0) ;
67 |
68 | begin
69 |
70 | check_fifo : process(clock)
71 | begin
72 | if( rising_edge(clock) ) then
73 | if( fifo_full = '1' and fifo_write = '1' ) then
74 | report "Writing to a full FIFO"
75 | severity error ;
76 | end if ;
77 | end if ;
78 | end process ;
79 |
80 | fifo_input <= std_logic_vector(mux_i) & std_logic_vector(mux_q) ;
81 | fifo_write <= short.valid or long.valid or symbol.valid ;
82 | fifo_read <= sample_re ;
83 | sample_i <= signed(fifo_output(31 downto 16)) ;
84 | sample_q <= signed(fifo_output(15 downto 0)) ;
85 | sample_empty <= fifo_empty ;
86 |
87 | mux_input : process(all)
88 | begin
89 | if( short.valid = '1' ) then
90 | mux_i <= short.i ;
91 | mux_q <= short.q ;
92 | elsif( long.valid = '1' ) then
93 | mux_i <= long.i ;
94 | mux_q <= long.q ;
95 | elsif( symbol.valid = '1' ) then
96 | mux_i <= symbol.i ;
97 | mux_q <= symbol.q ;
98 | else
99 | mux_i <= (others =>'0') ;
100 | mux_q <= (others =>'0') ;
101 | end if ;
102 | end process ;
103 |
104 | room <= '1' when unsigned(fifo_usedw) < 2**(fifo_usedw'length)-128 else '0' ;
105 |
106 | U_fifo : scfifo
107 | generic map (
108 | lpm_width => fifo_input'length,
109 | lpm_widthu => fifo_usedw'length,
110 | lpm_numwords => 2**(fifo_usedw'length),
111 | lpm_showahead => "ON"
112 | ) port map (
113 | clock => clock,
114 | aclr => reset,
115 | data => fifo_input,
116 | wrreq => fifo_write,
117 | rdreq => fifo_read,
118 | q => fifo_output,
119 | full => fifo_full,
120 | empty => fifo_empty,
121 | usedw => fifo_usedw
122 | ) ;
123 |
124 | end architecture ;
125 |
126 |
--------------------------------------------------------------------------------
/fpga/vhdl/wlan_tx_long.vhd:
--------------------------------------------------------------------------------
1 | -- This file is part of bladeRF-wiphy.
2 | --
3 | -- Copyright (C) 2020 Nuand, LLC.
4 | --
5 | -- This program is free software; you can redistribute it and/or modify
6 | -- it under the terms of the GNU General Public License as published by
7 | -- the Free Software Foundation; either version 2 of the License, or
8 | -- (at your option) any later version.
9 | --
10 | -- This program is distributed in the hope that it will be useful,
11 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | -- GNU General Public License for more details.
14 | --
15 | -- You should have received a copy of the GNU General Public License along
16 | -- with this program; if not, write to the Free Software Foundation, Inc.,
17 | -- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 |
19 | library ieee ;
20 | use ieee.std_logic_1164.all ;
21 | use ieee.numeric_std.all ;
22 | use ieee.math_real.all ;
23 |
24 | library work ;
25 | use work.wlan_p.all ;
26 | use work.wlan_tx_p.all ;
27 |
28 | entity wlan_tx_long is
29 | port (
30 | clock : in std_logic ;
31 | reset : in std_logic ;
32 | start : in std_logic ;
33 | done : out std_logic ;
34 | out_sample : out wlan_sample_t ;
35 | out_valid_cp : out std_logic
36 | ) ;
37 | end entity ;
38 |
39 | architecture arch of wlan_tx_long is
40 |
41 | function create_long_sequence return sample_array_t is
42 | variable rv : sample_array_t(LONG_SEQ_TIME'range) ;
43 | begin
44 | for i in rv'range loop
45 | rv(i).i := to_signed(integer(round(LONG_SEQ_TIME(i).re*4096.0*4.0)),rv(i).i'length) ;
46 | rv(i).q := to_signed(integer(round(LONG_SEQ_TIME(i).im*4096.0*4.0)),rv(i).q'length) ;
47 | rv(i).valid := '1' ;
48 | end loop;
49 | return rv ;
50 | end function ;
51 |
52 | constant LONG_SEQ : sample_array_t := create_long_sequence ;
53 |
54 | type fsm_t is (IDLE, CYCLIC_PREFIX, T_SEQ) ;
55 |
56 | type state_t is record
57 | fsm : fsm_t ;
58 | repeat : natural range 1 to 2 ;
59 | index : natural range LONG_SEQ'range ;
60 | sample : wlan_sample_t ;
61 | valid_cp : std_logic ;
62 | done : std_logic ;
63 | end record ;
64 |
65 | constant NULL_STATE : state_t := (
66 | fsm => IDLE,
67 | repeat => 2,
68 | index => 32,
69 | sample => NULL_SAMPLE,
70 | valid_cp => '0',
71 | done => '0'
72 | ) ;
73 |
74 | -- FSM state
75 | signal current, future : state_t := NULL_STATE ;
76 |
77 | begin
78 |
79 | done <= current.done ;
80 | out_sample <= current.sample ;
81 | out_valid_cp <= current.valid_cp ;
82 |
83 | seq : process(clock, reset)
84 | begin
85 | if( reset = '1' ) then
86 | current <= NULL_STATE ;
87 | elsif( rising_edge(clock) ) then
88 | current <= future ;
89 | end if ;
90 | end process ;
91 |
92 | comb : process(all)
93 | begin
94 | future <= current ;
95 | case current.fsm is
96 | when IDLE =>
97 | future <= NULL_STATE ;
98 | if( start = '1' ) then
99 | future.fsm <= CYCLIC_PREFIX ;
100 | end if ;
101 |
102 | when CYCLIC_PREFIX =>
103 | future.sample <= LONG_SEQ(current.index) ;
104 | future.valid_cp <= '1' ;
105 | future.sample.valid <= '0' ;
106 | if( current.index < LONG_SEQ'high ) then
107 | future.index <= current.index + 1 ;
108 | else
109 | future.fsm <= T_SEQ ;
110 | future.index <= 0 ;
111 | end if ;
112 |
113 | when T_SEQ =>
114 | future.sample <= LONG_SEQ(current.index) ;
115 | future.valid_cp <= '0' ;
116 | if( current.index < LONG_SEQ'high ) then
117 | future.index <= current.index + 1 ;
118 | else
119 | if( current.repeat = 1 ) then
120 | future.fsm <= IDLE ;
121 | future.done <= '1' ;
122 | else
123 | future.repeat <= current.repeat - 1 ;
124 | future.index <= 0 ;
125 | end if ;
126 | end if ;
127 |
128 | when others =>
129 | future <= NULL_STATE ;
130 |
131 | end case ;
132 | end process ;
133 |
134 | end architecture ;
135 |
136 |
--------------------------------------------------------------------------------
/fpga/vhdl/wlan_tx_p.vhd:
--------------------------------------------------------------------------------
1 | -- This file is part of bladeRF-wiphy.
2 | --
3 | -- Copyright (C) 2020 Nuand, LLC.
4 | --
5 | -- This program is free software; you can redistribute it and/or modify
6 | -- it under the terms of the GNU General Public License as published by
7 | -- the Free Software Foundation; either version 2 of the License, or
8 | -- (at your option) any later version.
9 | --
10 | -- This program is distributed in the hope that it will be useful,
11 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | -- GNU General Public License for more details.
14 | --
15 | -- You should have received a copy of the GNU General Public License along
16 | -- with this program; if not, write to the Free Software Foundation, Inc.,
17 | -- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 |
19 | library ieee ;
20 | use ieee.std_logic_1164.all ;
21 | use ieee.numeric_std.all ;
22 | use ieee.math_real.all ;
23 |
24 | library work ;
25 | use work.wlan_p.all ;
26 |
27 | package wlan_tx_p is
28 |
29 | type wlan_tx_vector_t is record
30 | length : positive range 1 to 4095 ;
31 | datarate : wlan_datarate_t ;
32 | bandwidth : wlan_bandwidth_t ;
33 | end record ;
34 |
35 | type wlan_tx_params_t is record
36 | n_bpsc : natural range 1 to 6 ;
37 | n_cbps : natural range 48 to 288 ;
38 | n_dbps : natural range 24 to 216 ;
39 | modulation : wlan_modulation_t ;
40 | datarate : wlan_datarate_t ;
41 | length : natural range 1 to 4095 ;
42 | lfsr_init : unsigned(6 downto 0) ;
43 | num_decoded_bits : natural range 8 to 11224 ;
44 | num_data_symbols : natural range 1 to 1366 ;
45 | num_padding_bits : natural range 0 to 287 ;
46 | end record ;
47 |
48 | function NULL_PARAMS return wlan_tx_params_t ;
49 | function NULL_TX_VECTOR return wlan_tx_vector_t ;
50 |
51 | type wlan_tx_status_t is (TX_IDLE, TX_SHORT, TX_LONG, TX_DATA, TX_FAULT_NODATA, TX_FAULT_UNDERRUN) ;
52 |
53 | end package ;
54 |
55 | package body wlan_tx_p is
56 |
57 | function NULL_PARAMS return wlan_tx_params_t is
58 | variable rv : wlan_tx_params_t ;
59 | begin
60 | rv.n_bpsc := 1 ;
61 | rv.n_cbps := 48 ;
62 | rv.n_dbps := 24 ;
63 | rv.modulation := WLAN_BPSK ;
64 | rv.datarate := WLAN_RATE_6 ;
65 | rv.length := 1 ;
66 | rv.lfsr_init := (others =>'1') ;
67 | rv.num_data_symbols := 0 ;
68 | rv.num_data_symbols := 1 ;
69 | rv.num_padding_bits := 0 ;
70 | return rv ;
71 | end function ;
72 |
73 | function NULL_TX_VECTOR return wlan_tx_vector_t is
74 | variable rv : wlan_tx_vector_t ;
75 | begin
76 | rv.length := 1 ;
77 | rv.datarate := WLAN_RATE_6 ;
78 | rv.bandwidth := WLAN_BW_20 ;
79 | return rv ;
80 | end function ;
81 |
82 | end package body ;
83 |
--------------------------------------------------------------------------------
/fpga/vhdl/wlan_tx_short.vhd:
--------------------------------------------------------------------------------
1 | -- This file is part of bladeRF-wiphy.
2 | --
3 | -- Copyright (C) 2020 Nuand, LLC.
4 | --
5 | -- This program is free software; you can redistribute it and/or modify
6 | -- it under the terms of the GNU General Public License as published by
7 | -- the Free Software Foundation; either version 2 of the License, or
8 | -- (at your option) any later version.
9 | --
10 | -- This program is distributed in the hope that it will be useful,
11 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | -- GNU General Public License for more details.
14 | --
15 | -- You should have received a copy of the GNU General Public License along
16 | -- with this program; if not, write to the Free Software Foundation, Inc.,
17 | -- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 |
19 | library ieee ;
20 | use ieee.std_logic_1164.all ;
21 | use ieee.numeric_std.all ;
22 | use ieee.math_real.all ;
23 |
24 | library work ;
25 | use work.wlan_p.all ;
26 | use work.wlan_tx_p.all ;
27 |
28 | entity wlan_tx_short is
29 | port (
30 | clock : in std_logic ;
31 | reset : in std_logic ;
32 | start : in std_logic ;
33 | done : out std_logic ;
34 | out_sample : out wlan_sample_t
35 | ) ;
36 | end entity ;
37 |
38 | architecture arch of wlan_tx_short is
39 |
40 | function create_short_sequence return sample_array_t is
41 | variable rv : sample_array_t(SHORT_SEQ_TIME'range) ;
42 | begin
43 | for i in rv'range loop
44 | rv(i).i := to_signed(integer(round(SHORT_SEQ_TIME(i).re*4.0*4096.0)),rv(i).i'length) ;
45 | rv(i).q := to_signed(integer(round(SHORT_SEQ_TIME(i).im*4.0*4096.0)),rv(i).i'length) ;
46 | rv(i).valid := '1' ;
47 | end loop ;
48 | return rv ;
49 | end function ;
50 |
51 | constant SHORT_SEQ : sample_array_t := create_short_sequence ;
52 |
53 | type fsm_t is (IDLE, COUNTING) ;
54 |
55 | type state_t is record
56 | fsm : fsm_t ;
57 | repeat : natural range 1 to 10 ;
58 | index : natural range short_seq'range ;
59 | sample : wlan_sample_t ;
60 | done : std_logic ;
61 | end record ;
62 |
63 | constant NULL_STATE : state_t := (
64 | fsm => IDLE,
65 | repeat => 10,
66 | index => 0,
67 | sample => NULL_SAMPLE,
68 | done => '0'
69 | ) ;
70 |
71 | -- FSM state
72 | signal current, future : state_t := NULL_STATE ;
73 |
74 | begin
75 |
76 | done <= current.done ;
77 | out_sample <= current.sample ;
78 |
79 | seq : process(clock, reset)
80 | begin
81 | if( reset = '1' ) then
82 | current <= NULL_STATE ;
83 | elsif( rising_edge(clock) ) then
84 | current <= future ;
85 | end if ;
86 | end process ;
87 |
88 | comb : process(all)
89 | begin
90 | future <= current ;
91 | case current.fsm is
92 | when IDLE =>
93 | future <= NULL_STATE ;
94 | if( start = '1' ) then
95 | future.fsm <= COUNTING ;
96 | end if ;
97 |
98 | when COUNTING =>
99 | future.sample <= short_seq(current.index) ;
100 | if( current.index < short_seq'high ) then
101 | future.index <= current.index + 1 ;
102 | else
103 | if( current.repeat = 1 ) then
104 | future.fsm <= IDLE ;
105 | future.done <= '1' ;
106 | else
107 | future.repeat <= current.repeat - 1 ;
108 | future.index <= 0 ;
109 | end if ;
110 | end if ;
111 |
112 | when others =>
113 | future <= NULL_STATE ;
114 | end case ;
115 | end process ;
116 |
117 | end architecture ;
118 |
119 |
--------------------------------------------------------------------------------
/fpga/vhdl/wlan_viterbi_decoder.vhd:
--------------------------------------------------------------------------------
1 | -- This file is part of bladeRF-wiphy.
2 | --
3 | -- Copyright (C) 2020 Nuand, LLC.
4 | --
5 | -- This program is free software; you can redistribute it and/or modify
6 | -- it under the terms of the GNU General Public License as published by
7 | -- the Free Software Foundation; either version 2 of the License, or
8 | -- (at your option) any later version.
9 | --
10 | -- This program is distributed in the hope that it will be useful,
11 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | -- GNU General Public License for more details.
14 | --
15 | -- You should have received a copy of the GNU General Public License along
16 | -- with this program; if not, write to the Free Software Foundation, Inc.,
17 | -- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 |
19 | library ieee ;
20 | use ieee.std_logic_1164.all ;
21 | use ieee.numeric_std.all ;
22 |
23 | library wlan ;
24 | use wlan.wlan_p.all ;
25 | use wlan.wlan_rx_p.all ;
26 |
27 | library work ;
28 | library viterbi_decoder ;
29 |
30 | entity wlan_viterbi_decoder is
31 | port (
32 | clock : in std_logic ;
33 | reset : in std_logic ;
34 |
35 | init : in std_logic ;
36 |
37 | in_soft_a : in signed(7 downto 0) ;
38 | in_soft_b : in signed(7 downto 0) ;
39 | in_erasure : in std_logic_vector(1 downto 0) ;
40 | in_valid : in std_logic ;
41 |
42 | params : in wlan_rx_params_t ;
43 | params_valid : in std_logic ;
44 |
45 | done : out std_logic ;
46 |
47 | out_dec_bit : out std_logic ;
48 | out_dec_valid : out std_logic
49 | ) ;
50 | end entity ;
51 |
52 | architecture arch of wlan_viterbi_decoder is
53 |
54 | type fsm_t is (IDLE, DECODE, RESET_CORE ) ;
55 |
56 | type state_t is record
57 | fsm : fsm_t ;
58 | num_decoded_bits : unsigned( 13 downto 0 ) ;
59 | done : std_logic ;
60 | end record ;
61 |
62 | function NULL_STATE return state_t is
63 | variable rv : state_t ;
64 | begin
65 | rv.fsm := IDLE ;
66 | rv.num_decoded_bits := ( others => '0' );
67 | rv.done := '0' ;
68 | return rv ;
69 | end function ;
70 |
71 | signal sink_rdy : std_logic ;
72 | signal sink_val : std_logic ;
73 |
74 | signal source_rdy : std_logic ;
75 | signal source_val : std_logic ;
76 |
77 | signal rr : std_logic_vector(15 downto 0) ;
78 |
79 | signal decbit : std_logic ;
80 |
81 | signal normalizations : std_logic_vector(7 downto 0) ;
82 |
83 | signal core_reset : std_logic ;
84 |
85 | signal current, future : state_t := NULL_STATE ;
86 |
87 | function fix_var( x : signed(7 downto 0) ) return std_logic_vector is
88 | variable ret : std_logic_vector(7 downto 0);
89 | begin
90 | ret(6 downto 0) := not(std_logic_vector(x(6 downto 0)));
91 | ret(7) := x(7);
92 | return (ret);
93 | end function;
94 |
95 | begin
96 |
97 | done <= current.done ;
98 |
99 | sync : process(clock, reset)
100 | begin
101 | if( reset = '1' ) then
102 | current <= NULL_STATE ;
103 | elsif( rising_edge(clock) ) then
104 | if( init = '1' ) then
105 | current <= NULL_STATE ;
106 | else
107 | current <= future ;
108 | end if ;
109 | end if ;
110 | end process ;
111 |
112 | comb : process(all)
113 | begin
114 | future <= current ;
115 | future.done <= '0' ;
116 |
117 | case current.fsm is
118 | when IDLE =>
119 | if( params_valid = '1' ) then
120 | future.num_decoded_bits <= to_unsigned(params.num_decoded_bits - 1, future.num_decoded_bits'length ) ;
121 | future.fsm <= DECODE ;
122 | end if ;
123 |
124 | when DECODE =>
125 | if( source_val = '1' ) then
126 | future.num_decoded_bits <= current.num_decoded_bits - 1;
127 | end if ;
128 | if( current.num_decoded_bits = 0 ) then
129 | future.done <= '1' ;
130 | future.fsm <= RESET_CORE ;
131 | end if ;
132 |
133 | when RESET_CORE =>
134 | future.fsm <= IDLE ;
135 | end case ;
136 | end process ;
137 |
138 | core_reset <= '1' when current.fsm = RESET_CORE or current.fsm = IDLE or reset = '1' else '0' ;
139 | rr <= std_logic_vector(in_soft_a) & std_logic_vector(in_soft_b) ;
140 | sink_val <= in_valid ;
141 |
142 | --U_altera_decoder : entity viterbi_decoder.viterbi_decoder
143 | -- port map (
144 | -- clk => clock,
145 | -- reset => core_reset,
146 |
147 | -- sink_val => sink_val,
148 | -- sink_rdy => sink_rdy,
149 | -- rr => rr,
150 | -- eras_sym => in_erasure,
151 |
152 | -- source_rdy => source_rdy,
153 | -- source_val => source_val,
154 | -- decbit => decbit,
155 | -- normalizations => normalizations
156 | -- ) ;
157 | U_vit : entity work.viterbi_decoder
158 | generic map(
159 | TB_LEN => 60
160 | )
161 | port map(
162 | clock => clock,
163 | reset => core_reset,
164 | in_a => (fix_var(in_soft_a)),
165 | in_b => (fix_var(in_soft_b)),
166 | erasure => in_erasure(0) & in_erasure(1),
167 | bsd_valid => in_valid,
168 |
169 | out_bit => decbit,
170 | out_valid => source_val
171 | );
172 |
173 |
174 |
175 | out_dec_bit <= decbit ;
176 | out_dec_valid <= source_val ;
177 | source_rdy <= '1' ;
178 |
179 | end architecture ;
180 |
181 |
--------------------------------------------------------------------------------
/fpga/vhdl/wlan_viterbi_encoder.vhd:
--------------------------------------------------------------------------------
1 | -- This file is part of bladeRF-wiphy.
2 | --
3 | -- Copyright (C) 2020 Nuand, LLC.
4 | --
5 | -- This program is free software; you can redistribute it and/or modify
6 | -- it under the terms of the GNU General Public License as published by
7 | -- the Free Software Foundation; either version 2 of the License, or
8 | -- (at your option) any later version.
9 | --
10 | -- This program is distributed in the hope that it will be useful,
11 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | -- GNU General Public License for more details.
14 | --
15 | -- You should have received a copy of the GNU General Public License along
16 | -- with this program; if not, write to the Free Software Foundation, Inc.,
17 | -- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 |
19 | library ieee ;
20 | use ieee.std_logic_1164.all ;
21 | use ieee.numeric_std.all ;
22 |
23 | library work ;
24 |
25 | entity wlan_viterbi_encoder is
26 | generic (
27 | WIDTH : positive := 4
28 | ) ;
29 | port (
30 | clock : in std_logic ;
31 | reset : in std_logic ;
32 |
33 | init : in std_logic ;
34 |
35 | in_data : in std_logic_vector(WIDTH-1 downto 0) ;
36 | in_valid : in std_logic ;
37 | in_done : in std_logic ;
38 |
39 | out_a : out std_logic_vector(WIDTH-1 downto 0) ;
40 | out_b : out std_logic_vector(WIDTH-1 downto 0) ;
41 | out_done : out std_logic ;
42 | out_valid : out std_logic
43 | ) ;
44 | end entity ;
45 |
46 | architecture arch of wlan_viterbi_encoder is
47 |
48 | signal state : unsigned(5 downto 0) := (others =>'0') ;
49 |
50 | begin
51 |
52 | encode : process(clock, reset)
53 | variable tempstate : unsigned(state'range) := (others =>'0') ;
54 | begin
55 | if( reset = '1' ) then
56 | state <= (others =>'0') ;
57 | out_a <= (others =>'0') ;
58 | out_b <= (others =>'0') ;
59 | out_valid <= '0' ;
60 | out_done <= '0' ;
61 | tempstate := (others =>'0') ;
62 | elsif( rising_edge(clock) ) then
63 | out_valid <= '0' ;
64 | out_done <= in_done ;
65 | if( init = '1' ) then
66 | state <= (others =>'0') ;
67 | else
68 | out_valid <= in_valid ;
69 | if( in_valid = '1' ) then
70 | tempstate := state ;
71 | for i in 0 to in_data'high loop
72 | out_a(i) <= tempstate(5) xor tempstate(4) xor tempstate(2) xor tempstate(1) xor in_data(i) ;
73 | out_b(i) <= tempstate(5) xor tempstate(2) xor tempstate(1) xor tempstate(0) xor in_data(i) ;
74 | tempstate := tempstate(4 downto 0) & in_data(i) ;
75 | end loop ;
76 | state <= tempstate ;
77 | end if ;
78 | end if ;
79 | end if ;
80 | end process ;
81 |
82 | end architecture ;
83 |
84 |
--------------------------------------------------------------------------------
/matlab/util.m:
--------------------------------------------------------------------------------
1 | % This file is part of bladeRF-wiphy.
2 | %
3 | % Copyright (C) 2020 Nuand, LLC.
4 | %
5 | % This program is free software; you can redistribute it and/or modify
6 | % it under the terms of the GNU General Public License as published by
7 | % the Free Software Foundation; either version 2 of the License, or
8 | % (at your option) any later version.
9 | %
10 | % This program is distributed in the hope that it will be useful,
11 | % but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | % GNU General Public License for more details.
14 | %
15 | % You should have received a copy of the GNU General Public License along
16 | % with this program; if not, write to the Free Software Foundation, Inc.,
17 | % 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 |
19 | % Null OFDM symbol
20 | null = zeros(64,1) ;
21 |
22 | % Short preamble generation
23 | SHORT_ONE = 1.472 + 1.472*1j ;
24 |
25 | % Bins for positive and negative values
26 | % NOTE: MATLAB has bin 1 as the DC bin, but standard uses
27 | % bin 0 as DC, so we will define all bins here similar to the
28 | % standard, and when indexing them, we will add the MATLAB offset.
29 | SHORT_POS = [12, 16, 20, 24, 40, 48, 60] ;
30 | SHORT_NEG = [4, 8, 44, 52, 56] ;
31 |
32 | short_preamble.freq = zeros(64,1) ;
33 | short_preamble.freq(SHORT_POS+1) = SHORT_ONE ;
34 | short_preamble.freq(SHORT_NEG+1) = -SHORT_ONE ;
35 | short_preamble.time = ifft(short_preamble.freq) ;
36 |
37 | % Long preamble generation
38 | LONG_ONE = 1 ;
39 |
40 | % Bins for positive and negative values
41 | LONG_POS = [1, 4, 5, 7, 9, 15, 16, 19, 21, 23, 24, 25, 26, 38, 39, 42, 43, 45, 47, 48, 49, 50, 51, 52, 55, 56, 58, 60, 61, 62, 63 ] ;
42 | LONG_NEG = [2, 3, 6, 8, 10, 11, 12, 13, 14, 17, 18, 20, 22, 40, 41, 44, 46, 53, 54, 57, 59 ] ;
43 |
44 | long_preamble.freq = zeros(64,1) ;
45 | long_preamble.freq(LONG_POS+1) = LONG_ONE ;
46 | long_preamble.freq(LONG_NEG+1) = -LONG_ONE ;
47 | long_preamble.time = ifft(long_preamble.freq) ;
48 |
49 |
50 |
--------------------------------------------------------------------------------
/matlab/wlan_rx.m:
--------------------------------------------------------------------------------
1 | % This file is part of bladeRF-wiphy.
2 | %
3 | % Copyright (C) 2020 Nuand, LLC.
4 | %
5 | % This program is free software; you can redistribute it and/or modify
6 | % it under the terms of the GNU General Public License as published by
7 | % the Free Software Foundation; either version 2 of the License, or
8 | % (at your option) any later version.
9 | %
10 | % This program is distributed in the hope that it will be useful,
11 | % but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | % GNU General Public License for more details.
14 | %
15 | % You should have received a copy of the GNU General Public License along
16 | % with this program; if not, write to the Free Software Foundation, Inc.,
17 | % 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 |
19 | %% User Parameters
20 | snr = 99 ;
21 |
22 | %% Initialization
23 |
24 | % Get common stuff, x is input signal
25 | util
26 | clear rx
27 | idx = 1 ;
28 |
29 | %% AWGN Channel with some phase offset
30 | % TODO: Make this more interesting
31 | %h = [1] ;
32 | % h = [ randn+1j*randn 0 (randn+1j*randn)/2 0 (randn+1j*randn)/4 ];
33 | h = [ 0.85 0.1 0 0.05 0 0.05 ] ;
34 | % Add noise
35 | noise = (randn(length(x),1) + randn(length(x),1)*1j) ;
36 | sp = sum(abs(x).^2) ;
37 | np = sum(abs(noise).^2) ;
38 |
39 | % Scale noise based on signal and noise power
40 | nl = sp / (10^(snr/10)) / np ;
41 | noise = sqrt(nl).*noise ;
42 |
43 | sp = sum(abs(x).^2) ;
44 | np = sum(abs(noise).^2) ;
45 | rx.actual_snr = 10*log10(sp/np) ;
46 |
47 | % Finally add the noise
48 | % NOTE: Channel impulse response does not have a group delay, so don't
49 | % delay the input, just chop it off.
50 | xn = conv(x,h) ; xn = xn(1:length(x)) ;
51 | xn = xn + noise ;
52 |
53 | % Add a phase rotation
54 | xn = xn .* exp(1j*pi/8) ;
55 |
56 | %% Acquisition
57 | % Acquire
58 | % TODO: Actually acquire here, but for now we know we just advance 160
59 | % samples into the signal
60 | rx.short = xn(idx:idx+160-1) ;
61 | idx = idx + 160 ; % short sequence
62 |
63 | %% Save off T1 and T2 after GI2
64 | % Initialize frequency offset correction
65 | idx = idx + 32 ; % GI2
66 | rx.t1 = xn(idx:idx+64-1) ;
67 | rx.T1 = fft(rx.t1) ;
68 | rx.T1(rx.T1==0) = 1e-20 ;
69 | idx = idx + 64 ; % T1
70 |
71 | % Figure out initial equalizer taps
72 | rx.t2 = xn(idx:idx+64-1) ;
73 | rx.T2 = fft(rx.t2) ;
74 | rx.T2(rx.T2==0) = 1e-20 ;
75 | idx = idx + 64 ; % T2
76 |
77 | %% Initialize Equalizer from average of T1 and T2
78 | % Since T1 and T2 should be the same, we should be able to average the
79 | % observed samples together and try to get rid of some noise.
80 | rx.tavg = (rx.t1 + rx.t2)./2 ;
81 | rx.TAVG = fft(rx.tavg) ;
82 |
83 | %rx.TAVG = fft([ h, zeros(1,64-length(h))].') ;
84 |
85 | % Equalizer is just the reference signal divided by received signal
86 | rx.EQ = long_preamble.freq .* conj(rx.TAVG) ./ (abs(rx.TAVG).^2 + 10^(-snr/10)) ;
87 |
88 | %% Extract SIGNAL frame
89 | idx = idx + 16 ; % GI
90 | rx.signal = xn(idx:idx+64-1) ;
91 | rx.SIGNAL = fft(rx.signal) ;
92 | rx.SIGNAL_EQ = rx.SIGNAL .* rx.EQ ;
93 | idx = idx + 64 ;
94 |
95 | %% Extract DATA frames
96 | n = 1 ;
97 | num_data_frames = floor((length(x) - idx)/80) ;
98 | rx.data = zeros(num_data_frames, 64) ;
99 | rx.DATA = zeros(num_data_frames, 64) ;
100 | idx = idx + 16 ; % GI
101 | while n <= num_data_frames
102 | rx.data(n,:) = xn(idx:idx+64-1) ;
103 | rx.DATA(n,:) = fft(rx.data(n,:)) ;
104 | rx.DATA_EQ(n,:) = rx.DATA(n,:) .* rx.EQ.' ;
105 | % Increment
106 | n = n + 1 ;
107 | idx = idx + 80 ;
108 | end
109 |
--------------------------------------------------------------------------------