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

Subversion Repositories warp

[/] [warp/] [rtl/] [tmu_pixin.v] - Blame information for rev 7

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 7 lekernel
/*
2
 * Milkymist VJ SoC
3
 * Copyright (C) 2007, 2008, 2009 Sebastien Bourdeauducq
4
 *
5
 * This program is free and excepted software; you can use it, redistribute it
6
 * and/or modify it under the terms of the Exception General Public License as
7
 * published by the Exception License Foundation; either version 2 of the
8
 * License, or (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful, but WITHOUT
11
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12
 * FOR A PARTICULAR PURPOSE. See the Exception General Public License for more
13
 * details.
14
 *
15
 * You should have received a copy of the Exception General Public License along
16
 * with this project; if not, write to the Exception License Foundation.
17
 */
18
 
19
module tmu_pixin #(
20
        parameter fml_depth = 26,
21
        parameter cache_depth = 12
22
) (
23
        input sys_clk,
24
        input sys_rst,
25
 
26
        output reg [fml_depth-1:0] fml_adr,
27
        output reg fml_stb,
28
        input fml_ack,
29
        input [63:0] fml_di,
30
 
31
        input flush,
32
        output reg busy,
33
 
34
        input pipe_stb_i,
35
        output reg pipe_ack_o,
36
        input [fml_depth-1-1:0] src_addr, /* in 16-bit words */
37
        input [fml_depth-1-1:0] dst_addr, /* in 16-bit words, pass-through */
38
 
39
        output reg pipe_stb_o,
40
        input pipe_ack_i,
41
        output reg [15:0] src_pixel,
42
        output reg [fml_depth-1-1:0] dst_addr1, /* in 16-bit words */
43
 
44
        output reg inc_misses
45
);
46
 
47
/* Work on 8-bit addresses to reduce the probability of
48
 * spending hours fixing typos in indices.
49
 * The synthesizer should optimize the trailing 0 away.
50
 */
