Entity: qtrstage
- File: qtrstage.v
Diagram
Description
//////////////////////////////////////////////////////////////////////////////
Filename: qtrstage.v
Project: A General Purpose Pipelined FFT Implementation
Purpose: This file encapsulates the 4 point stage of a decimation in frequency FFT. This particular implementation is optimized so that all of the multiplies are accomplished by additions and multiplexers only.
Operation: The operation of this stage is identical to the regular stages of the FFT (see them for details), with one additional and critical difference: this stage doesn't require any hardware multiplication. The multiplies within it may all be accomplished using additions and subtractions.
Let's see how this is done. Given x[n] and x[n+2], cause thats the stage we are working on, with i_sync true for x[0] being input, produce the output:
y[n ] = x[n] + x[n+2] y[n+2] = (x[n] - x[n+2]) * e^{-j2pi n/2} (forward transform) = (x[n] - x[n+2]) * -j^n
y[n].r = x[n].r + x[n+2].r (This is the easy part) y[n].i = x[n].i + x[n+2].i
y[2].r = x[0].r - x[2].r y[2].i = x[0].i - x[2].i
y[3].r = (x[1].i - x[3].i) (forward transform) y[3].i = - (x[1].r - x[3].r)
y[3].r = - (x[1].i - x[3].i) (inverse transform) y[3].i = (x[1].r - x[3].r) (INVERSE = 1) Creator: Dan Gisselquist, Ph.D. Gisselquist Technology, LLC
//////////////////////////////////////////////////////////////////////////////
Copyright (C) 2015-2019, Gisselquist Technology, LLC
This file is part of the general purpose pipelined FFT project.
The pipelined FFT project is free software (firmware): you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
The pipelined FFT project 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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser 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: LGPL, v3, as defined and found on www.gnu.org, http://www.gnu.org/licenses/lgpl.html
//////////////////////////////////////////////////////////////////////////////
`default_nettype none
Generics
| Generic name | Type | Value | Description |
|---|---|---|---|
| IWIDTH | 16 | ||
| LGWIDTH | 8 |
Ports
| Port name | Direction | Type | Description |
|---|---|---|---|
| i_clk | input | wire | |
| i_reset | input | wire | |
| i_ce | input | wire | |
| i_sync | input | wire | |
| i_data | input | wire [(2*IWIDTH-1):0] | |
| o_data | output | [(2*OWIDTH-1):0] | |
| o_sync | output |
Signals
| Name | Type | Description |
|---|---|---|
| wait_for_sync | reg | |
| pipeline | reg [2:0] | |
| sum_r | reg signed [(IWIDTH):0] | |
| sum_i | reg signed [(IWIDTH):0] | |
| diff_r | reg signed [(IWIDTH):0] | |
| diff_i | reg signed [(IWIDTH):0] | |
| ob_a | reg [(2*OWIDTH-1):0] | |
| ob_b | wire [(2*OWIDTH-1):0] | |
| ob_b_r | reg [(OWIDTH-1):0] | |
| ob_b_i | reg [(OWIDTH-1):0] | |
| iaddr | reg [(LGWIDTH-1):0] | |
| imem | reg [(2*IWIDTH-1):0] | |
| imem_r | wire [(IWIDTH-1):0] | |
| imem_i | wire [(IWIDTH-1):0] | |
| omem | reg [(2*OWIDTH-1):0] | |
| rnd_sum_r | wire [(OWIDTH-1):0] | Round our output values down to OWIDTH bits |
| rnd_sum_i | wire [(OWIDTH-1):0] | Round our output values down to OWIDTH bits |
| rnd_diff_r | wire [(OWIDTH-1):0] | Round our output values down to OWIDTH bits |
| rnd_diff_i | wire [(OWIDTH-1):0] | Round our output values down to OWIDTH bits |
| n_rnd_diff_r | wire [(OWIDTH-1):0] | Round our output values down to OWIDTH bits |
| n_rnd_diff_i | wire [(OWIDTH-1):0] | Round our output values down to OWIDTH bits |
| f_past_valid | reg | |
| f_piped_real | reg signed [IWIDTH-1:0] | |
| f_piped_imag | reg signed [IWIDTH-1:0] | |
| f_rsyncd | reg | |
| f_syncd | wire | |
| f_state | reg [1:0] | |
| f_i_real | wire [2*IWIDTH-1:0] | |
| f_i_imag | wire [2*IWIDTH-1:0] | |
| f_o_real | wire [OWIDTH-1:0] | |
| f_o_imag | wire [OWIDTH-1:0] |
Processes
- unnamed: ( @(posedge i_clk) )
Type: always
- unnamed: ( @(posedge i_clk) )
Type: always
- unnamed: ( @(posedge i_clk) )
Type: always
- unnamed: ( @(posedge i_clk) )
Type: always
Description
This is the pipeline[-1] stage, pipeline[0] will be set next.
- unnamed: ( @(posedge i_clk) )
Type: always
Description
pipeline[1] takes sum_x and diff_x and produces rnd_x Now for pipeline[2]. We can actually do this at all i_ce clock times, since nothing will listen unless pipeline[3] on the next clock. Thus, we simplify this logic and do it independent of pipeline[2].
- unnamed: ( @(posedge i_clk) )
Type: always
- unnamed: ( @(posedge i_clk) )
Type: always
- unnamed: ( @(posedge i_clk) )
Type: always
- unnamed: ( @(posedge i_clk) )
Type: always
- unnamed: ( @(posedge i_clk) )
Type: always
- unnamed: ( @(posedge i_clk) )
Type: always
- unnamed: ( @(posedge i_clk) )
Type: always
- unnamed: ( @(*) )
Type: always
- unnamed: ( @(posedge i_clk) )
Type: always
- unnamed: ( @(posedge i_clk) )
Type: always
- unnamed: ( @(posedge i_clk) )
Type: always
- unnamed: ( @(posedge i_clk) )
Type: always
- unnamed: ( @(posedge i_clk) )
Type: always
- unnamed: ( @(posedge i_clk) )
Type: always
- unnamed: ( @(*) )
Type: always
- unnamed: ( @(*) )
Type: always
- unnamed: ( @(posedge i_clk) )
Type: always
- unnamed: ( @(posedge i_clk) )
Type: always
Instantiations
- do_rnd_sum_r: convround
- do_rnd_sum_i: convround
- do_rnd_diff_r: convround
- do_rnd_diff_i: convround