OpenCores
URL https://opencores.org/ocsvn/dblclockfft/dblclockfft/trunk

Subversion Repositories dblclockfft

[/] [dblclockfft/] [trunk/] [bench/] [cpp/] [fft_tb.cpp] - Rev 7

Go to most recent revision | Compare with Previous | Blame | View Log

////////////////////////////////////////////////////////////////////////////
//
// Filename: 	butterfly_tb.cpp
//
// Project:	A Doubletime Pipelined FFT
//
// Purpose:	A test-bench for the butterfly.v subfile of the double
//		clocked FFT.  This file may be run autonomously.  If so,
//		the last line output will either read "SUCCESS" on success,
//		or some other failure message otherwise.
//
//		This file depends upon verilator to both compile, run, and
//		therefore test butterfly.v
//
// Creator:	Dan Gisselquist, Ph.D.
//		Gisselquist Tecnology, LLC
//
///////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2015, Gisselquist Technology, LLC
//
// This program is free software (firmware): you can redistribute it and/or
// modify it under the terms of  the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or (at
// your option) any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program.  (It's in the $(ROOT)/doc directory, run make with no
// target there if the PDF file isn't present.)  If not, see
// <http://www.gnu.org/licenses/> for a copy.
//
// License:	GPL, v3, as defined and found on www.gnu.org,
//		http://www.gnu.org/licenses/gpl.html
//
//
///////////////////////////////////////////////////////////////////////////
#include <stdio.h>
 
#include "verilated.h"
#include "Vfftmain.h"
 
#define	LGWIDTH	11
#define	IWIDTH	16
#define	OWIDTH	22
 
#define	FFTLEN	(1<<LGWIDTH)
 
class	FFT_TB {
public:
	Vfftmain	*m_fft;
	long		m_data[FFTLEN];
	int		m_addr;
	FILE		*m_dumpfp;
 
	FFT_TB(void) {
		m_fft = new Vfftmain;
		m_addr = 0;
		m_dumpfp = NULL;
	}
 
	void	tick(void) {
		m_fft->i_clk = 0;
		m_fft->eval();
		m_fft->i_clk = 1;
		m_fft->eval();
	}
 
	void	reset(void) {
		m_fft->i_ce  = 0;
		m_fft->i_rst = 1;
		tick();
		m_fft->i_rst = 0;
		tick();
	}
 
 
	bool	test(int lft, int rht) {
		m_fft->i_ce    = 1;
		m_fft->i_rst   = 0;
		m_fft->i_left  = lft;
		m_fft->i_right = rht;
 
		tick();
 
		if (m_fft->o_sync) {
			m_addr = 0;
		} else m_addr += 2;
 
		printf("%5d: %08x,%08x -> %09lx,%09lx\t%s%s%s%s%s%s%s%s%s%s %s\n",
			m_addr,
			lft, rht, m_fft->o_left, m_fft->o_right,
			(m_fft->v__DOT__w_s2048)?"S":"-",
			(m_fft->v__DOT__w_s1024)?"S":"-",
			(m_fft->v__DOT__w_s512)?"S":"-",
			(m_fft->v__DOT__w_s256)?"S":"-",
			(m_fft->v__DOT__w_s128)?"S":"-",
			(m_fft->v__DOT__w_s64)?"S":"-",
			(m_fft->v__DOT__w_s32)?"S":"-",
			(m_fft->v__DOT__w_s16)?"S":"-", // This works
			(m_fft->v__DOT__w_s8)?"S":"-",
			(m_fft->v__DOT__w_s4)?"S":"-", // This doesn.t
			(m_fft->o_sync)?"\t(SYNC!)":"");
 
		m_data[(m_addr  )&(FFTLEN-1)] = m_fft->o_left;
		m_data[(m_addr+1)&(FFTLEN-1)] = m_fft->o_right;
 
		if (m_addr == FFTLEN-2)
			dumpwrite();
 
		return (m_fft->o_sync);
	}
 
	bool	test(double lft_r, double lft_i, double rht_r, double rht_i) {
		int	ilft, irht, ilft_r, ilft_i, irht_r, irht_i;
 
		ilft_r = (int)(lft_r + 0.5) & ((1<<IWIDTH)-1);
		ilft_i = (int)(lft_i + 0.5) & ((1<<IWIDTH)-1);
		irht_r = (int)(rht_r + 0.5) & ((1<<IWIDTH)-1);
		irht_i = (int)(rht_i + 0.5) & ((1<<IWIDTH)-1);
 
		ilft = (ilft_r << IWIDTH) | ilft_i;
		irht = (irht_r << IWIDTH) | irht_i;
 
		return test(ilft, irht);
	}
 
