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

Subversion Repositories openhmc

[/] [openhmc/] [trunk/] [openHMC/] [rtl/] [hmc_controller/] [tx/] [tx_run_length_limiter.v] - Blame information for rev 15

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 11 juko
/*
2
 *                              .--------------. .----------------. .------------.
3
 *                             | .------------. | .--------------. | .----------. |
4
 *                             | | ____  ____ | | | ____    ____ | | |   ______ | |
5
 *                             | ||_   ||   _|| | ||_   \  /   _|| | | .' ___  || |
6
 *       ___  _ __   ___ _ __  | |  | |__| |  | | |  |   \/   |  | | |/ .'   \_|| |
7
 *      / _ \| '_ \ / _ \ '_ \ | |  |  __  |  | | |  | |\  /| |  | | || |       | |
8
 *       (_) | |_) |  __/ | | || | _| |  | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| |
9
 *      \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| |
10
 *           | |               | |            | | |              | | |          | |
11
 *           |_|               | '------------' | '--------------' | '----------' |
12
 *                              '--------------' '----------------' '------------'
13
 *
14
 *  openHMC - An Open Source Hybrid Memory Cube Controller
15
 *  (C) Copyright 2014 Computer Architecture Group - University of Heidelberg
16
 *  www.ziti.uni-heidelberg.de
17
 *  B6, 26
18
 *  68159 Mannheim
19
 *  Germany
20
 *
21
 *  Contact: openhmc@ziti.uni-heidelberg.de
22
 *  http://ra.ziti.uni-heidelberg.de/openhmc
23
 *
24
 *   This source file is free software: you can redistribute it and/or modify
25
 *   it under the terms of the GNU Lesser General Public License as published by
26
 *   the Free Software Foundation, either version 3 of the License, or
27
 *   (at your option) any later version.
28
 *
29
 *   This source file is distributed in the hope that it will be useful,
30
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
31
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
32
 *   GNU Lesser 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 source file.  If not, see <http://www.gnu.org/licenses/>.
36
 *
37
 *
38
 *  Module name: tx_run_length_limiter
39
 *
40
 *  Description:
41
 *  The idea is to break the counts up into manageable chunks.  FPGAs have 6-input LUTs, so a
42
 *  reasonable granularity is 5.  This means that we check 5 bits + the previous bit in every chunk.
43
 *
44
 *  Granularity 1 should be more accurate, but uses more resources.
45
 *
46
 *  When there are no bit flips in the input, count_top and count_bottom should be equal.
47
 *  Calculating them separately is faster and uses fewer resources.
48
 */
49
 
