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

Subversion Repositories zet86

[/] [zet86/] [trunk/] [soc/] [vga/] [rtl/] [vdu.v] - Blame information for rev 51

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

Line No. Rev Author Line
1 40 zeus
/*
2
 *  Copyright (c) 2008  Zeus Gomez Marmolejo <zeus@opencores.org>
3
 *
4
 *  This file is part of the Zet processor. This processor is free
5
 *  hardware; you can redistribute it and/or modify it under the terms of
6
 *  the GNU General Public License as published by the Free Software
7
 *  Foundation; either version 3, or (at your option) any later version.
8
 *
9
 *  Zet is distrubuted in the hope that it will be useful, but WITHOUT
10
 *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11
 *  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
12
 *  License for more details.
13
 *
14
 *  You should have received a copy of the GNU General Public License
15
 *  along with Zet; see the file COPYING. If not, see
16
 *  <http://www.gnu.org/licenses/>.
17
 */
18
 
19 39 zeus
`timescale 1ns/10ps
20
 
21
module vdu (
22
    // Wishbone signals
23
    input             wb_clk_i,     // 25 Mhz VDU clock
24
    input             wb_rst_i,
25
    input      [15:0] wb_dat_i,
26
    output reg [15:0] wb_dat_o,
27
    input      [11:1] wb_adr_i,
28
    input             wb_we_i,
29
    input             wb_tga_i,
30
    input      [ 1:0] wb_sel_i,
31
    input             wb_stb_i,
32
    input             wb_cyc_i,
33
    output reg        wb_ack_o,
34
 
35
    // VGA pad signals
36
    output reg [ 1:0] vga_red_o,
37
    output reg [ 1:0] vga_green_o,
38
    output reg [ 1:0] vga_blue_o,
39
    output reg        horiz_sync,
40
    output reg        vert_sync
41
  );
42
 
43
  // Net, registers and parameters
44
 
45 40 zeus
  // Synchronization constants, these values are taken from:
46
  //  http://tinyvga.com/vga-timing/640x400@70Hz
47
 
48
  parameter HOR_DISP_END = 10'd639; // Last horizontal pixel displayed
49
  parameter HOR_SYNC_BEG = 10'd655; // Start of horizontal synch pulse
50
  parameter HOR_SYNC_END = 10'd751; // End of Horizontal Synch pulse
51 39 zeus
  parameter HOR_SCAN_END = 10'd799; // Last pixel in scan line
52
  parameter HOR_DISP_CHR = 80;      // Number of characters displayed per row
53 40 zeus
  parameter HOR_VIDEO_ON = 10'd7;   // When to start displaying characters
54
  parameter HOR_VIDEO_OFF = 10'd647; // When to stop displaying characters
55 39 zeus
 
56 48 zeus
  parameter VER_DISP_END = 9'd400;  // last row displayed
57 40 zeus
  parameter VER_SYNC_BEG = 9'd411;  // start of vertical synch pulse
58
  parameter VER_SYNC_END = 9'd413;  // end of vertical synch pulse
59
  parameter VER_SCAN_END = 9'd448;  // Last scan row in the frame
60 39 zeus
  parameter VER_DISP_CHR = 6'd25;   // Number of character rows displayed
61
 
62
  reg        cursor_on_v;
63
  reg        cursor_on_h;
64
  reg        video_on_v;
65
  reg        video_on_h;
66
  reg [9:0]  h_count;
67
  reg [8:0]  v_count;       // 0 to VER_SCAN_END
68
  reg [22:0] blink_count;
69
 
70
  // Character generator ROM
71
  wire        char_cs;
72
  wire        char_we;
73
  wire [11:0] char_addr;
74
  wire [7:0]  char_data_in;
75
  wire [7:0]  char_data_out;
76
 
77
  // Control registers
78 48 zeus
  reg [3:0] reg_adr;
79 39 zeus
  reg [6:0] reg_hcursor; // 80 columns
80
  reg [4:0] reg_vcursor; // 25 rows
81 48 zeus
  reg [3:0] reg_cur_start;
82
  reg [3:0] reg_cur_end;
83 39 zeus
 
84 48 zeus
  wire      wr_adr;
85
  wire      wr_reg;
86
  wire      write;
87
  wire      wr_hcursor;
88
  wire      wr_vcursor;
89
  wire      wr_cur_start;
90
  wire      wr_cur_end;
91 39 zeus
 
92
  // Video shift register
93
  reg [7:0] vga_shift;
94
  reg [2:0] vga_fg_colour;
95
  reg [2:0] vga_bg_colour;
96
  reg       cursor_on;
97
  wire      cursor_on1;
98
  reg       video_on;
99
  wire      video_on1;
100
 
101
  // vga character ram access bus
102
  reg   [6:0] col_addr;  // 0 to 79
103
  reg   [4:0] row_addr;  // 0 to 49 (25 * 2 -1)
104
  reg   [6:0] col1_addr; // 0 to 79
105
  reg   [4:0] row1_addr; // 0 to 49 (25 * 2 - 1)
106
  reg   [6:0] hor_addr;  // 0 to 79
107
  reg   [6:0] ver_addr;  // 0 to 124
108
  reg         vga0_we;
109
  reg         vga0_rw, vga1_rw, vga2_rw, vga3_rw, vga4_rw;
110
  reg         vga1_we;
111
  reg         vga2_we;
112
  reg         buff_we;
113
  reg   [7:0] buff_data_in;
114
  reg         attr_we;
115
  reg   [7:0] attr_data_in;
116
  reg  [10:0] buff_addr;
117
  reg  [10:0] attr0_addr;
118
  reg         attr0_we;
119
  reg  [10:0] buff0_addr;
120
  reg         buff0_we;
121
  reg  [10:0] attr_addr;
122
  reg         intense;
123
  wire        vga_cs;
124
  wire  [7:0] vga_data_out;
125
  wire  [7:0] attr_data_out;
126
  wire [10:0] vga_addr;  // 2K byte character buffer
127
  wire [15:0] out_data;
128
  wire        fg_or_bg;
129
  wire        stb;
130
  wire        brown_bg;
131
  wire        brown_fg;
132 41 zeus
  wire        status_reg1;
133
  wire        vh_retrace;
134
  wire        v_retrace;
135 39 zeus
 
136
  // Module instantiation
137
  char_rom vdu_char_rom (
138
    .clk   (wb_clk_i),
139
    .rst   (wb_rst_i),
140
    .cs    (char_cs),
141
    .we    (char_we),
142
    .addr  (char_addr),
143
    .wdata (char_data_in),
144
    .rdata (char_data_out)
145
  );
146
 
147
  ram_2k char_buff_ram (
148
    .clk   (wb_clk_i),
149
    .rst   (wb_rst_i),
150
    .cs    (vga_cs),
151
    .we    (buff_we),
152
    .addr  (buff_addr),
153
    .wdata (buff_data_in),
154
    .rdata (vga_data_out)
155
  );
156
 
157
  ram_2k_attr attr_buff_ram (
158
    .clk   (wb_clk_i),
159
    .rst   (wb_rst_i),
160
    .cs    (vga_cs),
161
    .we    (attr_we),
162
    .addr  (attr_addr),
163
    .wdata (attr_data_in),
164
    .rdata (attr_data_out)
165
  );
166
 
167
  // Assignments
168
  assign video_on1  = video_on_h && video_on_v;
169
  assign cursor_on1 = cursor_on_h && cursor_on_v;
170
  assign char_cs    = 1'b1;
171
  assign char_we    = 1'b0;
172
  assign char_data_in = 8'b0;
173
  assign char_addr  = { vga_data_out, v_count[3:0] };
174
  assign vga_addr   = { 4'b0, hor_addr} + { ver_addr, 4'b0 };
175
  assign out_data   = {attr_data_out, vga_data_out};
176
 
177
  assign vga_cs     = 1'b1;
178
  assign stb        = wb_stb_i && wb_cyc_i;
179
 
180
  assign fg_or_bg    = vga_shift[7] ^ cursor_on;
181
  assign brown_fg    = (vga_fg_colour==3'd6) && !intense;
182
  assign brown_bg    = (vga_bg_colour==3'd6);
183
 
184 48 zeus
  // Control registers
185
  assign write        = wb_tga_i & wb_stb_i & wb_cyc_i & wb_we_i;
186
  assign wr_adr       = write & wb_sel_i[0];
187
  assign wr_reg       = write & wb_sel_i[1];
188
  assign wr_hcursor   = wr_reg & (reg_adr==4'hf);
189
  assign wr_vcursor   = wr_reg & (reg_adr==4'he);
190
  assign wr_cur_start = wr_reg & (reg_adr==4'ha);
191
  assign wr_cur_end   = wr_reg & (reg_adr==4'hb);
192 39 zeus
 
193 41 zeus
  assign v_retrace   = !video_on_v;
194
  assign vh_retrace  = v_retrace | !video_on_h;
195
  assign status_reg1 = { 11'b0, v_retrace, 3'b0, vh_retrace };
196
 
197 39 zeus
  // Behaviour
198
 
199
  // CPU write interface
200
  always @(posedge wb_clk_i)
201
    if (wb_rst_i)
202
      begin
203
        attr0_addr    <= 11'b0;
204
        attr0_we      <= 1'b0;
205
        attr_data_in  <= 8'h0;
206
        buff0_addr    <= 11'b0;
207
        buff0_we      <= 1'b0;
208
        buff_data_in  <= 8'h0;
209
      end
210
    else
211
      begin
212
        if (stb && !wb_tga_i)
213
          begin
214
            attr0_addr   <= wb_adr_i;
215
            attr0_we     <= wb_we_i & wb_sel_i[1];
216
            attr_data_in <= wb_dat_i[15:8];
217
            buff0_addr   <= wb_adr_i;
218
            buff0_we     <= wb_we_i & wb_sel_i[0];
219
            buff_data_in <= wb_dat_i[7:0];
220
          end
221
      end
222
 
223
  // CPU read interface
224
  always @(posedge wb_clk_i)
225
    if (wb_rst_i)
226
      begin
227
        wb_dat_o <= 16'h0;
228
        wb_ack_o <= 16'h0;
229
      end
230
    else
231 41 zeus
      if (wb_tga_i)
232
        begin
233
          wb_dat_o <= status_reg1;
234
          wb_ack_o <= stb;
235
        end
236
      else
237
        begin
238
          wb_dat_o <= vga4_rw ? out_data : wb_dat_o;
239
          wb_ack_o <= vga4_rw ? 1'b1 : (wb_ack_o && stb);
240
        end
241 39 zeus
 
242 48 zeus
  // Control registers
243 39 zeus
  always @(posedge wb_clk_i)
244 48 zeus
    reg_adr <= wb_rst_i ? 4'h0
245
      : (wr_adr ? wb_dat_i[3:0] : reg_adr);
246 39 zeus
 
247 48 zeus
  always @(posedge wb_clk_i)
248
    reg_hcursor <= wb_rst_i ? 7'h0
249
      : (wr_hcursor ? wb_dat_i[14:8] : reg_hcursor);
250
 
251
  always @(posedge wb_clk_i)
252
    reg_vcursor <= wb_rst_i ? 5'h0
253
      : (wr_vcursor ? wb_dat_i[12:8] : reg_vcursor);
254
 
255
  always @(posedge wb_clk_i)
256
    reg_cur_start <= wb_rst_i ? 4'he
257
      : (wr_cur_start ? wb_dat_i[11:8] : reg_cur_start);
258
 
259
  always @(posedge wb_clk_i)
260
    reg_cur_end <= wb_rst_i ? 4'hf
261
      : (wr_cur_end ? wb_dat_i[11:8] : reg_cur_end);
262
 
263 39 zeus
  // Sync generation & timing process
264
  // Generate horizontal and vertical timing signals for video signal
265
  always @(posedge wb_clk_i)
266
    if (wb_rst_i)
267
      begin
268
        h_count     <= 10'b0;
269
        horiz_sync  <= 1'b1;
270
        v_count     <= 9'b0;
271
        vert_sync   <= 1'b1;
272
        video_on_h  <= 1'b1;
273
        video_on_v  <= 1'b1;
274
        cursor_on_h <= 1'b0;
275
        cursor_on_v <= 1'b0;
276
        blink_count <= 22'b0;
277
      end
278
    else
279
      begin
280
        h_count    <= (h_count==HOR_SCAN_END) ? 10'b0 : h_count + 10'b1;
281
        horiz_sync <= (h_count==HOR_SYNC_BEG) ? 1'b0
282
                    : ((h_count==HOR_SYNC_END) ? 1'b1 : horiz_sync);
283
        v_count    <= (v_count==VER_SCAN_END && h_count==HOR_SCAN_END) ? 9'b0
284
                    : ((h_count==HOR_SYNC_END) ? v_count + 9'b1 : v_count);
285
        vert_sync  <= (v_count==VER_SYNC_BEG) ? 1'b0
286
                    : ((v_count==VER_SYNC_END) ? 1'b1 : vert_sync);
287 40 zeus
        video_on_h <= (h_count==HOR_VIDEO_ON) ? 1'b1
288
                    : ((h_count==HOR_VIDEO_OFF) ? 1'b0 : video_on_h);
289 48 zeus
        video_on_v <= (v_count==9'h0) ? 1'b1
290 39 zeus
                    : ((v_count==VER_DISP_END) ? 1'b0 : video_on_v);
291
        cursor_on_h <= (h_count[9:3] == reg_hcursor[6:0]);
292 48 zeus
        cursor_on_v <= (v_count[8:4] == reg_vcursor[4:0])
293
                    && (v_count[3:0] >= reg_cur_start)
294
                    && (v_count[3:0] <= reg_cur_end);
295 39 zeus
        blink_count <= blink_count + 22'd1;
296
      end
297
 
298
  // Video memory access
299
  always @(posedge wb_clk_i)
300
    if (wb_rst_i)
301
      begin
302
        vga0_we <= 1'b0;
303
        vga0_rw <= 1'b1;
304
        row_addr <= 5'b0;
305
        col_addr <= 7'b0;
306
 
307
        vga1_we  <= 1'b0;
308
        vga1_rw  <= 1'b1;
309
        row1_addr <= 5'b0;
310
        col1_addr <= 7'b0;
311
 
312
        vga2_we  <= 1'b0;
313
        vga2_rw  <= 1'b0;
314
        vga3_rw  <= 1'b0;
315
        vga4_rw  <= 1'b0;
316
        ver_addr <= 7'b0;
317
        hor_addr <= 7'b0;
318
 
319
        buff_addr <= 10'b0;
320
        attr_addr <= 10'b0;
321
        buff_we   <= 1'b0;
322
        attr_we   <= 1'b0;
323
      end
324
    else
325
      begin
326
        // on h_count = 0 initiate character write
327
        // all other cycles are reads
328
        case (h_count[2:0])
329
          3'b000:   // pipeline character write
330
            begin
331
              vga0_we <= wb_we_i;
332
              vga0_rw <= stb;
333
            end
334
          default:  // other 6 cycles free
335
            begin
336
              vga0_we <= 1'b0;
337
              vga0_rw <= 1'b0;
338
              col_addr <= h_count[9:3];
339
              row_addr <= v_count[8:4];
340
            end
341
        endcase
342
 
343
        // on vdu_clk + 1 round off row address
344
        // row1_addr = (row_addr % 80)
345
        vga1_we <= vga0_we;
346
        vga1_rw <= vga0_rw;
347
        row1_addr <= (row_addr < VER_DISP_CHR) ? row_addr
348
                    : row_addr - VER_DISP_CHR;
349
        col1_addr <= col_addr;
350
 
351
        // on vdu_clk + 2 calculate vertical address
352
        // ver_addr = (row_addr % 80) x 5
353
        vga2_we <= vga1_we;
354
        vga2_rw <= vga1_rw;
355
        ver_addr <= { 2'b00, row1_addr } + { row1_addr, 2'b00 }; // x5
356
        hor_addr <= col1_addr;
357
 
358
        // on vdu_clk + 3 calculate memory address
359
        // vga_addr = (row_addr % 80) * 80 + hor_addr
360
        buff_addr <= vga2_rw ? buff0_addr : vga_addr;
361
        attr_addr <= vga2_rw ? attr0_addr : vga_addr;
362
        buff_we   <= vga2_rw ? (buff0_we & vga2_we) : 1'b0;
363
        attr_we   <= vga2_rw ? (attr0_we & vga2_we) : 1'b0;
364
        vga3_rw   <= vga2_rw;
365
        vga4_rw   <= vga3_rw;
366
      end
367
 
368
  // Video shift register
369
  always @(posedge wb_clk_i)
370
    if (wb_rst_i)
371
      begin
372
        video_on      <= 1'b0;
373
        cursor_on     <= 1'b0;
374
        vga_bg_colour <= 3'b000;
375
        vga_fg_colour <= 3'b111;
376
        vga_shift     <= 8'b00000000;
377
        vga_red_o     <= 1'b0;
378
        vga_green_o   <= 1'b0;
379
        vga_blue_o    <= 1'b0;
380
      end
381
    else
382
      begin
383
        if (h_count[2:0] == 3'b000)
384
          begin
385
            video_on      <= video_on1;
386
            cursor_on     <= (cursor_on1 | attr_data_out[7]) & blink_count[22];
387
            vga_fg_colour <= attr_data_out[2:0];
388
            vga_bg_colour <= attr_data_out[6:4];
389
            intense       <= attr_data_out[3];
390
            vga_shift     <= char_data_out;
391
          end
392
        else vga_shift <= { vga_shift[6:0], 1'b0 };
393
 
394
        //
395
        // Colour mask is
396
        //  7  6  5  4  3  2  1  0
397
        //  X BR BG BB  X FR FG FB
398
        //
399
        vga_blue_o   <= video_on ? (fg_or_bg ? { vga_fg_colour[0], intense }
400
                                            : { vga_bg_colour[0], 1'b0 })
401
                                : 2'b0;
402
 
403
        // Green color exception with color brown
404
        // http://en.wikipedia.org/wiki/Color_Graphics_Adapter#With_an_RGBI_monitor
405
        vga_green_o  <= video_on ?
406
           (fg_or_bg ? (brown_fg ? 2'b01 : { vga_fg_colour[1], intense })
407
                     : (brown_bg ? 2'b01 : { vga_bg_colour[1], 1'b0 }))
408
                                : 2'b0;
409
        vga_red_o    <= video_on ? (fg_or_bg ? { vga_fg_colour[2], intense }
410
                                            : { vga_bg_colour[2], 1'b0 })
411
                                : 2'b0;
412
      end
413
endmodule

powered by: WebSVN 2.1.0

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