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

Subversion Repositories openmsp430

[/] [openmsp430/] [trunk/] [fpga/] [altera_de0_nano_soc/] [rtl/] [verilog/] [opengfx430/] [ogfx_backend_frame_fifo.v] - Blame information for rev 221

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 221 olivier.gi
//----------------------------------------------------------------------------
2
// Copyright (C) 2015 Authors
3
//
4
// This source file may be used and distributed without restriction provided
5
// that this copyright statement is not removed from the file and that any
6
// derivative work contains the original copyright notice and the associated
7
// disclaimer.
8
//
9
// This source file is free software; you can redistribute it and/or modify
10
// it under the terms of the GNU Lesser General Public License as published
11
// by the Free Software Foundation; either version 2.1 of the License, or
12
// (at your option) any later version.
13
//
14
// This source is distributed in the hope that it will be useful, but WITHOUT
15
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
17
// License for more details.
18
//
19
// You should have received a copy of the GNU Lesser General Public License
20
// along with this source; if not, write to the Free Software Foundation,
21
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
22
//
23
//----------------------------------------------------------------------------
24
//
25
// *File Name: ogfx_backend_frame_fifo.v
26
//
27
// *Module Description:
28
//                      Mini-cache memory for frame memory access.
29
//
30
// *Author(s):
31
//              - Olivier Girard,    olgirard@gmail.com
32
//
33
//----------------------------------------------------------------------------
34
// $Rev$
35
// $LastChangedBy$
36
// $LastChangedDate$
37
//----------------------------------------------------------------------------
38
`ifdef OGFX_NO_INCLUDE
39
`else
40
`include "openGFX430_defines.v"
41
`endif
42
 
43
module  ogfx_backend_frame_fifo (
44
 
45
// OUTPUTs
46
    frame_data_o,                               // Frame data
47
    frame_data_ready_o,                         // Frame data ready
48
 
49
    vid_ram_addr_o,                             // Video-RAM address
50
    vid_ram_cen_o,                              // Video-RAM enable (active low)
51
 
52
// INPUTs
53
    mclk,                                       // Main system clock
54
    puc_rst,                                    // Main system reset
55
 
56
    display_width_i,                            // Display width
57
    display_height_i,                           // Display height
58
    display_size_i,                             // Display size (number of pixels)
59
    display_y_swap_i,                           // Display configuration: swap Y axis (horizontal symmetry)
60
    display_x_swap_i,                           // Display configuration: swap X axis (vertical symmetry)
61
    display_cl_swap_i,                          // Display configuration: swap column/lines
62
 
63
    frame_data_request_i,                       // Request for next frame data
64
 
65
    gfx_mode_i,                                 // Video mode (1xx:16bpp / 011:8bpp / 010:4bpp / 001:2bpp / 000:1bpp)
66
 
67
    vid_ram_dout_i,                             // Video-RAM data output
68
    vid_ram_dout_rdy_nxt_i,                     // Video-RAM data output ready during next cycle
69
 
70
    refresh_active_i,                           // Display refresh on going
71
    refresh_frame_base_addr_i                   // Refresh frame base address
72
);
73
 
74
// OUTPUTs
75
//=========
76
output       [15:0] frame_data_o;               // Frame data
77
output              frame_data_ready_o;         // Frame data ready
78
 
79
output[`VRAM_MSB:0] vid_ram_addr_o;             // Video-RAM address
80
output              vid_ram_cen_o;              // Video-RAM enable (active low)
81
 
82
// INPUTs
83
//=========
84
input               mclk;                       // Main system clock
85
input               puc_rst;                    // Main system reset
86
 
87
input [`LPIX_MSB:0] display_width_i;            // Display width
88
input [`LPIX_MSB:0] display_height_i;           // Display height
89
input [`SPIX_MSB:0] display_size_i;             // Display size (number of pixels)
90
input               display_y_swap_i;           // Display configuration: swap Y axis (horizontal symmetry)
91
input               display_x_swap_i;           // Display configuration: swap X axis (vertical symmetry)
92
input               display_cl_swap_i;          // Display configuration: swap column/lines
93
 
94
input               frame_data_request_i;       // Request for next frame data
95
 
96
input         [2:0] gfx_mode_i;                 // Video mode (1xx:16bpp / 011:8bpp / 010:4bpp / 001:2bpp / 000:1bpp)
97
 
98
input        [15:0] vid_ram_dout_i;             // Video-RAM data output
99
input               vid_ram_dout_rdy_nxt_i;     // Video-RAM data output ready during next cycle
100
 
