Line 4... |
Line 4... |
//
|
//
|
// Project: A Doubletime Pipelined FFT
|
// Project: A Doubletime Pipelined FFT
|
//
|
//
|
// Purpose: This is the core generator for the project. Every part
|
// Purpose: This is the core generator for the project. Every part
|
// and piece of this project begins and ends in this program.
|
// and piece of this project begins and ends in this program.
|
// Once built, this program will build an FFT (or IFFT) core
|
// Once built, this program will build an FFT (or IFFT) core of arbitrary
|
// of arbitrary width, precision, etc., that will run at
|
// width, precision, etc., that will run at two samples per clock.
|
// two samples per clock. (Incidentally, I didn't pick two
|
// (Incidentally, I didn't pick two samples per clock because it was
|
// samples per clock because it was easier, but rather because
|
// easier, but rather because there weren't any two-sample per clock
|
// there weren't any two-sample per clock FFT's posted on
|
// FFT's posted on opencores.com. Further, FFT's running at one sample
|
// opencores.com. Further, FFT's running at one sample per
|
// per aren't that hard to find.)
|
// clock aren't that hard to find.)
|
|
//
|
//
|
// You can find the documentation for this program in two places.
|
// You can find the documentation for this program in two places. One is
|
// One is in the usage() function below. The second is in the
|
// in the usage() function below. The second is in the 'doc'uments
|
// 'doc'uments directory that comes with this package,
|
// directory that comes with this package, specifically in the spec.pdf
|
// specifically in the spec.pdf file. If it's not there, type
|
// file. If it's not there, type make in the documents directory to
|
// make in the documents directory to build it.
|
// build it.
|
//
|
//
|
// 20160123 - Thanks to Lesha Birukov, adjusted for MS Visual Studio 2012.
|
// 20160123 - Thanks to Lesha Birukov, adjusted for MS Visual Studio 2012.
|
// (Adjustments are at the top of the file ...)
|
// (Adjustments are at the top of the file ...)
|
//
|
//
|
// Creator: Dan Gisselquist, Ph.D.
|
// Creator: Dan Gisselquist, Ph.D.
|
// Gisselquist Technology, LLC
|
// Gisselquist Technology, LLC
|
//
|
//
|
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
//
|
//
|
// Copyright (C) 2015-2016, Gisselquist Technology, LLC
|
// Copyright (C) 2015-2017, Gisselquist Technology, LLC
|
//
|
//
|
// This program is free software (firmware): you can redistribute it and/or
|
// 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
|
// 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
|
// by the Free Software Foundation, either version 3 of the License, or (at
|
// your option) any later version.
|
// your option) any later version.
|
Line 141... |
Line 140... |
} ROUND_T;
|
} ROUND_T;
|
|
|
const char cpyleft[] =
|
const char cpyleft[] =
|
"////////////////////////////////////////////////////////////////////////////////\n"
|
"////////////////////////////////////////////////////////////////////////////////\n"
|
"//\n"
|
"//\n"
|
"// Copyright (C) 2015-2016, Gisselquist Technology, LLC\n"
|
"// Copyright (C) 2015-2017, Gisselquist Technology, LLC\n"
|
"//\n"
|
"//\n"
|
"// This program is free software (firmware): you can redistribute it and/or\n"
|
"// This program is free software (firmware): you can redistribute it and/or\n"
|
"// modify it under the terms of the GNU General Public License as published\n"
|
"// modify it under the terms of the GNU General Public License as published\n"
|
"// by the Free Software Foundation, either version 3 of the License, or (at\n"
|
"// by the Free Software Foundation, either version 3 of the License, or (at\n"
|
"// your option) any later version.\n"
|
"// your option) any later version.\n"
|
Line 366... |
Line 365... |
"//\n",
|
"//\n",
|
prjname, creator);
|
prjname, creator);
|
|
|
fprintf(fp, "%s", cpyleft);
|
fprintf(fp, "%s", cpyleft);
|
fprintf(fp,
|
fprintf(fp,
|
"module convround(i_clk, i_ce, i_val, o_val);\n"
|
"module roundfromzero(i_clk, i_ce, i_val, o_val);\n"
|
"\tparameter\tIWID=16, OWID=8, SHIFT=0;\n"
|
"\tparameter\tIWID=16, OWID=8, SHIFT=0;\n"
|
"\tinput\t\t\t\t\ti_clk, i_ce;\n"
|
"\tinput\t\t\t\t\ti_clk, i_ce;\n"
|
"\tinput\t\tsigned\t[(IWID-1):0]\ti_val;\n"
|
"\tinput\t\tsigned\t[(IWID-1):0]\ti_val;\n"
|
"\toutput\treg\tsigned\t[(OWID-1):0]\to_val;\n"
|
"\toutput\treg\tsigned\t[(OWID-1):0]\to_val;\n"
|
"\n"
|
"\n"
|
Line 466... |
Line 465... |
"//\n"
|
"//\n"
|
"// Purpose: A convergent rounding routine, also known as banker\'s\n"
|
"// Purpose: A convergent rounding routine, also known as banker\'s\n"
|
"// rounding, Dutch rounding, Gaussian rounding, unbiased\n"
|
"// rounding, Dutch rounding, Gaussian rounding, unbiased\n"
|
"// rounding, or ... more, at least according to Wikipedia.\n"
|
"// rounding, or ... more, at least according to Wikipedia.\n"
|
"//\n"
|
"//\n"
|
"// This form of rounding works by rounding, when the direction\n"
|
"// This form of rounding works by rounding, when the direction is in\n"
|
"// is in question, towards the nearest even value.\n"
|
"// question, towards the nearest even value.\n"
|
"//\n"
|
"//\n"
|
"//\n%s"
|
"//\n%s"
|
"//\n",
|
"//\n",
|
prjname, creator);
|
prjname, creator);
|
|
|
Line 493... |
Line 492... |
"\t//\t3. Two or more bits would be dropped. In this case, we round\n"
|
"\t//\t3. Two or more bits would be dropped. In this case, we round\n"
|
"\t//\t\tnormally unless we are rounding a value of exactly\n"
|
"\t//\t\tnormally unless we are rounding a value of exactly\n"
|
"\t//\t\thalfway between the two. In the halfway case we round\n"
|
"\t//\t\thalfway between the two. In the halfway case we round\n"
|
"\t//\t\tto the nearest even number.\n"
|
"\t//\t\tto the nearest even number.\n"
|
"\tgenerate\n"
|
"\tgenerate\n"
|
|
// What if IWID < OWID? We should expand here ... somehow
|
"\tif (IWID == OWID) // In this case, the shift is irrelevant and\n"
|
"\tif (IWID == OWID) // In this case, the shift is irrelevant and\n"
|
"\tbegin // cannot be applied. No truncation or rounding takes\n"
|
"\tbegin // cannot be applied. No truncation or rounding takes\n"
|
"\t// effect here.\n"
|
"\t// effect here.\n"
|
"\n"
|
"\n"
|
"\t\talways @(posedge i_clk)\n"
|
"\t\talways @(posedge i_clk)\n"
|
"\t\t\tif (i_ce)\to_val <= i_val[(IWID-1):0];\n"
|
"\t\t\tif (i_ce)\to_val <= i_val[(IWID-1):0];\n"
|
"\n"
|
"\n"
|
|
// What if IWID-SHIFT < OWID? Shouldn't we also shift here as well?
|
"\tend else if (IWID-SHIFT == OWID)\n"
|
"\tend else if (IWID-SHIFT == OWID)\n"
|
"\tbegin // No truncation or rounding, output drops no bits\n"
|
"\tbegin // No truncation or rounding, output drops no bits\n"
|
"\n"
|
"\n"
|
"\t\talways @(posedge i_clk)\n"
|
"\t\talways @(posedge i_clk)\n"
|
"\t\t\tif (i_ce)\to_val <= i_val[(IWID-SHIFT-1):0];\n"
|
"\t\t\tif (i_ce)\to_val <= i_val[(IWID-SHIFT-1):0];\n"
|
"\n"
|
"\n"
|
"\tend else if (IWID-SHIFT-1 == OWID)\n"
|
"\tend else if (IWID-SHIFT-1 == OWID)\n"
|
|
// Is there any way to limit the number of bits that are examined here, for the
|
|
// purpose of simplifying/reducing logic? I mean, if we go from 32 to 16 bits,
|
|
// must we check all 15 bits for equality to zero?
|
"\tbegin // Output drops one bit, can only add one or ... not.\n"
|
"\tbegin // Output drops one bit, can only add one or ... not.\n"
|
"\t\twire\t[(OWID-1):0] truncated_value, rounded_up;\n"
|
"\t\twire\t[(OWID-1):0] truncated_value, rounded_up;\n"
|
"\t\twire\t\t\tlast_valid_bit, first_lost_bit;\n"
|
"\t\twire\t\t\tlast_valid_bit, first_lost_bit;\n"
|
"\t\tassign\ttruncated_value=i_val[(IWID-1-SHIFT):(IWID-SHIFT-OWID)];\n"
|
"\t\tassign\ttruncated_value=i_val[(IWID-1-SHIFT):(IWID-SHIFT-OWID)];\n"
|
"\t\tassign\trounded_up=truncated_value + {{(OWID-1){1\'b0}}, 1\'b1 };\n"
|
"\t\tassign\trounded_up=truncated_value + {{(OWID-1){1\'b0}}, 1\'b1 };\n"
|