50
`default_nettype none
51
 
52
module tx_run_length_limiter #(
53
    parameter LANE_WIDTH  =64,
54
    parameter GRANULARITY =4,
55
    parameter RUN_LIMIT   =85
56
)
57
(
58
    input wire              clk,
59
    input wire              res_n,
60
    input wire              enable,
61
    input wire [LANE_WIDTH-1:0] data_in,
62
    output reg [LANE_WIDTH-1:0] data_out,
63
    output reg              rf_bit_flip
64
);
65
 
66
localparam NUM_CHUNKS   = (LANE_WIDTH + GRANULARITY-1)/(GRANULARITY);
67
localparam REM_BITS     = LANE_WIDTH - (GRANULARITY * (LANE_WIDTH/GRANULARITY));
68
localparam COUNT_BITS   = 8;
69
 
70
wire [NUM_CHUNKS-1:0] no_flip;
71
wire [NUM_CHUNKS-1:0] still_counting_top;
72
wire [NUM_CHUNKS-1:0] still_counting_bottom;
73
 
74
wire [COUNT_BITS-1:0] count_top;
75
wire [COUNT_BITS-1:0] count_top_part    [NUM_CHUNKS-1:0];
76
wire [COUNT_BITS-1:0] count_bottom;
77
wire [COUNT_BITS-1:0] count_bottom_part [NUM_CHUNKS-1:0];
78
 
79
wire bit_flip;
80
 
81
reg [COUNT_BITS-1:0] count_bottom_d1;
82
reg                  no_flip_bottom_d1;
83
reg                  data_in_bottom_d1;
84
 
85
genvar chunk;
86
genvar chunkT;
87
genvar chunkB;
88
generate
89
 
90
    assign no_flip[0] = &( {data_in[GRANULARITY-1:0],data_in_bottom_d1}) ||
91
                        &(~{data_in[GRANULARITY-1:0],data_in_bottom_d1});
92
 
93
    for(chunk=1; chunk<NUM_CHUNKS-1; chunk=chunk+1) begin : no_flip_gen
94
        assign no_flip[chunk]    =  &( data_in[(chunk+1)*(GRANULARITY)-1:chunk*(GRANULARITY)-1]) ||
95
                                    &(~data_in[(chunk+1)*(GRANULARITY)-1:chunk*(GRANULARITY)-1]);
96
    end
97
 
98
    assign no_flip[NUM_CHUNKS-1] =  &( data_in[LANE_WIDTH-1:(NUM_CHUNKS-1)*(GRANULARITY)-1]) ||
99
                                    &(~data_in[LANE_WIDTH-1:(NUM_CHUNKS-1)*(GRANULARITY)-1]);
100
 
101
 
102
    // Start at the top and count until a flip is found
103
    assign still_counting_top[0] = no_flip[0];
104
    assign count_top_part[0]     = (no_flip[0] ? GRANULARITY : 0);
105
 
106
    for(chunkT=1; chunkT<NUM_CHUNKS; chunkT=chunkT+1) begin : count_top_gen
107
        assign still_counting_top[chunkT]   = still_counting_top[chunkT-1] && no_flip[chunkT];
108
        assign count_top_part[chunkT]       = (still_counting_top[chunkT] ? GRANULARITY : 0) + count_top_part[chunkT-1];
109
    end
110
 
111
    assign count_top = (still_counting_top[NUM_CHUNKS-1] ? LANE_WIDTH :             // No flips found
112
                        count_top_part[NUM_CHUNKS-2]) +                     // Take the last value
113
                        (no_flip[0] ? (count_bottom_d1 == 0 ? 1 : count_bottom_d1) : 0); // Add the saved count
114
 
115
    // Start at the bottom and count until a flip is found
116
    assign still_counting_bottom[0] = no_flip[NUM_CHUNKS-1];
117
    assign count_bottom_part[0]     = 0;
118
 
119
    for(chunkB=1; chunkB<NUM_CHUNKS; chunkB=chunkB+1) begin : count_bottom_gen
120
        assign still_counting_bottom[chunkB] = still_counting_bottom[chunkB-1] && no_flip[NUM_CHUNKS-1-chunkB];
121
        assign count_bottom_part[chunkB]     = (still_counting_bottom[chunkB] ? GRANULARITY : 0) + count_bottom_part[chunkB-1];
122
    end
123
 
124
    assign count_bottom = still_counting_bottom[NUM_CHUNKS-1] ? LANE_WIDTH + (count_bottom_d1 == 0 ? 1 : count_bottom_d1) : // No flips found + saved count
125
                          count_bottom_part[NUM_CHUNKS-2] +                                     // Take the last value
126
                          (no_flip[NUM_CHUNKS-1] ? (REM_BITS ? REM_BITS : GRANULARITY) + 1 : 0);    // Add the remainder
127
 
128
endgenerate
129
 
130
assign bit_flip = count_top > (RUN_LIMIT - (GRANULARITY-1) - (REM_BITS ? REM_BITS-1 : GRANULARITY-1));
131
 
132
`ifdef ASYNC_RES
133
always @(posedge clk or negedge res_n)  begin `else
134
always @(posedge clk)  begin `endif
135 15 juko
 
136
    `ifdef RESET_ALL
137
        if(!res_n) begin
138
            data_out <= {DWIDTH {1'b0}};
139
        end else
140
    `endif
141
    begin
142
        if (enable && bit_flip) begin
143
            data_out    <= {data_in[LANE_WIDTH-1:1], ~data_in[0]};
144
        end else begin
145
            data_out    <= data_in;
146
        end
147
    end
148 11 juko
    if (!res_n) begin
149
        count_bottom_d1   <= { COUNT_BITS {1'b0}};
150
        no_flip_bottom_d1 <= 1'b0;
151
        data_in_bottom_d1 <= 1'b0;
152
        rf_bit_flip       <= 1'b0;
153
    end else begin
154
        count_bottom_d1   <= count_bottom;
155
        no_flip_bottom_d1 <= no_flip[NUM_CHUNKS-1];
156
        data_in_bottom_d1 <= data_in[LANE_WIDTH-1];
157
        if (enable && bit_flip) begin
158
            rf_bit_flip <= bit_flip;
159
        end
160
    end
161
end
162
 
163
endmodule

powered by: WebSVN 2.1.0

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