101
input               refresh_active_i;           // Display refresh on going
102
input [`APIX_MSB:0] refresh_frame_base_addr_i;  // Refresh frame base address
103
 
104
 
105
//=============================================================================
106
// 1)  WIRE, REGISTERS AND PARAMETER DECLARATION
107
//=============================================================================
108
 
109
// Some parameter(s)
110
parameter   FIFO_EMPTY        =  2'h0,
111
            FIFO_FULL         =  2'h3;
112
 
113
// Video modes decoding
114
wire        gfx_mode_1_bpp    =  (gfx_mode_i == 3'b000);
115
wire        gfx_mode_2_bpp    =  (gfx_mode_i == 3'b001);
116
wire        gfx_mode_4_bpp    =  (gfx_mode_i == 3'b010);
117
wire        gfx_mode_8_bpp    =  (gfx_mode_i == 3'b011);
118
wire        gfx_mode_16_bpp   = ~(gfx_mode_8_bpp | gfx_mode_4_bpp |
119
                                  gfx_mode_2_bpp | gfx_mode_1_bpp);
120
 
121
// Others
122
reg   [1:0] fifo_counter;
123
wire  [1:0] fifo_counter_nxt;
124
wire        fifo_data_ready;
125
wire        read_from_fifo;
126
reg         vid_ram_data_mux_ready;
127
reg         vid_ram_dout_ready;
128
wire [15:0] vid_ram_dout_processed;
129
 
130
 
131
//============================================================================
132
// 1) FRAME ADDRESS GENERATION
133
//============================================================================
134
 
135
//--------------------------------
136
// FIFO data request
137
//--------------------------------
138
// The FIFO requests for new data whenever it is not full (or not about to get full)
139
 
140
reg   fifo_data_request;
141
wire  fifo_data_request_nxt = refresh_active_i                  &
142
                               (fifo_counter_nxt !=  FIFO_FULL) &                      // FIFO is full
143
                             ~((fifo_counter_nxt == (FIFO_FULL-1)) & fifo_data_ready); // FIFO is about to be full
144
 
145
always @(posedge mclk or posedge puc_rst)
146
  if (puc_rst)  fifo_data_request  <= 1'h0;
147
  else          fifo_data_request  <= fifo_data_request_nxt;
148
 
149
//--------------------------------
150
// Video RAM Address generation
151
//--------------------------------
152
reg    [`APIX_MSB:0] vid_ram_pixel_addr;
153
reg    [`APIX_MSB:0] vid_ram_line_addr;
154
reg    [`LPIX_MSB:0] vid_ram_column_count;
155
 
156
// Detect when the fifo is done reading the current pixel data
157
wire                 vid_ram_pixel_done = fifo_data_request & fifo_data_ready;
158
 
159
// Detect when the current line refresh is done
160
wire   [`LPIX_MSB:0] line_length        = display_cl_swap_i ? display_height_i : display_width_i;
161
wire                 vid_ram_line_done  = vid_ram_pixel_done & (vid_ram_column_count==(line_length-{{`LPIX_MSB{1'b0}}, 1'b1}));
162
 
