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

Subversion Repositories rtfbitmapcontroller

[/] [rtfbitmapcontroller/] [trunk/] [rtl/] [verilog/] [rtfBitmapController.v] - Blame information for rev 9

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 9 robfinch
`timescale 1ns / 1ps
2 4 robfinch
// ============================================================================
3 9 robfinch
//  Bitmap Controller
4 4 robfinch
//  - Displays a bitmap from memory.
5
//
6
//
7 9 robfinch
//        __
8
//   \\__/ o\    (C) 2008-2013  Robert Finch, Stratford
9
//    \  __ /    All rights reserved.
10
//     \/_//     robfinch<remove>@opencores.org
11
//       ||
12 4 robfinch
//
13
//
14
// This source file is free software: you can redistribute it and/or modify 
15
// it under the terms of the GNU Lesser General Public License as published 
16
// by the Free Software Foundation, either version 3 of the License, or     
17
// (at your option) any later version.                                      
18
//                                                                          
19
// This source file is distributed in the hope that it will be useful,      
20
// but WITHOUT ANY WARRANTY; without even the implied warranty of           
21
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            
22
// GNU General Public License for more details.                             
23
//                                                                          
24
// You should have received a copy of the GNU General Public License        
25
// along with this program.  If not, see <http://www.gnu.org/licenses/>.    
26
//                                                                          
27
//
28
//  The default base screen address is:
29 9 robfinch
//              $4100000 - the second 4MiB of RAM
30 4 robfinch
//
31
//
32
//      Verilog 1995
33
//
34
// ============================================================================
35
 
36
module rtfBitmapController(
37 9 robfinch
        rst_i, s_clk_i, s_cyc_i, s_stb_i, s_ack_o, s_we_i, s_adr_i, s_dat_i, s_dat_o, irq_o,
38
        clk_i, bte_o, cti_o, bl_o, cyc_o, stb_o, ack_i, we_o, sel_o, adr_o, dat_i, dat_o,
39
        vclk, hSync, vSync, blank, rgbo, xonoff
40 4 robfinch
);
41 9 robfinch
parameter pIOAddress = 32'hFFDC5000;
42
parameter BM_BASE_ADDR1 = 32'h0410_0000;
43
parameter BM_BASE_ADDR2 = 32'h0420_0000;
44
parameter REG_CTRL = 12'd0;
45
parameter REG_CTRL2 = 12'd1;
46
parameter REG_HDISPLAYED = 12'd2;
47
parameter REG_VDISPLAYED = 12'd3;
48
parameter REG_PAGE1ADDR = 12'd5;
49
parameter REG_PAGE2ADDR = 12'd6;
50
parameter REG_REFDELAY = 12'd7;
51 4 robfinch
 
52
// SYSCON
53
input rst_i;                            // system reset
54
 
55 9 robfinch
// Peripheral slave port
56
input s_clk_i;
57
input s_cyc_i;
58
input s_stb_i;
59
output s_ack_o;
60
input s_we_i;
61
input [33:0] s_adr_i;
62
input [31:0] s_dat_i;
63
output [31:0] s_dat_o;
64
reg [31:0] s_dat_o;
65
output irq_o;
66
 
67 4 robfinch
// Video Master Port
68
// Used to read memory via burst access
69 9 robfinch
input clk_i;                            // system bus interface clock
70 4 robfinch
output [1:0] bte_o;
71
output [2:0] cti_o;
72 9 robfinch
output [5:0] bl_o;
73 4 robfinch
output cyc_o;                   // video burst request
74
output stb_o;
75
input  ack_i;                   // vid_acknowledge from memory
76
output we_o;
77 9 robfinch
output [ 3:0] sel_o;
78
output [33:0] adr_o;     // address for memory access
79
input  [31:0] dat_i;     // memory data input
80
output [31:0] dat_o;
81 4 robfinch
 
82
// Video
83 9 robfinch
input vclk;                             // Video clock 85.71 MHz
84
input hSync;                    // start/end of scan line
85
input vSync;                    // start/end of frame
86 4 robfinch
input blank;                    // blank the output
87 9 robfinch
output [23:0] rgbo;              // 8-bit RGB output
88
reg [23:0] rgbo;
89 4 robfinch
 
90 9 robfinch
input xonoff;
91 4 robfinch
 
92
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
93
// IO registers
94
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
95
reg [1:0] bte_o;
96
reg [2:0] cti_o;
97 9 robfinch
reg [5:0] bl_o;
98
reg sync_o;
99 4 robfinch
reg cyc_o;
100
reg stb_o;
101
reg we_o;
102 9 robfinch
reg [3:0] sel_o;
103
reg [33:0] adr_o;
104
reg [31:0] dat_o;
105 4 robfinch
 
106
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
107
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
108 9 robfinch
wire cs = s_cyc_i && s_stb_i && (s_adr_i[33:14]==pIOAddress[31:12]);
109
reg ack,ack1;
110
always @(posedge clk_i)
111
begin
112
        ack1 <= cs;
113
        ack <= ack1 & cs;
114
end
115
assign s_ack_o = cs ? (s_we_i ? 1'b1 : ack) : 1'b0;
116
 
117
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
118
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
119
reg [11:0] hDisplayed,vDisplayed;
120
reg [33:0] bm_base_addr1,bm_base_addr2;
121
reg [1:0] color_depth;
122
wire [8:0] fifo_cnt;
123
reg onoff;
124
reg [5:0] Bpp;                   // bits per pixel, 8,16, or 32
125
reg [1:0] hres,vres;
126
reg page;
127
reg [11:0] hrefdelay;
128
reg [11:0] vrefdelay;
129
reg [11:0] hctr;         // horizontal reference counter
130
wire [11:0] hctr1 = hctr - hrefdelay;
131
reg [11:0] vctr;         // vertical reference counter
132
wire [11:0] vctr1 = vctr - vrefdelay;
133
reg [33:0] baseAddr;     // base address register
134
wire [31:0] rgbo1;
135 4 robfinch
reg [11:0] pixelRow;
136
reg [11:0] pixelCol;
137 9 robfinch
wire [31:0] pal_wo;
138
wire [31:0] pal_o;
139 4 robfinch
 
140 9 robfinch
always @(page or bm_base_addr1 or bm_base_addr2)
141
        baseAddr = page ? bm_base_addr2 : bm_base_addr1;
142 4 robfinch
 
143 9 robfinch
syncRam512x32_1rw1r upal1
144
(
145
        .wrst(1'b0),
146
        .wclk(s_clk_i),
147
        .wce(cs & s_adr_i[13]),
148
        .we(s_we_i),
149
        .wadr(s_adr_i[10:2]),
150
        .i(s_dat_i),
151
        .wo(pal_wo),
152
        .rrst(1'b0),
153
        .rclk(vclk),
154
        .rce(1'b1),
155
        .radr({1'b0,rgbo4[7:0]}),
156
        .o(pal_o)
157
);
158
 
159 4 robfinch
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
160 9 robfinch
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
161
always @(posedge s_clk_i)
162
if (rst_i) begin
163
        page <= 1'b0;
164
        hres <= 2'b11;
165
        vres <= 2'b11;
166
        hDisplayed <= 12'd340;
167
        vDisplayed <= 12'd192;
168
        onoff <= 1'b1;
169
        color_depth <= 2'b00;
170
        bm_base_addr1 <= {BM_BASE_ADDR1,2'b00};
171
        bm_base_addr2 <= {BM_BASE_ADDR2,2'b00};
172
        hrefdelay <= 12'd218;
173
        vrefdelay <= 12'd27;
174
end
175
else begin
176
        if (cs) begin
177
                if (s_we_i) begin
178
                        casex(s_adr_i[13:2])
179
                        REG_CTRL:
180
                                begin
181
                                        onoff <= s_dat_i[0];
182
                                        color_depth <= s_dat_i[10:9];
183
                                        hres <= s_dat_i[17:16];
184
                                        vres <= s_dat_i[19:18];
185
                                end
186
                        REG_CTRL2:
187
                                begin
188
                                        page <= s_dat_i[16];
189
                                end
190
                        REG_HDISPLAYED: hDisplayed <= s_dat_i[11:0];
191
                        REG_VDISPLAYED: vDisplayed <= s_dat_i[11:0];
192
                        REG_PAGE1ADDR:  bm_base_addr1 <= {s_dat_i,2'b00};
193
                        REG_PAGE2ADDR:  bm_base_addr2 <= {s_dat_i,2'b00};
194
                        REG_REFDELAY:
195
                                begin
196
                                        hrefdelay <= s_dat_i[11:0];
197
                                        vrefdelay <= s_dat_i[27:16];
198
                                end
199
                        endcase
200
                end
201
                casex(s_adr_i[13:2])
202
                REG_CTRL:
203
                        begin
204
                                s_dat_o[0] <= onoff;
205
                                s_dat_o[10:9] <= color_depth;
206
                                s_dat_o[17:16] <= hres;
207
                                s_dat_o[19:18] <= vres;
208
                        end
209
                REG_CTRL2:
210
                        begin
211
                                s_dat_o[16] <= page;
212
                        end
213
                REG_HDISPLAYED: s_dat_o <= hDisplayed;
214
                REG_VDISPLAYED: s_dat_o <= vDisplayed;
215
                REG_PAGE1ADDR:  s_dat_o <= bm_base_addr1;
216
                REG_PAGE2ADDR:  s_dat_o <= bm_base_addr2;
217
                REG_REFDELAY:   s_dat_o <= {vrefdelay,4'h0,hrefdelay};
218
                12'b100x_xxxx_xxxx:     s_dat_o <= pal_wo;
219
                endcase
220
        end
221
        else
222
                s_dat_o <= 32'd0;
223
end
224
 
225
assign irq_o = 1'b0;
226
 
227
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
228 4 robfinch
// Horizontal and Vertical timing reference counters
229
// - The memory fetch address is determined from these counters.
230
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
231 9 robfinch
wire hSyncEdge, vSyncEdge;
232
edge_det ed0(.rst(rst_i), .clk(vclk), .ce(1'b1), .i(hSync), .pe(hSyncEdge), .ne(), .ee() );
233
edge_det ed1(.rst(rst_i), .clk(vclk), .ce(1'b1), .i(vSync), .pe(vSyncEdge), .ne(), .ee() );
234 4 robfinch
 
235 9 robfinch
always @(posedge vclk)
236
if (rst_i)              hctr <= 1;
237
else if (hSyncEdge) hctr <= 1;
238
else                    hctr <= hctr + 1;
239 4 robfinch
 
240 9 robfinch
always @(posedge vclk)
241
if (rst_i)              vctr <= 1;
242
else if (vSyncEdge) vctr <= 1;
243
else if (hSyncEdge) vctr <= vctr + 1;
244 4 robfinch
 
245 9 robfinch
 
246 4 robfinch
// Pixel row and column are derived from the horizontal and vertical counts.
247
 
248
always @(vctr1)
249 9 robfinch
        case(vres)
250
        2'b00:          pixelRow <= vctr1[11:0];
251
        2'b01:          pixelRow <= vctr1[11:1];
252
        2'b10:          pixelRow <= vctr1[11:2];
253
        default:        pixelRow <= vctr1[11:2];
254
        endcase
255
always @(hctr1)
256
        case(hres)
257
        2'b00:          pixelCol = hctr1[11:0];
258
        2'b01:          pixelCol = hctr1[11:1];
259
        2'b10:          pixelCol = hctr1[11:2];
260
        default:        pixelCol = hctr1[11:2];
261
        endcase
262 4 robfinch
 
263 9 robfinch
wire vFetch = vctr1 < vDisplayed;
264
wire fifo_rst = hctr[11:4]==8'h00;
265 4 robfinch
 
266 9 robfinch
wire[23:0] rowOffset = pixelRow * hDisplayed;
267
reg [11:0] fetchCol;
268 4 robfinch
 
269
// - read from assigned video memory address, using burst mode reads
270 9 robfinch
// - 64 pixels at a time are read
271 4 robfinch
// - video data is fetched one pixel row in advance
272
//
273 9 robfinch
reg [5:0] bcnt;
274
wire [5:0] bcnt_inc = bcnt + 6'd1;
275
reg [33:0] adr;
276 4 robfinch
always @(posedge clk_i)
277
if (rst_i) begin
278 9 robfinch
        wb_nack();
279
        fetchCol <= 12'd0;
280
        bcnt <= 6'd0;
281 4 robfinch
end
282
else begin
283 9 robfinch
        if (fifo_rst) begin
284
                fetchCol <= 12'd0;
285
                adr <= baseAddr + rowOffset;
286
        end
287
        else if (fifo_cnt < 9'd500 && vFetch && onoff && xonoff && fetchCol < hDisplayed && !cyc_o) begin
288
                cti_o <= 3'b001;        // constant address burst
289 4 robfinch
                cyc_o <= 1'b1;
290
                stb_o <= 1'b1;
291 9 robfinch
                sel_o <= 4'b1111;
292
                bcnt <= 6'd0;
293
                bl_o <= 6'd7;
294
                adr_o <= adr;
295 4 robfinch
        end
296
        if (cyc_o & ack_i) begin
297 9 robfinch
                case(color_depth)
298
                2'b00:  fetchCol <= fetchCol + 12'd4;
299
                2'b01:  fetchCol <= fetchCol + 12'd2;
300
                2'b11:  fetchCol <= fetchCol + 12'd1;
301
                default:        fetchCol <= 12'hFF0;
302
                endcase
303
                bcnt <= bcnt_inc;
304
                if (bl_o==bcnt_inc)
305 4 robfinch
                        cti_o <= 3'b111;        // end of burst
306 9 robfinch
                else if (bl_o==bcnt) begin
307
                        wb_nack();
308
                        adr <= adr + 34'd32;
309 4 robfinch
                end
310
        end
311
end
312
 
313 9 robfinch
task wb_nack;
314
begin
315
        bte_o <= 2'b00;         // linear burst
316
        cti_o <= 3'b000;        // classic cycle
317
        bl_o <= 6'd0;
318
        cyc_o <= 1'b0;
319
        stb_o <= 1'b0;
320
        sel_o <= 4'b0000;
321
        we_o <= 1'b0;
322
        adr_o <= 34'h0000_0000;
323
        dat_o <= 32'h0000_0000;
324
end
325
endtask
326 4 robfinch
 
327 9 robfinch
reg [11:0] pixelColD1;
328
reg [31:0] rgbo2,rgbo3,rgbo4;
329 4 robfinch
always @(posedge vclk)
330 9 robfinch
        if (color_depth==2'b00)
331
                rgbo4 <= rgbo2;
332
        else if (color_depth==2'b01)
333
                rgbo4 <= {rgbo3[14:10],3'b0,rgbo3[9:5],3'b0,rgbo3[4:0],3'b0};
334
        else
335
                rgbo4 <= rgbo1;
336 4 robfinch
 
337
 
338 9 robfinch
reg rd_fifo,rd_fifo1,rd_fifo2;
339
reg de;
340
always @(posedge vclk)
341
        if (rd_fifo1)
342
                de <= ~blank;
343 4 robfinch
 
344 9 robfinch
always @(posedge vclk)
345
        if (onoff & xonoff & de) begin
346
                if (color_depth==2'b00)
347
                        rgbo <= pal_o;
348
                else
349
                        rgbo <= rgbo4;
350
        end
351
        else
352
                rgbo <= 24'd0;
353
 
354
wire vrd;
355
always @(posedge vclk) pixelColD1 <= pixelCol;
356
always @(posedge vclk)
357
if (pixelCol < hDisplayed + 12'd8)
358
        case({color_depth,hres})
359
        4'b0000:        rd_fifo1 <= hctr[1:0]==2'b00;    // 4 clocks
360
        4'b0001:        rd_fifo1 <= hctr[2:0]==3'b000;   // 8 clocks
361
        4'b0010:        rd_fifo1 <= hctr[3:0]==4'b0000;  // 16 clocks
362
        4'b0011:        rd_fifo1 <= hctr[3:0]==4'b0000;  // unsupported
363
        4'b0100:        rd_fifo1 <= hctr[0]==1'b0;               // 2 clocks
364
        4'b0101:        rd_fifo1 <= hctr[1:0]==2'b00;    // 4 clocks
365
        4'b0110:        rd_fifo1 <= hctr[2:0]==3'b000;   // 8 clocks (twice as often as a byte)
366
        4'b0111:        rd_fifo1 <= hctr[2:0]==3'b000;
367
        4'b1000:        rd_fifo1 <= 1'b0;
368
        4'b1001:        rd_fifo1 <= 1'b0;
369
        4'b1010:        rd_fifo1 <= 1'b0;
370
        4'b1011:        rd_fifo1 <= 1'b0;
371
        4'b1100:        rd_fifo1 <= 1'b1;
372
        4'b1101:        rd_fifo1 <= hctr[0]==1'b0;
373
        4'b1110:        rd_fifo1 <= hctr[1:0]==2'b00;
374
        4'b1111:        rd_fifo1 <= hctr[1:0]==2'b00;
375
        endcase
376
reg shift,shift1,shift2;
377
always @(posedge vclk)
378
if (pixelCol < hDisplayed + 12'd8)
379
        case({color_depth,hres})
380
        // shift four times as often as a load
381
        4'b0000:        shift1 <= 1'b1;
382
        4'b0001:        shift1 <= hctr[0]==1'b0;
383
        4'b0010:        shift1 <= hctr[1:0]==2'b00;
384
        4'b0011:        shift1 <= hctr[1:0]==2'b00;
385
        // shift twice as often as a load
386
        4'b0100:        shift1 <= 1'b1;
387
        4'b0101:        shift1 <= hctr[0]==1'b0;
388
        4'b0110:        shift1 <= hctr[1:0]==2'b00;
389
        4'b0111:        shift1 <= hctr[1:0]==2'b00;
390
        // unsupported color depth
391
        4'b1000:        shift1 <= 1'b0;
392
        4'b1001:        shift1 <= 1'b0;
393
        4'b1010:        shift1 <= 1'b0;
394
        4'b1011:        shift1 <= 1'b0;
395
        // nothing to shift (all loads)
396
        4'b1100:        shift1 <= 1'b0;
397
        4'b1101:        shift1 <= 1'b0;
398
        4'b1110:        shift1 <= 1'b0;
399
        4'b1111:        shift1 <= 1'b0;
400
        endcase
401
always @(posedge vclk) shift2 <= shift1;
402
always @(posedge vclk) shift <= shift2;
403
always @(posedge vclk) rd_fifo2 <= rd_fifo1;
404
always @(posedge vclk) rd_fifo <= rd_fifo2;
405
always @(posedge vclk)
406
        if (rd_fifo)
407
                rgbo2 <= rgbo1;
408
        else if (shift)
409
                rgbo2 <= {8'h00,rgbo2[31:8]};
410
always @(posedge vclk)
411
        if (rd_fifo)
412
                rgbo3 <= rgbo1;
413
        else if (shift)
414
                rgbo3 <= {16'h0000,rgbo3[31:16]};
415
 
416
rtfVideoFifo uf1
417 4 robfinch
(
418 9 robfinch
        .rst(fifo_rst),
419
        .wclk(clk_i),
420
        .wr(cyc_o & ack_i),
421
        .di(dat_i),
422
        .rclk(vclk),
423
        .rd(rd_fifo),
424
        .do(rgbo1),
425
        .cnt(fifo_cnt)
426 4 robfinch
);
427
 
428
endmodule
429 9 robfinch
 

powered by: WebSVN 2.1.0

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