1 |
36 |
dgisselq |
////////////////////////////////////////////////////////////////////////////
|
2 |
|
|
//
|
3 |
|
|
// Filename: snglbrev_tb.cpp
|
4 |
|
|
//
|
5 |
|
|
// Project: A General Purpose Pipelined FFT Implementation
|
6 |
|
|
//
|
7 |
|
|
// Purpose: A test-bench for the bitreversal stage of the pipelined
|
8 |
|
|
// FFT. This file may be run autonomously. If so, the last line
|
9 |
|
|
// output will either read "SUCCESS" on success, or some other failure
|
10 |
|
|
// message otherwise.
|
11 |
|
|
//
|
12 |
|
|
// This file depends upon verilator to both compile, run, and therefore
|
13 |
|
|
// test either snglbrev.v or dblreverse.v--depending on whether or not the
|
14 |
|
|
// FFT handles one or two inputs per clock respectively.
|
15 |
|
|
//
|
16 |
|
|
// Creator: Dan Gisselquist, Ph.D.
|
17 |
|
|
// Gisselquist Technology, LLC
|
18 |
|
|
//
|
19 |
|
|
///////////////////////////////////////////////////////////////////////////
|
20 |
|
|
//
|
21 |
|
|
// Copyright (C) 2015,2018, Gisselquist Technology, LLC
|
22 |
|
|
//
|
23 |
|
|
// This program is free software (firmware): you can redistribute it and/or
|
24 |
|
|
// modify it under the terms of the GNU General Public License as published
|
25 |
|
|
// by the Free Software Foundation, either version 3 of the License, or (at
|
26 |
|
|
// your option) any later version.
|
27 |
|
|
//
|
28 |
|
|
// This program is distributed in the hope that it will be useful, but WITHOUT
|
29 |
|
|
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
|
30 |
|
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
31 |
|
|
// for more details.
|
32 |
|
|
//
|
33 |
|
|
// You should have received a copy of the GNU General Public License along
|
34 |
|
|
// with this program. (It's in the $(ROOT)/doc directory, run make with no
|
35 |
|
|
// target there if the PDF file isn't present.) If not, see
|
36 |
|
|
// <http://www.gnu.org/licenses/> for a copy.
|
37 |
|
|
//
|
38 |
|
|
// License: GPL, v3, as defined and found on www.gnu.org,
|
39 |
|
|
// http://www.gnu.org/licenses/gpl.html
|
40 |
|
|
//
|
41 |
|
|
//
|
42 |
|
|
///////////////////////////////////////////////////////////////////////////
|
43 |
|
|
#include "verilated.h"
|
44 |
|
|
#include "verilated_vcd_c.h"
|
45 |
|
|
|
46 |
|
|
#include "fftsize.h"
|
47 |
|
|
#include "Vbitreverse.h"
|
48 |
|
|
|
49 |
|
|
#define FFTBITS TST_DBLREVERSE_LGSIZE
|
50 |
|
|
#define FFTSIZE (1<<(FFTBITS))
|
51 |
|
|
#define FFTMASK (FFTSIZE-1)
|
52 |
|
|
#define DATALEN (1<<(FFTBITS+1))
|
53 |
|
|
#define DATAMSK (DATALEN-1)
|
54 |
|
|
#define PAGEMSK (FFTSIZE)
|
55 |
|
|
|
56 |
|
|
#ifdef NEW_VERILATOR
|
57 |
|
|
#define VVAR(A) bitreverse__DOT_ ## A
|
58 |
|
|
#else
|
59 |
|
|
#define VVAR(A) v__DOT_ ## A
|
60 |
|
|
#endif
|
61 |
|
|
|
62 |
|
|
typedef Vbitreverse TSTCLASS;
|
63 |
|
|
|
64 |
|
|
#define iaddr VVAR(_wraddr)
|
65 |
|
|
#define in_reset VVAR(_in_reset)
|
66 |
|
|
|
67 |
|
|
VerilatedVcdC *trace = NULL;
|
68 |
|
|
uint64_t m_tickcount = 0;
|
69 |
|
|
|
70 |
|
|
void tick(TSTCLASS *brev) {
|
71 |
|
|
m_tickcount++;
|
72 |
|
|
|
73 |
|
|
brev->i_clk = 0;
|
74 |
|
|
brev->eval();
|
75 |
|
|
if (trace) trace->dump((uint64_t)(10ul*m_tickcount-2));
|
76 |
|
|
brev->i_clk = 1;
|
77 |
|
|
brev->eval();
|
78 |
|
|
if (trace) trace->dump((uint64_t)(10ul*m_tickcount));
|
79 |
|
|
brev->i_clk = 0;
|
80 |
|
|
brev->eval();
|
81 |
|
|
if (trace) {
|
82 |
|
|
trace->dump((uint64_t)(10ul*m_tickcount+5));
|
83 |
|
|
trace->flush();
|
84 |
|
|
}
|
85 |
|
|
|
86 |
|
|
brev->i_ce = 0;
|
87 |
|
|
}
|
88 |
|
|
|
89 |
|
|
void cetick(TSTCLASS *brev) {
|
90 |
|
|
brev->i_ce = 1;
|
91 |
|
|
tick(brev);
|
92 |
|
|
if (rand()&1) {
|
93 |
|
|
brev->i_ce = 1;
|
94 |
|
|
tick(brev);
|
95 |
|
|
}
|
96 |
|
|
}
|
97 |
|
|
|
98 |
|
|
void reset(TSTCLASS *brev) {
|
99 |
|
|
brev->i_ce = 0;
|
100 |
|
|
brev->i_reset = 1;
|
101 |
|
|
tick(brev);
|
102 |
|
|
brev->i_ce = 0;
|
103 |
|
|
brev->i_reset = 0;
|
104 |
|
|
tick(brev);
|
105 |
|
|
}
|
106 |
|
|
|
107 |
|
|
unsigned long bitrev(const int nbits, const unsigned long vl) {
|
108 |
|
|
unsigned long r = 0;
|
109 |
|
|
unsigned long val = vl;
|
110 |
|
|
|
111 |
|
|
for(int k=0; k<nbits; k++) {
|
112 |
|
|
r <<= 1;
|
113 |
|
|
r |= (val & 1);
|
114 |
|
|
val >>= 1;
|
115 |
|
|
}
|
116 |
|
|
|
117 |
|
|
return r;
|
118 |
|
|
}
|
119 |
|
|
|
120 |
|
|
int main(int argc, char **argv, char **envp) {
|
121 |
|
|
Verilated::commandArgs(argc, argv);
|
122 |
|
|
Verilated::traceEverOn(true);
|
123 |
|
|
TSTCLASS *brev = new TSTCLASS;
|
124 |
|
|
int syncd = 0;
|
125 |
|
|
unsigned long datastore[DATALEN], dataidx=0;
|
126 |
|
|
const int BREV_OFFSET = 0;
|
127 |
|
|
|
128 |
|
|
trace = new VerilatedVcdC;
|
129 |
|
|
brev->trace(trace, 99);
|
130 |
|
|
trace->open("bitreverse_tb.vcd");
|
131 |
|
|
|
132 |
|
|
reset(brev);
|
133 |
|
|
|
134 |
|
|
printf("FFTSIZE = %08x\n", FFTSIZE);
|
135 |
|
|
printf("FFTMASK = %08x\n", FFTMASK);
|
136 |
|
|
printf("DATALEN = %08x\n", DATALEN);
|
137 |
|
|
printf("DATAMSK = %08x\n", DATAMSK);
|
138 |
|
|
|
139 |
|
|
for(int k=0; k<4*(FFTSIZE); k++) {
|
140 |
|
|
brev->i_ce = 1;
|
141 |
|
|
#ifdef DBLCLKFFT
|
142 |
|
|
brev->i_in_0 = 2*k;
|
143 |
|
|
brev->i_in_1 = 2*k+1;
|
144 |
|
|
datastore[(dataidx++)&(DATAMSK)] = brev->i_in_0;
|
145 |
|
|
datastore[(dataidx++)&(DATAMSK)] = brev->i_in_1;
|
146 |
|
|
#else
|
147 |
|
|
brev->i_in = k;
|
148 |
|
|
datastore[(dataidx++)&(DATAMSK)] = brev->i_in;
|
149 |
|
|
#endif
|
150 |
|
|
tick(brev);
|
151 |
|
|
|
152 |
|
|
printf("k=%3d: IN = %6lx, OUT = %6lx, SYNC = %d\t(%2x) %d\n",
|
153 |
|
|
k, brev->i_in, brev->o_out, brev->o_sync,
|
154 |
|
|
brev->iaddr, brev->in_reset);
|
155 |
|
|
|
156 |
|
|
if ((k>BREV_OFFSET)&&((BREV_OFFSET==(k&FFTMASK))?1:0) != brev->o_sync) {
|
157 |
|
|
fprintf(stdout, "FAIL, BAD SYNC (k = %d > %d)\n", k, BREV_OFFSET);
|
158 |
|
|
exit(EXIT_FAILURE);
|
159 |
|
|
} else if (brev->o_sync) {
|
160 |
|
|
syncd = 1;
|
161 |
|
|
}
|
162 |
|
|
if ((syncd)&&((brev->o_out&FFTMASK) != bitrev(FFTBITS, k-BREV_OFFSET))) {
|
163 |
|
|
fprintf(stdout, "FAIL: BITREV.0 of k (%2x) = %2lx, not %2lx\n",
|
164 |
|
|
k, brev->o_out, bitrev(FFTBITS, (k-BREV_OFFSET)));
|
165 |
|
|
exit(EXIT_FAILURE);
|
166 |
|
|
}
|
167 |
|
|
}
|
168 |
|
|
|
169 |
|
|
for(int k=0; k<4*(FFTSIZE); k++) {
|
170 |
|
|
brev->i_ce = 1;
|
171 |
|
|
#ifdef DBLCLKFFT
|
172 |
|
|
brev->i_in_0 = rand() & 0x0ffffff;
|
173 |
|
|
brev->i_in_1 = rand() & 0x0ffffff;
|
174 |
|
|
datastore[(dataidx++)&(DATAMSK)] = brev->i_in_0;
|
175 |
|
|
datastore[(dataidx++)&(DATAMSK)] = brev->i_in_1;
|
176 |
|
|
#else
|
177 |
|
|
brev->i_in = rand() & 0x0ffffff;
|
178 |
|
|
datastore[(dataidx++)&(DATAMSK)] = brev->i_in;
|
179 |
|
|
#endif
|
180 |
|
|
tick(brev);
|
181 |
|
|
|
182 |
|
|
#ifdef DBLCLKFFT
|
183 |
|
|
printf("k=%3d: IN = %6lx : %6lx, OUT = %6lx : %6lx, SYNC = %d\n",
|
184 |
|
|
k, brev->i_in_0, brev->i_in_1,
|
185 |
|
|
brev->o_out_0, brev->o_out_1, brev->o_sync);
|
186 |
|
|
#else
|
187 |
|
|
printf("k=%3d: IN = %6lx, OUT = %6lx, SYNC = %d\n",
|
188 |
|
|
k, brev->i_in, brev->o_out, brev->o_sync);
|
189 |
|
|
#endif
|
190 |
|
|
|
191 |
|
|
if (brev->o_sync)
|
192 |
|
|
syncd = 1;
|
193 |
|
|
#ifdef DBLCLKFFT
|
194 |
|
|
if ((syncd)&&(brev->o_out_0 != datastore[(((dataidx-2-FFTSIZE)&PAGEMSK) + bitrev(FFTBITS, (dataidx-FFTSIZE-2)&FFTMASK))])) {
|
195 |
|
|
fprintf(stdout, "FAIL: BITREV.0 of k (%2x) = %2lx, not %2lx (expected %lx -> %lx)\n",
|
196 |
|
|
k, brev->o_out_0,
|
197 |
|
|
datastore[(((dataidx-2-FFTSIZE)&PAGEMSK)
|
198 |
|
|
+ bitrev(FFTBITS, (dataidx-FFTSIZE-2)&FFTMASK))],
|
199 |
|
|
(dataidx-2)&DATAMSK,
|
200 |
|
|
(((dataidx-2)&PAGEMSK)
|
201 |
|
|
+ bitrev(FFTBITS, (dataidx-FFTSIZE-2)&FFTMASK)));
|
202 |
|
|
// exit(-1);
|
203 |
|
|
}
|
204 |
|
|
|
205 |
|
|
if ((syncd)&&(brev->o_out_1 != datastore[(((dataidx-2-FFTSIZE)&PAGEMSK) + bitrev(FFTBITS, (dataidx-FFTSIZE-1)&FFTMASK))])) {
|
206 |
|
|
fprintf(stdout, "FAIL: BITREV.1 of k (%2x) = %2lx, not %2lx (expected %lx)\n",
|
207 |
|
|
k, brev->o_out_1,
|
208 |
|
|
datastore[(((dataidx-2-FFTSIZE)&PAGEMSK)
|
209 |
|
|
+ bitrev(FFTBITS, (dataidx-FFTSIZE-1)&FFTMASK))],
|
210 |
|
|
(((dataidx-1)&PAGEMSK)
|
211 |
|
|
+ bitrev(FFTBITS, (dataidx-FFTSIZE-1)&FFTMASK)));
|
212 |
|
|
// exit(-1);
|
213 |
|
|
}
|
214 |
|
|
#else
|
215 |
|
|
if ((syncd)&&(brev->o_out != datastore[
|
216 |
|
|
(((dataidx-1-FFTSIZE)&PAGEMSK)
|
217 |
|
|
+ bitrev(FFTBITS,
|
218 |
|
|
(dataidx-FFTSIZE-1)&FFTMASK))])) {
|
219 |
|
|
fprintf(stdout, "FAIL: BITREV.0 of k (%2x) = %2lx, not %2lx (expected %lx -> %lx)\n",
|
220 |
|
|
k, brev->o_out,
|
221 |
|
|
datastore[(((dataidx-1-FFTSIZE)&PAGEMSK)
|
222 |
|
|
+ bitrev(FFTBITS, (dataidx-FFTSIZE-1)&FFTMASK))],
|
223 |
|
|
(dataidx-2)&DATAMSK,
|
224 |
|
|
(((dataidx-2)&PAGEMSK)
|
225 |
|
|
+ bitrev(FFTBITS, (dataidx-FFTSIZE-1)&FFTMASK)));
|
226 |
|
|
exit(EXIT_FAILURE);
|
227 |
|
|
}
|
228 |
|
|
#endif
|
229 |
|
|
}
|
230 |
|
|
|
231 |
|
|
delete brev;
|
232 |
|
|
|
233 |
|
|
printf("SUCCESS!\n");
|
234 |
|
|
exit(0);
|
235 |
|
|
}
|