163
// Zero extension for LINT cleanup
164
wire [`VRAM_MSB*3:0] display_size_norm  =  {{`VRAM_MSB*3-`SPIX_MSB{1'b0}}, display_size_i};
165
wire [`VRAM_MSB*3:0] display_width_norm =  {{`VRAM_MSB*3-`LPIX_MSB{1'b0}}, display_width_i};
166
 
167
// Based on the display configuration (i.e. X-Swap / Y-Swap / CL-Swap)
168
// the screen is not going to be refreshed in the same way.
169
// The screen refresh is the performed according to the following
170
// pseudo-code procedure:
171
//
172
// for (l_idx=0; l_idx<HEIGHT; l_idx++)
173
//    for (c_idx=0; c_idx<WIDTH; c_idx++)
174
//        addr = FIRST +    0    + WIDTH*l_idx + c_idx // Normal
175
//        addr = FIRST + WIDTH-1 + WIDTH*l_idx - c_idx // X-Swap
176
//        addr = LAST  - WIDTH+1 - WIDTH*l_idx + c_idx // Y-Swap
177
//        addr = LAST  -    0    - WIDTH*l_idx - c_idx // X/Y-Swap
178
//
179
 
180
wire [`APIX_MSB:0] next_base_addr     =  ~refresh_active_i  ? refresh_frame_base_addr_i :
181
                                          vid_ram_line_done ? vid_ram_line_addr         :
182
                                                              vid_ram_pixel_addr        ;
183
 
184
wire [`APIX_MSB:0] next_addr          =   next_base_addr
185
                                        + (display_size_norm[`APIX_MSB:0]  & {`APIX_MSB+1{refresh_active_i ?  1'b0                                                          : display_y_swap_i}})
186
                                        + (display_width_norm[`APIX_MSB:0] & {`APIX_MSB+1{refresh_active_i ? (~display_y_swap_i &  (display_cl_swap_i ^ vid_ram_line_done)) : display_x_swap_i}})
187
                                        - (display_width_norm[`APIX_MSB:0] & {`APIX_MSB+1{refresh_active_i ? ( display_y_swap_i &  (display_cl_swap_i ^ vid_ram_line_done)) : display_y_swap_i}})
188
                                        + ({{`APIX_MSB{1'b0}}, 1'b1}       & {`APIX_MSB+1{refresh_active_i ? (~display_x_swap_i & ~(display_cl_swap_i ^ vid_ram_line_done)) : 1'b0            }})
189
                                        - ({{`APIX_MSB{1'b0}}, 1'b1}       & {`APIX_MSB+1{refresh_active_i ? ( display_x_swap_i & ~(display_cl_swap_i ^ vid_ram_line_done)) : display_x_swap_i}});
190
 
191
wire               update_line_addr   =  ~refresh_active_i | vid_ram_line_done;
192
wire               update_pixel_addr  =   update_line_addr | vid_ram_pixel_done;
193
 
194
// Start RAM address of currentely refreshed line
195
always @(posedge mclk or posedge puc_rst)
196
  if (puc_rst)               vid_ram_line_addr  <=  {`APIX_MSB+1{1'b0}};
197
  else if (update_line_addr) vid_ram_line_addr  <=  next_addr;
198
 
199
// Current RAM address of the currentely refreshed pixel
200
wire [`APIX_MSB:0] vid_ram_pixel_addr_nxt = update_pixel_addr ? next_addr : vid_ram_pixel_addr;
201
 
202
always @(posedge mclk or posedge puc_rst)
203
  if (puc_rst) vid_ram_pixel_addr  <=  {`APIX_MSB+1{1'b0}};
204
  else         vid_ram_pixel_addr  <=  vid_ram_pixel_addr_nxt;
205
 
206
// Count the pixel number in the current line
207
// (used to detec the end of a line)
208
always @(posedge mclk or posedge puc_rst)
209
  if (puc_rst)                 vid_ram_column_count  <=  {`LPIX_MSB+1{1'b0}};
210
  else if (~refresh_active_i)  vid_ram_column_count  <=  {`LPIX_MSB+1{1'b0}};
211
  else if (vid_ram_line_done)  vid_ram_column_count  <=  {`LPIX_MSB+1{1'b0}};
212
  else if (vid_ram_pixel_done) vid_ram_column_count  <=  vid_ram_column_count + {{`LPIX_MSB{1'b0}}, 1'b1};
213
 
214
// Depending on the color mode, format the address for doing the RAM accesses.
215
assign              vid_ram_addr_o   = ({`VRAM_MSB+1{gfx_mode_1_bpp }} & vid_ram_pixel_addr[`VRAM_MSB+4:4]) |
216
                                       ({`VRAM_MSB+1{gfx_mode_2_bpp }} & vid_ram_pixel_addr[`VRAM_MSB+3:3]) |
217
                                       ({`VRAM_MSB+1{gfx_mode_4_bpp }} & vid_ram_pixel_addr[`VRAM_MSB+2:2]) |
218
                                       ({`VRAM_MSB+1{gfx_mode_8_bpp }} & vid_ram_pixel_addr[`VRAM_MSB+1:1]) |
219
                                       ({`VRAM_MSB+1{gfx_mode_16_bpp}} & vid_ram_pixel_addr[`VRAM_MSB+0:0]) ;
220
 
221
// Compute the next RAM address to detect when a new address is generated
222
wire [`VRAM_MSB:0] vid_ram_addr_nxt = ({`VRAM_MSB+1{gfx_mode_1_bpp }} & vid_ram_pixel_addr_nxt[`VRAM_MSB+4:4]) |
223
                                      ({`VRAM_MSB+1{gfx_mode_2_bpp }} & vid_ram_pixel_addr_nxt[`VRAM_MSB+3:3]) |
224
                                      ({`VRAM_MSB+1{gfx_mode_4_bpp }} & vid_ram_pixel_addr_nxt[`VRAM_MSB+2:2]) |
225
                                      ({`VRAM_MSB+1{gfx_mode_8_bpp }} & vid_ram_pixel_addr_nxt[`VRAM_MSB+1:1]) |
226
                                      ({`VRAM_MSB+1{gfx_mode_16_bpp}} & vid_ram_pixel_addr_nxt[`VRAM_MSB+0:0]) ;
227
 
228
// Detect when a new word needs to be fetched from the memory
229
// (i.e. detect when the RAM address is updated)
230
reg  vid_ram_addr_update;
231
wire vid_ram_addr_update_nxt = (vid_ram_addr_o != vid_ram_addr_nxt);
232
always @(posedge mclk or posedge puc_rst)
233
  if (puc_rst)                 vid_ram_addr_update  <=  1'h0;
234
  else if (~refresh_active_i)  vid_ram_addr_update  <=  1'h1;
235
  else if (vid_ram_pixel_done) vid_ram_addr_update  <=  vid_ram_addr_update_nxt;
236
 
237
 
238
// Disable RAM access if there is no need to fetch a new word
239
assign vid_ram_cen_o   = vid_ram_addr_update ? ~fifo_data_request     : 1'b1;
240
 
241
// If the next FIFO data doesn't come from the RAM, then it is ready as
242
// soon as it is requested
243
assign fifo_data_ready = vid_ram_addr_update ? vid_ram_dout_rdy_nxt_i : fifo_data_request;
244
 
245
 
246
//============================================================================
247
// 2) FRAME DATA-PRE-PROCESSING (PRIOR BEING PUSHED INTO FIFO)
248
//============================================================================
249
 
250
//--------------------------------
251
// Data buffer
252
//--------------------------------
253
// For the LUT modes, it is not necessary to access the RAM for
254
// every pixel. In that case, the FIFO is filled with the values
255
// coming from the buffer.
256
// (i.e. we only take data directly from the RAM when it is just read)
257
reg [15:0] vid_ram_dout_buf;
258
always @(posedge mclk or posedge puc_rst)
259
  if (puc_rst)                 vid_ram_dout_buf <=  16'h0000;
260
  else if (vid_ram_dout_ready) vid_ram_dout_buf <=  vid_ram_dout_i;
261
 
262
wire [15:0] vid_ram_dout_mux = vid_ram_dout_ready ? vid_ram_dout_i : vid_ram_dout_buf;
263
 
264
//--------------------------------
265
// Data formating
266
//--------------------------------
267
// Depending on the mode, the address LSBs are used to select which bits
268
// of the current data word need to be put in the FIFO
269
wire [3:0] vid_ram_data_sel_nxt    = ({4{gfx_mode_1_bpp}} & {vid_ram_pixel_addr[3:0]         }) |
270
                                     ({4{gfx_mode_2_bpp}} & {vid_ram_pixel_addr[2:0], 1'b0   }) |
271
                                     ({4{gfx_mode_4_bpp}} & {vid_ram_pixel_addr[1:0], 2'b00  }) |
272
                                     ({4{gfx_mode_8_bpp}} & {vid_ram_pixel_addr[0],   3'b000 }) ;
273
 
274
reg  [3:0] vid_ram_data_sel;
275
always @(posedge mclk or posedge puc_rst)
276
  if (puc_rst)                 vid_ram_data_sel <=  4'h0;
277
  else if (vid_ram_pixel_done) vid_ram_data_sel <=  vid_ram_data_sel_nxt;
278
 
279
 
280
wire [15:0] vid_ram_dout_shifted   = (vid_ram_dout_mux >> vid_ram_data_sel);
281
 
282
// Format data output for LUT processing
283
// (8 bit LSBs are used to address the LUT memory, MSBs are ignored)
284
assign      vid_ram_dout_processed = ({16{gfx_mode_1_bpp }} & {8'h00, 7'b0000000, vid_ram_dout_shifted[0]  }) |
285
                                     ({16{gfx_mode_2_bpp }} & {8'h00, 6'b000000 , vid_ram_dout_shifted[1:0]}) |
286
                                     ({16{gfx_mode_4_bpp }} & {8'h00, 4'b0000   , vid_ram_dout_shifted[3:0]}) |
287
                                     ({16{gfx_mode_8_bpp }} & {8'h00,             vid_ram_dout_shifted[7:0]}) |
288
                                     ({16{gfx_mode_16_bpp}} & {       vid_ram_dout_shifted[15:0]           }) ;
289
 
290
//--------------------------------
291
// Data Ready
292
//--------------------------------
293
// Data is available on the bus one cycle after the rdy_nxt signals
294
always @(posedge mclk or posedge puc_rst)
295
  if (puc_rst) vid_ram_data_mux_ready  <=  1'b0;
296
  else         vid_ram_data_mux_ready  <=  fifo_data_ready;
297
 
298
always @(posedge mclk or posedge puc_rst)
299
  if (puc_rst) vid_ram_dout_ready      <=  1'b0;
300
  else         vid_ram_dout_ready      <=  vid_ram_dout_rdy_nxt_i;
301
 
302
 
303
//============================================================================
304
// 3) FIFO COUNTER
305
//============================================================================
306
 
307
// Declaration
308
// Control signals
309
wire      fifo_push =  vid_ram_data_mux_ready & (fifo_counter != FIFO_FULL);
310
wire      fifo_pop  =  read_from_fifo         & (fifo_counter != FIFO_EMPTY);
311
 
312
// Fifo counter
313
assign fifo_counter_nxt = ~refresh_active_i      ?  FIFO_EMPTY          : // Initialize
314
                          (fifo_push & fifo_pop) ?  fifo_counter        : // Keep value (pop & push at the same time)
315
                           fifo_push             ?  fifo_counter + 2'h1 : // Push
316
                           fifo_pop              ?  fifo_counter - 2'h1 : // Pop
317
                                                    fifo_counter;         // Hold
318
 
319
always @(posedge mclk or posedge puc_rst)
320
  if (puc_rst) fifo_counter <= FIFO_EMPTY;
321
  else         fifo_counter <= fifo_counter_nxt;
322
 
323
 
324
//============================================================================
325
// 4) FIFO MEMORY & RD/WR POINTERS
326
//============================================================================
327
 
328
// Write pointer
329
reg [1:0] wr_ptr;
330
always @(posedge mclk or posedge puc_rst)
331
  if (puc_rst)                    wr_ptr  <=  2'h0;
332
  else if (~refresh_active_i)     wr_ptr  <=  2'h0;
333
  else if (fifo_push)
334
    begin
335
       if (wr_ptr==(FIFO_FULL-1)) wr_ptr  <=  2'h0;
336
       else                       wr_ptr  <=  wr_ptr + 2'h1;
337
    end
338
 
339
// Memory
340
reg [15:0] fifo_mem [0:2];
341
always @(posedge mclk or posedge puc_rst)
342
  if (puc_rst)
343
    begin
344
       fifo_mem[0]      <=  16'h0000;
345
       fifo_mem[1]      <=  16'h0000;
346
       fifo_mem[2]      <=  16'h0000;
347
    end
348
  else if (fifo_push)
349
    begin
350
       fifo_mem[wr_ptr] <=  vid_ram_dout_processed;
351
    end
352
 
353
// Read pointer
354
reg [1:0] rd_ptr;
355
always @(posedge mclk or posedge puc_rst)
356
  if (puc_rst)                    rd_ptr  <=  2'h0;
357
  else if (~refresh_active_i)     rd_ptr  <=  2'h0;
358
  else if (fifo_pop)
359
    begin
360
       if (rd_ptr==(FIFO_FULL-1)) rd_ptr  <=  2'h0;
361
       else                       rd_ptr  <=  rd_ptr + 2'h1;
362
    end
363
 
364
 
365
//============================================================================
366
// 5) FRAME DATA FROM FIFO
367
//============================================================================
368
 
369
// RAW Data is valid
370
reg  frame_data_init;
371
wire frame_data_init_nxt = ~refresh_active_i ? 1'h0 :
372
                            fifo_pop         ? 1'b1 : frame_data_init;
373
 
374
always @(posedge mclk or posedge puc_rst)
375
  if (puc_rst)       frame_data_init <= 1'h0;
376
  else               frame_data_init <= frame_data_init_nxt;
377
 
378
// RAW Data from the frame buffer
379
reg [15:0] frame_data_o;
380
always @(posedge mclk or posedge puc_rst)
381
  if (puc_rst)       frame_data_o    <= 16'h0000;
382
  else if (fifo_pop) frame_data_o    <= fifo_mem[rd_ptr];
383
 
384
// Data is ready
385
assign    frame_data_ready_o       = frame_data_init_nxt & (fifo_counter != FIFO_EMPTY);
386
 
387
// Read from FIFO command
388
assign    read_from_fifo = ~refresh_active_i |
389
                           ~frame_data_init  |
390
                            ((fifo_counter != FIFO_EMPTY) & frame_data_request_i);
391
 
392
 
393
endmodule // ogfx_backend_frame_fifo
394
 
395
`ifdef OGFX_NO_INCLUDE
396
`else
397
`include "openGFX430_undefines.v"
398
`endif

powered by: WebSVN 2.1.0

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