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

Subversion Repositories openhmc

[/] [openhmc/] [trunk/] [openHMC/] [rtl/] [building_blocks/] [fifos/] [async/] [openhmc_async_fifo.v] - Blame information for rev 11

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: openhmc_async_fifo
39
 *
40
 */
41
 
42
`default_nettype none
43
 
44
module openhmc_async_fifo #(
45
        parameter DWIDTH                        = 8,
46
        parameter ENTRIES                       = 2,
47
        parameter DISABLE_FULL_ASSERT           = 0,
48
        parameter DISABLE_EMPTY_ASSERT          = 0,
49
        parameter DISABLE_SHIFT_OUT_ASSERT      = 0,
50
        parameter DISABLE_SHIFT_IN_ASSERT       = 0,
51
        parameter DISABLE_SO_DATA_KNOWN_ASSERT  = 0
52
    ) (
53
        // interface for shift_in side
54
        input wire              si_clk,
55
        input wire              si_res_n,
56
        input wire              shift_in,
57
        input wire [DWIDTH-1:0] d_in,
58
 
59
        output reg              full,
60
        output reg              almost_full,
61
 
62
        // interface for shift_out side
63
        input wire              so_clk,
64
        input wire              so_res_n,
65
        input wire              shift_out,
66
 
67
        output reg [DWIDTH-1:0] d_out,
68
        output reg              empty,
69
        output reg              almost_empty
70
    );
71
 
72
//=====================================================================================================
73
//-----------------------------------------------------------------------------------------------------
74
//---------WIRING AND SIGNAL STUFF---------------------------------------------------------------------
75
//-----------------------------------------------------------------------------------------------------
76
//=====================================================================================================
77
 
78
// the FIFO currently can only have up to 2048 entries
79
    localparam LG_ENTRIES = (ENTRIES <= 2)    ?  1 :
80
                            (ENTRIES <= 4)    ?  2 :
81
                            (ENTRIES <= 8)    ?  3 :
82
                            (ENTRIES <= 16)   ?  4 :
83
                            (ENTRIES <= 32)   ?  5 :
84
                            (ENTRIES <= 64)   ?  6 :
85
                            (ENTRIES <= 128)  ?  7 :
86
                            (ENTRIES <= 256)  ?  8 :
87
                            (ENTRIES <= 512)  ?  9 :
88
                            (ENTRIES <= 1024) ? 10 : 11;
89
 
90
    reg [DWIDTH-1:0]            entry [0:ENTRIES-1];
91
 
92
    reg [LG_ENTRIES-1:0]    wp;
93
    reg [LG_ENTRIES-1:0]    rp;
94
 
95
    // asynchronous thermo wp
96
    reg [ENTRIES-1:0]       thermo_wp_w;
97
    reg [ENTRIES-1:0]       thermo_rp_w;
98
 
99
    reg [ENTRIES-1:0]       thermo_wp;
100
    reg [ENTRIES-1:0]       thermo_rp;
101
 
102
    reg [ENTRIES-1:0]       thermo_wp_synced_0;
103
 
104
    reg [ENTRIES-1:0]       thermo_wp_synced_1;
105
 
106
    reg [ENTRIES-1:0]       thermo_rp_synced_0;
107
 
108
    reg [ENTRIES-1:0]       thermo_rp_synced_1;
109
 
110
    wire [LG_ENTRIES-1:0]   next_rp;
111
    wire [LG_ENTRIES-1:0]   next_rp_p1;
112
 
113
    wire                    set_empty_w;
114
    wire                    set_a_empty_0_w;
115
    wire                    set_a_empty_1_w;
116
    wire                    set_a_empty_2_w;
117
 
118
    wire                    set_full_w;
119
    wire                    set_a_full_0_w;
120
    wire                    set_a_full_1_w;
121
    wire                    set_a_full_2_w;
122
 
123
    wire [LG_ENTRIES-1:0]   upper_bound;
124
 
125
    assign next_rp          = (rp == upper_bound) ? {LG_ENTRIES {1'b0}} : rp + 1'b1;
126
    assign next_rp_p1       = (next_rp == upper_bound) ? {LG_ENTRIES {1'b0}} : next_rp + 1'b1;
127
 
128
    assign set_empty_w      = (thermo_rp == thermo_wp_synced_1);
129
    assign set_a_empty_0_w  = (thermo_rp == {~thermo_wp_synced_1[0],   thermo_wp_synced_1[ENTRIES-1:1]});
130
    assign set_a_empty_1_w  = (thermo_rp == {~thermo_wp_synced_1[1:0], thermo_wp_synced_1[ENTRIES-1:2]});
131
    assign set_a_empty_2_w  = (thermo_rp == {~thermo_wp_synced_1[2:0], thermo_wp_synced_1[ENTRIES-1:3]});
132
 
133
    assign set_full_w       = &(thermo_wp ^ thermo_rp_synced_1);
134
    assign set_a_full_0_w   = &(thermo_wp ^ {~thermo_rp_synced_1[0],   thermo_rp_synced_1[ENTRIES-1:1]});
135
    assign set_a_full_1_w   = &(thermo_wp ^ {~thermo_rp_synced_1[1:0], thermo_rp_synced_1[ENTRIES-1:2]});
136
    assign set_a_full_2_w   = &(thermo_wp ^ {~thermo_rp_synced_1[2:0], thermo_rp_synced_1[ENTRIES-1:3]});
137
 
138
    assign upper_bound      = ENTRIES[LG_ENTRIES-1:0] - {{LG_ENTRIES-1 {1'b0}}, 1'b1};
139
 
140
    always @ (*)
141
    begin
142
        if (shift_in && !full)
143
            thermo_wp_w     = {thermo_wp[ENTRIES-2:0], !thermo_wp[ENTRIES-1]};
144
        else
145
            thermo_wp_w     = thermo_wp;
146
    end
147
 
148
    always @ (*)
149
    begin
150
        if (shift_out && !empty)
151
            thermo_rp_w     = {thermo_rp[ENTRIES-2:0], !thermo_rp[ENTRIES-1]};
152
        else
153
            thermo_rp_w     = thermo_rp;
154
    end
155
 
156
//=====================================================================================================
157
//-----------------------------------------------------------------------------------------------------
158
//---------LOGIC STARTS HERE---------------------------------------------------------------------------
159
//-----------------------------------------------------------------------------------------------------
160
//=====================================================================================================
161
 
162
    // shift_in side:
163
    `ifdef ASYNC_RES
