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

Subversion Repositories dblclockfft

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

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

powered by: WebSVN 2.1.0

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