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

Subversion Repositories zet86

[/] [zet86/] [tags/] [INITIAL/] [impl/] [spartan3an-sk/] [rtl/] [vga/] [vdu.v] - Blame information for rev 49

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 zeus
// Video Display terminal
2
// John Kent
3
// 3th September 2004 
4
// Assumes a pixel clock input of 50 MHz
5
// Generates a 12.5MHz CPU Clock output
6
//
7
// Display Format is: 
8
// 80 characters across by 25 characters down.
9
// 8 horizonal pixels / character
10
// 16 vertical scan lines / character (2 scan lines/row)
11
`timescale 1ns/10ps
12
 
13
module vdu
14
  (
15
    input             vdu_clk_in,  // 50MHz     System clock
16
    output            cpu_clk_out, // 6.25 MHz CPU Clock
17
    input             vdu_rst,
18
    input             vdu_cs,
19
    input             vdu_we,
20
    input             byte_m,
21
    input      [11:0] vdu_addr,
22
    input      [15:0] wr_data,
23
    output reg [15:0] rd_data,
24
    output            ready,
25
 
26
    output reg        vga_red_o,
27
    output reg        vga_green_o,
28
    output reg        vga_blue_o,
29
    output reg        horiz_sync,
30
    output reg        vert_sync
31
  );
32
 
33
  // Net, registers and parameters
34
 
35
  // Synchronization constants
36
  parameter HOR_DISP_END = 10'd639; // Last horizontal pixel displayed
37
  parameter HOR_SYNC_BEG = 10'd679; // Start of horizontal synch pulse
38
  parameter HOR_SYNC_END = 10'd775; // End of Horizontal Synch pulse
39
  parameter HOR_SCAN_END = 10'd799; // Last pixel in scan line
40
  parameter HOR_DISP_CHR = 80;      // Number of characters displayed per row
41
 
42
  parameter VER_DISP_END = 9'd399;  // last row displayed
43
  parameter VER_SYNC_BEG = 9'd413;  // start of vertical synch pulse
44
  parameter VER_SYNC_END = 9'd414;  // end of vertical synch pulse
45
  parameter VER_SCAN_END = 9'd450;  // Last scan row in the frame
46
  parameter VER_DISP_CHR = 6'd25;   // Number of character rows displayed
47
 
48
  reg        cursor_on_v;
49
  reg        cursor_on_h;
50
  reg        video_on_v;
51
  reg        video_on_h;
52
  reg [9:0]  h_count;
53
  reg [8:0]  v_count;       // 0 to VER_SCAN_END
54
  reg [22:0] blink_count;
55
 
56
  // Character generator ROM
57
  wire        char_cs;
58
  wire        char_we;
59
  wire [11:0] char_addr;
60
  wire [7:0]  char_data_in;
61
  wire [7:0]  char_data_out;
62
 
63
  // Control registers
64
  wire [6:0] reg_hcursor; // 80 columns
65
  wire [4:0] reg_vcursor; // 25 rows
66
  wire [4:0] reg_voffset; // 25 rows
67
 
68
  // Video shift register
69
  reg [7:0] vga_shift;
70
  reg [2:0] vga_fg_colour;
71
  reg [2:0] vga_bg_colour;
72
  reg       cursor_on;
73
  wire      cursor_on1;
74
  reg       video_on;
75
  wire      video_on1;
76
 
77
  // vga character ram access bus
78
  reg   [6:0] col_addr;  // 0 to 79
79
  reg   [4:0] row_addr;  // 0 to 49 (25 * 2 -1)
80
  reg   [6:0] col1_addr; // 0 to 79
81
  reg   [4:0] row1_addr; // 0 to 49 (25 * 2 - 1)
82
  reg   [6:0] hor_addr;  // 0 to 79
83
  reg   [6:0] ver_addr;  // 0 to 124
84
  reg         vga0_we;
85
  reg         vga0_rw, vga1_rw, vga2_rw, vga3_rw, vga4_rw;
86
  reg         vga1_we;
87
  reg         vga2_we;
88
  reg         buff_we;
89
  reg   [7:0] buff_data_in;
90
  reg         attr_we;
91
  reg   [7:0] attr_data_in;
92
  reg  [10:0] buff_addr;
93
  reg  [10:0] attr0_addr;
94
  reg         attr0_we;
95
  reg  [10:0] buff0_addr;
96
  reg         buff0_we;
97
  reg  [10:0] attr_addr;
98
  wire        vga_cs;
99
  wire  [7:0] vga_data_out;
100
  wire  [7:0] attr_data_out;
101
  wire [10:0] vga_addr;  // 2K byte character buffer
102
  wire        a0;
103
  wire [10:0] vdu_addr1;
104
  wire        byte1;
105
  wire [15:0] out_data;
106
  wire [15:0] ext_attr, ext_buff;
107
  wire        fg_or_bg;
108
 
109
  // Character write handshake signals
110
  reg req_write; // request character write
111
  reg req_read;
112
  reg one_more_cycle;
113
 
114
  // Clock divider
115
  reg [1:0] clk_count;
116
  wire      vdu_clk;
117
 
118
  // Module instantiation
119
  char_rom vdu_char_rom (
120
    .clk   (vdu_clk),
121
    .rst   (vdu_rst),
122
    .cs    (char_cs),
123
    .we    (char_we),
124
    .addr  (char_addr),
125
    .wdata (char_data_in),
126
    .rdata (char_data_out)
127
  );
128
 
129
  ram_2k char_buff_ram (
130
    .clk   (vdu_clk),
131
    .rst   (vdu_rst),
132
    .cs    (vga_cs),
133
    .we    (buff_we),
134
    .addr  (buff_addr),
135
    .wdata (buff_data_in),
136
    .rdata (vga_data_out)
137
  );
138
 
139
  ram_2k_attr attr_buff_ram (
140
    .clk   (vdu_clk),
141
    .rst   (vdu_rst),
142
    .cs    (vga_cs),
143
    .we    (attr_we),
144
    .addr  (attr_addr),
145
    .wdata (attr_data_in),
146
    .rdata (attr_data_out)
147
  );
148
 
149
  BUFG vdu_clk_buffer (
150
    .I (clk_count[0]),
151
    .O (vdu_clk)
152
  );
153
 
154
  BUFG cpu_clk_buffer (
155
    .I (clk_count[1]),
156
    .O (cpu_clk_out)
157
  );
158
 
159
  // Assignments
160
  assign video_on1  = video_on_h && video_on_v;
161
  assign cursor_on1 = cursor_on_h && cursor_on_v;
162
  assign char_cs    = 1'b1;
163
  assign char_we    = 1'b1;
164
  assign char_data_in = 8'b0;
165
  assign char_addr  = { vga_data_out, v_count[3:0] };
166
  assign vga_addr   = { 4'b0, hor_addr} + { ver_addr, 4'b0 };
167
  assign a0         = vdu_addr[0];
168
  assign vdu_addr1  = vdu_addr[11:1] + 11'd1;
169
  assign byte1      = byte_m || (vdu_addr == 12'hfff);
170
  assign ready      = !req_write && !req_read;
171
  assign out_data   = a0 ? (byte_m ? ext_attr : {vga_data_out, attr_data_out} )
172
                     : (byte_m ? ext_buff : {attr_data_out, vga_data_out} );
173
  assign ext_buff   = { {8{vga_data_out[7]}}, vga_data_out };
174
  assign ext_attr   = { {8{attr_data_out[7]}}, attr_data_out };
175
 
176
  assign vga_cs     = 1'b1;
177
 
178
  // Old control registers
179
  assign reg_hcursor = 7'b0;
180
  assign reg_vcursor = 5'd0;
181
  assign reg_voffset = 5'd0;
182
 
183
  assign fg_or_bg    = vga_shift[7] ^ cursor_on;
184
 
185
  // Behaviour
186
  // vga clock generation
187
  always @(negedge vdu_clk_in)
188
    /* if (vdu_rst) clk_count <= 2'b00;
189
    else */ clk_count <= clk_count + 2'b01;
190
 
191
  // For simulation
192
  initial clk_count <= 2'b00;
193
 
194
  // CPU write interface
195
  always @(negedge vdu_clk)
196
    if (vdu_rst)
197
      begin
198
        attr0_addr    <= 11'b0;
199
        attr0_we      <= 1'b1;
200
        attr_data_in  <= 8'h0;
201
        buff0_addr    <= 11'b0;
202
        buff0_we      <= 1'b1;
203
        buff_data_in  <= 8'h0;
204
      end
205
    else
206
      begin
207
        if (vdu_cs && ready)
208
          begin
209
            attr0_addr   <= vdu_addr[11:1];
210
            attr0_we     <= vdu_we | (byte1 & ~a0);
211
            attr_data_in <= a0 ? wr_data[7:0] : wr_data[15:8];
212
            buff0_addr   <= (a0 && !byte1) ? vdu_addr1 : vdu_addr[11:1];
213
            buff0_we     <= vdu_we | (byte1 & a0);
214
            buff_data_in <= a0 ? wr_data[15:8] : wr_data[7:0];
215
          end
216
      end
217
 
218
  always @(negedge cpu_clk_out)
219
    if (vdu_rst)
220
      begin
221
        req_write <= 1'b0;
222
        req_read  <= 1'b0;
223
        one_more_cycle <= 1'b0;
224
      end
225
    else
226
      begin
227
        if (vdu_cs && !vdu_we && ready) req_write <= 1'b1;
228
        else if (req_write && !vga2_we) req_write <= 1'b0;
229
        if (vdu_cs && vdu_we)
230
          begin
231
            if (ready)
232
              begin
233
                req_read <= 1'b1;
234
                if (vga2_rw) one_more_cycle <= 1'b1;
235
                else one_more_cycle <= 1'b0;
236
              end
237
            else
238
              if (req_read && vga4_rw)
239
                begin
240
                  if (one_more_cycle) one_more_cycle <= 1'b0;
241
                  else req_read <= 1'b0;
242
                end
243
          end
244
      end
245
 
246
  // Sync generation & timing process
247
  // Generate horizontal and vertical timing signals for video signal
248
  always @(negedge vdu_clk)
249
    if (vdu_rst)
250
      begin
251
        h_count     <= 10'b0;
252
        horiz_sync  <= 1'b1;
253
        v_count     <= 9'b0;
254
        vert_sync   <= 1'b1;
255
        video_on_h  <= 1'b1;
256
        video_on_v  <= 1'b1;
257
        cursor_on_h <= 1'b0;
258
        cursor_on_v <= 1'b0;
259
        blink_count <= 22'b0;
260
      end
261
    else
262
      begin
263
        h_count    <= (h_count==HOR_SCAN_END) ? 10'b0 : h_count + 10'b1;
264
        horiz_sync <= (h_count==HOR_SYNC_BEG) ? 1'b0
265
                    : ((h_count==HOR_SYNC_END) ? 1'b1 : horiz_sync);
266
        v_count    <= (v_count==VER_SCAN_END && h_count==HOR_SCAN_END) ? 9'b0
267
                    : ((h_count==HOR_SYNC_END) ? v_count + 9'b1 : v_count);
268
        vert_sync  <= (v_count==VER_SYNC_BEG) ? 1'b0
269
                    : ((v_count==VER_SYNC_END) ? 1'b1 : vert_sync);
270
        video_on_h <= (h_count==HOR_SCAN_END) ? 1'b1
271
                    : ((h_count==HOR_DISP_END) ? 1'b0 : video_on_h);
272
        video_on_v <= (v_count==VER_SYNC_BEG) ? 1'b1
273
                    : ((v_count==VER_DISP_END) ? 1'b0 : video_on_v);
274
        cursor_on_h <= (h_count[9:3] == reg_hcursor[6:0]);
275
        cursor_on_v <= (v_count[8:4] == reg_vcursor[4:0]);
276
        blink_count <= blink_count + 22'd1;
277
      end
278
 
279
  // Video memory access
280
  always @(negedge vdu_clk)
281
    if (vdu_rst)
282
      begin
283
        vga0_we <= 1'b0;
284
        vga0_rw <= 1'b1;
285
        row_addr <= 5'b0;
286
        col_addr <= 7'b0;
287
 
288
        vga1_we  <= 1'b0;
289
        vga1_rw  <= 1'b1;
290
        row1_addr <= 5'b0;
291
        col1_addr <= 7'b0;
292
 
293
        vga2_we  <= 1'b0;
294
        vga2_rw  <= 1'b0;
295
        vga3_rw  <= 1'b0;
296
        vga4_rw  <= 1'b0;
297
        ver_addr <= 7'b0;
298
        hor_addr <= 7'b0;
299
 
300
        buff_addr <= 10'b0;
301
        attr_addr <= 10'b0;
302
        buff_we   <= 1'b1;
303
        attr_we   <= 1'b1;
304
 
305
        rd_data   <= 16'd0;
306
      end
307
    else
308
      begin
309
        // on h_count = 0 initiate character write
310
        // all other cycles are reads
311
        case (h_count[2:0])
312
          3'b000:   // pipeline character write
313
            begin
314
              vga0_we <= !req_write;
315
              vga0_rw <= 1'b1;
316
            end
317
          default:  // other 6 cycles free
318
            begin
319
              vga0_we <= 1'b1;
320
              vga0_rw <= 1'b0;
321
              col_addr <= h_count[9:3];
322
              row_addr <= v_count[8:4] + reg_voffset[4:0];
323
            end
324
        endcase
325
 
326
        // on vdu_clk + 1 round off row address
327
        // row1_addr = (row_addr % 80)
328
        vga1_we <= vga0_we;
329
        vga1_rw <= vga0_rw;
330
        row1_addr <= (row_addr < VER_DISP_CHR) ? row_addr
331
                    : row_addr - VER_DISP_CHR;
332
        col1_addr <= col_addr;
333
 
334
        // on vdu_clk + 2 calculate vertical address
335
        // ver_addr = (row_addr % 80) x 5
336
        vga2_we <= vga1_we;
337
        vga2_rw <= vga1_rw;
338
        ver_addr <= { 2'b00, row1_addr } + { row1_addr, 2'b00 }; // x5
339
        hor_addr <= col1_addr;
340
 
341
        // on vdu_clk + 3 calculate memory address
342
        // vga_addr = (row_addr % 80) * 80 + hor_addr
343
        buff_addr <= vga2_rw ? buff0_addr : vga_addr;
344
        attr_addr <= vga2_rw ? attr0_addr : vga_addr;
345
        buff_we   <= vga2_rw ? (buff0_we | vga2_we) : 1'b1;
346
        attr_we   <= vga2_rw ? (attr0_we | vga2_we) : 1'b1;
347
        vga3_rw   <= vga2_rw;
348
 
349
        rd_data   <= vga3_rw ? out_data : rd_data;
350
        vga4_rw   <= vga3_rw;
351
      end
352
 
353
  // Video shift register
354
  always @(negedge vdu_clk)
355
    if (vdu_rst)
356
      begin
357
        video_on      = 1'b0;
358
        cursor_on     = 1'b0;
359
        vga_bg_colour = 3'b000;
360
        vga_fg_colour = 3'b111;
361
        vga_shift     = 8'b00000000;
362
        vga_red_o     = 1'b0;
363
        vga_green_o   = 1'b0;
364
        vga_blue_o    = 1'b0;
365
      end
366
    else
367
      begin
368
        if (h_count[2:0] == 3'b000)
369
          begin
370
            video_on  = video_on1;
371
            cursor_on = (cursor_on1 | attr_data_out[3]) & blink_count[22];
372
            vga_fg_colour = attr_data_out[2:0];
373
            vga_bg_colour = attr_data_out[6:4];
374
            if (!attr_data_out[7]) vga_shift = char_data_out;
375
            else
376
              case (v_count[3:2])
377
                2'b00: vga_shift = { {4{vga_data_out[0]}}, {4{vga_data_out[1]}} };
378
                2'b01: vga_shift = { {4{vga_data_out[2]}}, {4{vga_data_out[3]}} };
379
                2'b10: vga_shift = { {4{vga_data_out[4]}}, {4{vga_data_out[5]}} };
380
                default: vga_shift = { {4{vga_data_out[6]}}, {4{vga_data_out[7]}} };
381
              endcase
382
          end
383
        else vga_shift = { vga_shift[6:0], 1'b0 };
384
 
385
        //
386
        // Colour mask is
387
        //  7  6  5  4  3  2  1  0
388
        //  X BG BB BR  X FG FB FR
389
        //
390
        vga_red_o    = fg_or_bg ? video_on & vga_fg_colour[0]
391
                                : video_on & vga_bg_colour[0];
392
        vga_green_o  = fg_or_bg ? video_on & vga_fg_colour[1]
393
                                : video_on & vga_bg_colour[1];
394
        vga_blue_o   = fg_or_bg ? video_on & vga_fg_colour[2]
395
                                : video_on & vga_bg_colour[2];
396
      end
397
endmodule

powered by: WebSVN 2.1.0

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