	double	rdata(int addr) {
		long	ivl = m_data[addr & (FFTLEN-1)];
 
		ivl = ivl >> 17;
		ivl &= ((1<<OWIDTH)-1);
		if (1 & (ivl>>(OWIDTH-1)))
			ivl |= (-1l << OWIDTH);
		return (double)ivl;
	}
 
	double	idata(int addr) {
		long	ivl = m_data[addr & (FFTLEN-1)];
 
		ivl = ivl;
		ivl &= ((1<<OWIDTH)-1);
		if (1 & (ivl>>(OWIDTH-1)))
			ivl |= (-1l << OWIDTH);
		return (double)ivl;
	}
 
	void	dump(FILE *fp) {
		m_dumpfp = fp;
	}
 
	void	dumpwrite(void) {
		if (!m_dumpfp)
			return;
 
		double	*buf;
 
		buf = new double[FFTLEN * 2];
		for(int i=0; i<FFTLEN; i++) {
			buf[i*2] = rdata(i);
			buf[i*2+1] = idata(i);
		}
 
		fwrite(buf, sizeof(double), FFTLEN*2, m_dumpfp);
		delete[] buf;
	}
};
 
int	main(int argc, char **argv, char **envp) {
	Verilated::commandArgs(argc, argv);
	FFT_TB *fft = new FFT_TB;
	FILE	*fpout;
 
	fpout = fopen("fft_tb.dbl", "w");
	if (NULL == fpout) {
		fprintf(stderr, "Cannot write output file, fft_tb.dbl\n");
		exit(-1);
	}
 
	fft->reset();
	fft->dump(fpout);
 
	// Let's start by just testing our limits ...
	// First, the smallest real number
	for(int k=0; k<FFTLEN/2; k++)
		fft->test(1.0,0.0,1.0,0.0);
	// Then the smallest imaginary number
	for(int k=0; k<FFTLEN/2; k++)
		fft->test(0.0,1.0,0.0,1.0);
	// First, the smallest real number
	for(int k=0; k<FFTLEN/2; k++)
		fft->test(-1.0,0.0,-1.0,0.0);
	// Then the smallest imaginary number
	for(int k=0; k<FFTLEN/2; k++)
		fft->test(0.0,-1.0,0.0,-1.0);
	// Now, how about the smallest alternating real signal
	for(int k=0; k<FFTLEN/2; k++)
		fft->test(1.0,0.0,0.0,0.0); // Don't forget to expect a bias!
	// Now, how about the smallest alternating imaginary signal
	for(int k=0; k<FFTLEN/2; k++)
		fft->test(0.0,1.0,0.0,0.0); // Don't forget to expect a bias!
	// Now, how about the smallest alternating real signal,2nd phase
	for(int k=0; k<FFTLEN/2; k++)
		fft->test(0.0,0.0,1.0,0.0); // Don't forget to expect a bias!
	// Now, how about the smallest alternating imaginary signal,2nd phase
	for(int k=0; k<FFTLEN/2; k++)
		fft->test(0.0,0.0,0.0,1.0); // Don't forget to expect a bias!
 
	// Now let's go for the largest value
	for(int k=0; k<FFTLEN/2; k++)
		fft->test(-32768.0,-32768.0,-32768.0,-32768.0);
 
	// And finally, let's clear out our results / buffer
	for(int k=0; k<(FFTLEN/2) * 3; k++)
		fft->test(0.0,0.0,0.0,0.0);
 
	// Now let's try some exponentials
	// for(int k=0; k<FFTLEN/2; k++)
		// fft->test(-32768.0,-32768.0,-32768.0,-32768.0);
 
 
 
	fclose(fpout);
}
 
// 564, 874, 1058, 1178, 1300, 1422, 1546, 1666, 1788, 1798 --> SYNC @ 3852
// 2612, 2922, 3106, 3226, 3348, 3470, 3594, 3714, 3836, 3846
// 808, 1118, 1302, 1422, 1544, 1666, 1790, 1910, 2032, 2042 --> SYNC @ 2848
// 8756 .. ??
 

Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.