51
wire [fml_depth-1:0] src_addr8 = {src_addr, 1'b0};
52
 
53
reg memorize_src_address;
54
reg [fml_depth-1:0] src_addr8_r;
55
always @(posedge sys_clk) begin
56
        if(memorize_src_address)
57
                src_addr8_r = src_addr8;
58
end
59
 
60
/*
61
 * Line length is the burst length, that is 4*64 bits, or 32 bytes
62
 * Address split up :
63
 *
64
 * |             TAG            |         INDEX          |   OFFSET   |
65
 * |fml_depth-1      cache_depth|cache_depth-1          5|4          0|
66
 *
67
 */
68
 
69
wire [4:0] offset = src_addr8[4:0];
70
wire [cache_depth-1-5:0] index = src_addr8[cache_depth-1:5];
71
wire [fml_depth-cache_depth-1:0] tag = src_addr8[fml_depth-1:cache_depth];
72
 
73
wire [4:0] offset_r = src_addr8_r[4:0];
74
wire [cache_depth-1-5:0] index_r = src_addr8_r[cache_depth-1:5];
75
wire [fml_depth-cache_depth-1:0] tag_r = src_addr8_r[fml_depth-1:cache_depth];
76
 
77
/* When we access FML, it's always because of a cache miss, and
78
 * therefore using the memorized address. Connect the address lines
79
 * straight to the output of the register to improve timing.
80
 * And add another register since that was not enough.
81
 */
82
always @(posedge sys_clk)
83
        fml_adr <= {tag_r, index_r, 5'd0};
84
 
85
/* Use the memorized address as the index for the tag and data memories */
86
reg use_memorized;
87
 
88
/*
89
 * TAG MEMORY
90
 *
91
 * Addressed by index (length cache_depth-5)
92
 * Contains valid bit + tag
93
 */
94
 
95
wire [cache_depth-1-5:0] tagmem_a;
96
reg tagmem_we;
97
wire [fml_depth-cache_depth-1+1:0] tagmem_di;
98
reg [fml_depth-cache_depth-1+1:0] tagmem_do;
99
 
100
reg [fml_depth-cache_depth-1+1:0] tags[0:(1 << (cache_depth-5))-1];
101
 
102
always @(posedge sys_clk) begin
103
        if(tagmem_we)
104
                tags[tagmem_a] <= tagmem_di;
105
        tagmem_do <= tags[tagmem_a];
106
end
107
 
108
reg flushmode;
109
reg flush_a_reset;
110
 
111
reg [cache_depth-1-5:0] flush_a;
112
always @(posedge sys_clk) begin
113
        if(flush_a_reset)
114
                flush_a <= {cache_depth-5{1'b0}};
115
        else
116
                flush_a <= flush_a + {{cache_depth-5-1{1'b0}}, 1'b1};
117
end
118
 
119
wire flush_last = (flush_a == {cache_depth-5{1'b1}});
120
 
121
assign tagmem_a = flushmode ? flush_a : (use_memorized ? index_r : index);
122
 
123
wire di_valid;
124
/* we always write tags from addresses missing the cache,
125
 * therefore with the memorized address.
126
 */
127
assign tagmem_di = {di_valid, tag_r};
128
 
129
assign di_valid = ~flushmode;
130
 
131
wire do_valid;
132
wire [fml_depth-cache_depth-1:0] do_tag;
133
assign do_valid = tagmem_do[fml_depth-cache_depth-1+1];
134
assign do_tag = tagmem_do[fml_depth-cache_depth-1:0];
135
 
136
/*
137
 * DATA MEMORY
138
 *
139
 * Addressed by index+offset in 64-bit words (length cache_depth-3)
140
 */
141
wire [cache_depth-3-1:0] datamem_a;
142
reg datamem_we;
143
wire [63:0] datamem_di;
144
reg [63:0] datamem_do;
145
 
146
reg [63:0] data[0:(1 << (cache_depth-3))-1];
147
 
148
always @(posedge sys_clk) begin
149
        if(datamem_we)
150
                data[datamem_a] <= datamem_di;
151
        datamem_do <= data[datamem_a];
152
end
153
 
154
assign datamem_di = fml_di;
155
always @(*) begin
156
        case(offset_r[2:1])
157
                2'd0: src_pixel = datamem_do[63:48];
158
                2'd1: src_pixel = datamem_do[47:32];
159
                2'd2: src_pixel = datamem_do[31:16];
160
                2'd3: src_pixel = datamem_do[15:0];
161
        endcase
162
end
163
 
164
reg bcounter_reset;
165
reg [1:0] bcounter;
166
always @(posedge sys_clk) begin
167
        if(bcounter_reset)
168
                bcounter <= 2'd0;
169
        else
170
                bcounter <= bcounter + 2'd1;
171
end
172
 
173
reg datamem_aswitch;
174
assign datamem_a = {
175
        (use_memorized ? index_r : index),
176
        datamem_aswitch ? bcounter : (use_memorized ? offset_r[4:3] : offset[4:3])
177
        };
178
 
179
/* FSM */
180
 
181
wire cache_hit = do_valid & (do_tag == tag_r);
182
 
183
reg [3:0] state;
184
reg [3:0] next_state;
185
 
186
parameter IDLE                  = 4'd0;
187
parameter RUNNING               = 4'd1;
188
parameter WAIT_DOWNSTREAM       = 4'd2;
189
parameter CACHEMISS             = 4'd3;
190
parameter BURST2                = 4'd4;
191
parameter BURST3                = 4'd5;
192
parameter BURST4                = 4'd6;
193
parameter READOFFSET            = 4'd7;
194
parameter FLUSH                 = 4'd8;
195
 
196
always @(posedge sys_clk) begin
197
        if(sys_rst)
198
                state <= IDLE;
199
        else begin
200
                state <= next_state;
201
        end
202
end
203
 
204
always @(*) begin
205
        next_state = state;
206
 
207
        memorize_src_address = 1'b0;
208
        use_memorized = 1'b0;
209
 
210
        tagmem_we = 1'b0;
211
        datamem_we = 1'b0;
212
        flush_a_reset = 1'b0;
213
        flushmode = 1'b0;
214
        bcounter_reset = 1'b1;
215
        datamem_aswitch = 1'b0;
216
 
217
        busy = 1'b1;
218
        pipe_ack_o = 1'b0;
219
        pipe_stb_o = 1'b0;
220
 
221
        fml_stb = 1'b0;
222
 
223
        inc_misses = 1'b0;
224
 
225
        case(state)
226
                IDLE: begin
227
                        memorize_src_address = 1'b1;
228
                        busy = 1'b0;
229
                        if(flush) begin
230
                                flush_a_reset = 1'b1;
231
                                next_state = FLUSH;
232
                        end else begin
233
                                pipe_ack_o = 1'b1;
234
                                if(pipe_stb_i)
235
                                        next_state = RUNNING;
236
                        end
237
                end
238
                RUNNING: begin
239
                        if(cache_hit) begin
240
                                pipe_stb_o = 1'b1;
241
                                pipe_ack_o = 1'b1;
242
                                memorize_src_address = 1'b1;
243
 
244
                                if(~pipe_ack_i) begin
245
                                        pipe_ack_o = 1'b0;
246
                                        memorize_src_address = 1'b0;
247
                                        use_memorized = 1'b1;
248
                                        next_state = WAIT_DOWNSTREAM;
249
                                end else if(pipe_stb_i)
250
                                        next_state = RUNNING;
251
                                else
252
                                        next_state = IDLE;
253
                        end else begin
254
                                memorize_src_address = 1'b0;
255
                                next_state = CACHEMISS;
256
                        end
257
                end
258
                WAIT_DOWNSTREAM: begin
259
                        pipe_stb_o = 1'b1;
260
                        if(pipe_ack_i) begin
261
                                memorize_src_address = 1'b1;
262
                                use_memorized = 1'b0;
263
 
264
                                pipe_ack_o = 1'b1;
265
                                if(pipe_stb_i) begin
266
                                        next_state = RUNNING;
267
                                end else
268
                                        next_state = IDLE;
269
                        end else begin
270
                                memorize_src_address = 1'b0;
271
                                use_memorized = 1'b1;
272
                        end
273
                end
274
                CACHEMISS: begin
275
                        memorize_src_address = 1'b0;
276
                        use_memorized = 1'b1;
277
                        fml_stb = 1'b1;
278
                        tagmem_we = 1'b1;
279
                        datamem_aswitch = 1'b1;
280
                        datamem_we = 1'b1;
281
                        if(fml_ack) begin
282
                                bcounter_reset = 1'b0;
283
                                next_state = BURST2;
284
                        end
285
                end
286
                BURST2: begin
287
                        inc_misses = 1'b1;
288
                        memorize_src_address = 1'b0;
289
                        use_memorized = 1'b1;
290
                        datamem_aswitch = 1'b1;
291
                        datamem_we = 1'b1;
292
                        bcounter_reset = 1'b0;
293
                        next_state = BURST3;
294
                end
295
                BURST3: begin
296
                        memorize_src_address = 1'b0;
297
                        use_memorized = 1'b1;
298
                        datamem_aswitch = 1'b1;
299
                        datamem_we = 1'b1;
300
                        bcounter_reset = 1'b0;
301
                        next_state = BURST4;
302
                end
303
                BURST4: begin
304
                        memorize_src_address = 1'b0;
305
                        use_memorized = 1'b1;
306
                        datamem_aswitch = 1'b1;
307
                        datamem_we = 1'b1;
308
 
309
                        next_state = READOFFSET;
310
                end
311
                READOFFSET: begin
312
                        /* Before asserting the downstream data strobe,
313
                         * we need to read the Data Memory at the correct offset
314
                         * by deasserting datamem_aswitch.
315
                         */
316
                        memorize_src_address = 1'b0;
317
                        use_memorized = 1'b1;
318
 
319
                        next_state = WAIT_DOWNSTREAM;
320
                end
321
                FLUSH: begin
322
                        flushmode = 1'b1;
323
                        tagmem_we = 1'b1;
324
                        if(flush_last)
325
                                next_state = IDLE;
326
                end
327
        endcase
328
end
329
 
330
/* Pass-through */
331
 
332
always @(posedge sys_clk) begin
333
        if(pipe_stb_i & pipe_ack_o)
334
                dst_addr1 = dst_addr;
335
end
336
 
337
endmodule

powered by: WebSVN 2.1.0

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