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

Subversion Repositories dblclockfft

[/] [dblclockfft/] [trunk/] [rtl/] [convround.v] - Blame information for rev 39

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 36 dgisselq
////////////////////////////////////////////////////////////////////////////////
2
//
3
// Filename:    convround.v
4
//
5
// Project:     A General Purpose Pipelined FFT Implementation
6
//
7
// Purpose:     A convergent rounding routine, also known as banker's
8
//              rounding, Dutch rounding, Gaussian rounding, unbiased
9
//      rounding, or ... more, at least according to Wikipedia.
10
//
11
//      This form of rounding works by rounding, when the direction is in
12
//      question, towards the nearest even value.
13
//
14
//
15
// Creator:     Dan Gisselquist, Ph.D.
16
//              Gisselquist Technology, LLC
17
//
18
////////////////////////////////////////////////////////////////////////////////
19
//
20
// Copyright (C) 2015-2018, Gisselquist Technology, LLC
21
//
22 39 dgisselq
// This file is part of the general purpose pipelined FFT project.
23 36 dgisselq
//
24 39 dgisselq
// The pipelined FFT project is free software (firmware): you can redistribute
25
// it and/or modify it under the terms of the GNU Lesser General Public License
26
// as published by the Free Software Foundation, either version 3 of the
27
// License, or (at your option) any later version.
28 36 dgisselq
//
29 39 dgisselq
// The pipelined FFT project is distributed in the hope that it will be useful,
30
// but WITHOUT ANY WARRANTY; without even the implied warranty of
31
// MERCHANTIBILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser
32
// General Public License for more details.
33
//
34
// You should have received a copy of the GNU Lesser General Public License
35
// along with this program.  (It's in the $(ROOT)/doc directory.  Run make
36
// with no target there if the PDF file isn't present.)  If not, see
37 36 dgisselq
// <http://www.gnu.org/licenses/> for a copy.
38
//
39 39 dgisselq
// License:     LGPL, v3, as defined and found on www.gnu.org,
40
//              http://www.gnu.org/licenses/lgpl.html
41 36 dgisselq
//
42
//
43
////////////////////////////////////////////////////////////////////////////////
44
//
45
//
46
`default_nettype        none
47
//
48
module  convround(i_clk, i_ce, i_val, o_val);
49
        parameter       IWID=16, OWID=8, SHIFT=0;
50 39 dgisselq
        input   wire                            i_clk, i_ce;
51
        input   wire    signed  [(IWID-1):0]     i_val;
52 36 dgisselq
        output  reg     signed  [(OWID-1):0]     o_val;
53
 
54
        // Let's deal with three cases to be as general as we can be here
55
        //
56
        //      1. The desired output would lose no bits at all
57
        //      2. One bit would be dropped, so the rounding is simply
58
        //              adjusting the value to be the nearest even number in
59
        //              cases of being halfway between two.  If identically
60
        //              equal to a number, we just leave it as is.
61
        //      3. Two or more bits would be dropped.  In this case, we round
62
        //              normally unless we are rounding a value of exactly
63
        //              halfway between the two.  In the halfway case we round
64
        //              to the nearest even number.
65
        generate
66
        if (IWID == OWID) // In this case, the shift is irrelevant and
67
        begin // cannot be applied.  No truncation or rounding takes
68
        // effect here.
69
 
70
                always @(posedge i_clk)
71
                        if (i_ce)       o_val <= i_val[(IWID-1):0];
72
 
73
        end else if (IWID-SHIFT == OWID)
74
        begin // No truncation or rounding, output drops no bits
75
 
76
                always @(posedge i_clk)
77
                        if (i_ce)       o_val <= i_val[(IWID-SHIFT-1):0];
78
 
79
        end else if (IWID-SHIFT-1 == OWID)
80
        begin // Output drops one bit, can only add one or ... not.
81
                wire    [(OWID-1):0]     truncated_value, rounded_up;
82
                wire                    last_valid_bit, first_lost_bit;
83
                assign  truncated_value=i_val[(IWID-1-SHIFT):(IWID-SHIFT-OWID)];
84
                assign  rounded_up=truncated_value + {{(OWID-1){1'b0}}, 1'b1 };
85
                assign  last_valid_bit = truncated_value[0];
86
                assign  first_lost_bit = i_val[0];
87
 
88
                always @(posedge i_clk)
89
                        if (i_ce)
90
                        begin
91
                                if (!first_lost_bit) // Round down / truncate
92
                                        o_val <= truncated_value;
93
                                else if (last_valid_bit)// Round up to nearest
94
                                        o_val <= rounded_up; // even value
95
                                else // else round down to the nearest
96
                                        o_val <= truncated_value; // even value
97
                        end
98
 
99
        end else // If there's more than one bit we are dropping
100
        begin
101
                wire    [(OWID-1):0]     truncated_value, rounded_up;
102
                wire                    last_valid_bit, first_lost_bit;
103
                assign  truncated_value=i_val[(IWID-1-SHIFT):(IWID-SHIFT-OWID)];
104
                assign  rounded_up=truncated_value + {{(OWID-1){1'b0}}, 1'b1 };
105
                assign  last_valid_bit = truncated_value[0];
106
                assign  first_lost_bit = i_val[(IWID-SHIFT-OWID-1)];
107
 
108
                wire    [(IWID-SHIFT-OWID-2):0]  other_lost_bits;
109
                assign  other_lost_bits = i_val[(IWID-SHIFT-OWID-2):0];
110
 
111
                always @(posedge i_clk)
112
                        if (i_ce)
113
                        begin
114
                                if (!first_lost_bit) // Round down / truncate
115
                                        o_val <= truncated_value;
116
                                else if (|other_lost_bits) // Round up to
117
                                        o_val <= rounded_up; // closest value
118
                                else if (last_valid_bit) // Round up to
119
                                        o_val <= rounded_up; // nearest even
120
                                else    // else round down to nearest even
121
                                        o_val <= truncated_value;
122
                        end
123
        end
124
        endgenerate
125
 
126
endmodule

powered by: WebSVN 2.1.0

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