164
    always @(posedge si_clk or negedge si_res_n) `else
165
    always @(posedge si_clk) `endif
166
    begin
167
        if (!si_res_n)
168
        begin
169
            wp                  <= {LG_ENTRIES {1'b0}};
170
            thermo_wp           <= {ENTRIES {1'b0}};
171
            full                <= 1'b0;
172
            almost_full         <= 1'b0;
173
        end
174
        else
175
        begin
176
            full                <= set_full_w || (set_a_full_0_w && shift_in) ;
177
            almost_full         <= set_full_w || (set_a_full_0_w) || (set_a_full_1_w && shift_in) ;
178
 
179
            thermo_wp           <= thermo_wp_w;
180
 
181
            if (shift_in && !full)
182
            begin
183
                entry[wp]       <= d_in;
184
 
185
                if (wp == upper_bound)
186
                    wp          <= {LG_ENTRIES {1'b0}};
187
                else
188
                    wp          <= wp + 1'b1;
189
            end
190
        end
191
    end
192
 
193
    // shift_out side
194
    `ifdef ASYNC_RES
195
    always @(posedge so_clk or negedge so_res_n) `else
196
    always @(posedge so_clk) `endif
197
    begin
198
        if (!so_res_n)
199
        begin
200
            rp                  <= {LG_ENTRIES {1'b0}};
201
            thermo_rp           <= {ENTRIES {1'b0}};
202
            empty               <= 1'b1;
203
            almost_empty        <= 1'b1;
204
 
205
        end
206
        else
207
        begin
208
            empty               <= (set_empty_w || (set_a_empty_0_w && shift_out && !empty));
209
            almost_empty        <= empty || set_empty_w || set_a_empty_0_w || (set_a_empty_1_w && shift_out && !empty);
210
 
211
            thermo_rp           <= thermo_rp_w;
212
            // shift out and not empty or empty but a new word just finished synchronizing (like almost empty)
213
            if (shift_out && !empty)
214
            begin
215
                rp              <= next_rp;
216
                d_out       <= entry[next_rp];
217
            end
218
            else
219
            begin
220
                d_out       <= entry[rp];
221
            end
222
        end
223
    end
224
 
225
    // syncing thermp_rp to shift_in domain
226
    `ifdef ASYNC_RES
227
    always @(posedge si_clk or negedge si_res_n) `else
228
    always @(posedge si_clk) `endif
229
    begin
230
        if (!si_res_n)
231
        begin
232
            thermo_rp_synced_0  <= {ENTRIES {1'b0}};
233
            thermo_rp_synced_1  <= {ENTRIES {1'b0}};
234
        end
235
        else
236
        begin
237
            thermo_rp_synced_0  <= thermo_rp;
238
            thermo_rp_synced_1  <= thermo_rp_synced_0;
239
        end
240
    end
241
 
242
    // syncing write pointer to shift_out domain
243
    `ifdef ASYNC_RES
244
    always @(posedge so_clk or negedge so_res_n) `else
245
    always @(posedge so_clk) `endif
246
    begin
247
        if (!so_res_n)
248
        begin
249
            thermo_wp_synced_0  <= {ENTRIES {1'b0}};
250
            thermo_wp_synced_1  <= {ENTRIES {1'b0}};
251
        end
252
        else
253
        begin
254
            thermo_wp_synced_0  <= thermo_wp;
255
            thermo_wp_synced_1  <= thermo_wp_synced_0;
256
        end
257
    end
258
 
259
 
260
`ifdef CAG_ASSERTIONS
261
    shift_in_and_full:      assert property (@(posedge si_clk) disable iff(!si_res_n) (shift_in |-> !full));
262
 
263
    if (DISABLE_SHIFT_OUT_ASSERT == 0)
264
        shift_out_and_empty:    assert property (@(posedge so_clk) disable iff(!so_res_n) (shift_out |-> !empty));
265
 
266
    if (DISABLE_SO_DATA_KNOWN_ASSERT == 0) begin
267
        dout_known:             assert property (@(posedge so_clk) disable iff(!so_res_n) (!empty |-> !$isunknown(d_out)));
268
    end
269
 
270
    final
271
    begin
272
        if (DISABLE_FULL_ASSERT == 0)
273
        begin
274
            full_set_assert:                assert (!full);
275
        end
276
 
277
        if (DISABLE_EMPTY_ASSERT == 0)
278
        begin
279
            almost_empty_not_set_assert:    assert (almost_empty);
280
            empty_not_set_assert:           assert (empty);
281
        end
282
    end
283
`endif // CAG_ASSERTIONS
284
 
285
endmodule
286
 
287
`default_nettype wire

powered by: WebSVN 2.1.0

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