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

Subversion Repositories zet86

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

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

Line No. Rev Author Line
1 39 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
    // Wishbone signals
15
    input             wb_clk_i,     // 25 Mhz VDU clock
16
    input             wb_rst_i,
17
    input      [15:0] wb_dat_i,
18
    output reg [15:0] wb_dat_o,
19
    input      [11:1] wb_adr_i,
20
    input             wb_we_i,
21
    input             wb_tga_i,
22
    input      [ 1:0] wb_sel_i,
23
    input             wb_stb_i,
24
    input             wb_cyc_i,
25
    output reg        wb_ack_o,
26
 
27
    // VGA pad signals
28
    output reg [ 1:0] vga_red_o,
29
    output reg [ 1:0] vga_green_o,
30
    output reg [ 1:0] vga_blue_o,
31
    output reg        horiz_sync,
32
    output reg        vert_sync
33
  );
34
 
35
  // Net, registers and parameters
36
 
37
  // Synchronization constants
38
  parameter HOR_DISP_END = 10'd640; // Last horizontal pixel displayed
39
  parameter HOR_SYNC_BEG = 10'd679; // Start of horizontal synch pulse
40
  parameter HOR_SYNC_END = 10'd775; // End of Horizontal Synch pulse
41
  parameter HOR_SCAN_END = 10'd799; // Last pixel in scan line
42
  parameter HOR_DISP_CHR = 80;      // Number of characters displayed per row
43
 
44
  parameter VER_DISP_END = 9'd399;  // last row displayed
45
  parameter VER_SYNC_BEG = 9'd413;  // start of vertical synch pulse
46
  parameter VER_SYNC_END = 9'd414;  // end of vertical synch pulse
47
  parameter VER_SCAN_END = 9'd450;  // Last scan row in the frame
48
  parameter VER_DISP_CHR = 6'd25;   // Number of character rows displayed
49
 
50
  reg        cursor_on_v;
51
  reg        cursor_on_h;
52
  reg        video_on_v;
53
  reg        video_on_h;
54
  reg [9:0]  h_count;
55
  reg [8:0]  v_count;       // 0 to VER_SCAN_END
56
  reg [22:0] blink_count;
57
 
58
  // Character generator ROM
59
  wire        char_cs;
60
  wire        char_we;
61
  wire [11:0] char_addr;
62
  wire [7:0]  char_data_in;
63
  wire [7:0]  char_data_out;
64
 
65
  // Control registers
66
  reg [6:0] reg_hcursor; // 80 columns
67
  reg [4:0] reg_vcursor; // 25 rows
68
 
69
  wire      wr_pos;
70
 
71
  // Video shift register
72
  reg [7:0] vga_shift;
73
  reg [2:0] vga_fg_colour;
74
  reg [2:0] vga_bg_colour;
75
  reg       cursor_on;
76
  wire      cursor_on1;
77
  reg       video_on;
78
  wire      video_on1;
79
 
80
  // vga character ram access bus
81
  reg   [6:0] col_addr;  // 0 to 79
82
  reg   [4:0] row_addr;  // 0 to 49 (25 * 2 -1)
83
  reg   [6:0] col1_addr; // 0 to 79
84
  reg   [4:0] row1_addr; // 0 to 49 (25 * 2 - 1)
85
  reg   [6:0] hor_addr;  // 0 to 79
86
  reg   [6:0] ver_addr;  // 0 to 124
87
  reg         vga0_we;
88
  reg         vga0_rw, vga1_rw, vga2_rw, vga3_rw, vga4_rw;
89
  reg         vga1_we;
90
  reg         vga2_we;
91
  reg         buff_we;
92
  reg   [7:0] buff_data_in;
93
  reg         attr_we;
94
  reg   [7:0] attr_data_in;
95
  reg  [10:0] buff_addr;
96
  reg  [10:0] attr0_addr;
97
  reg         attr0_we;
98
  reg  [10:0] buff0_addr;
99
  reg         buff0_we;
100
  reg  [10:0] attr_addr;
101
  reg         intense;
102
  wire        vga_cs;
103
  wire  [7:0] vga_data_out;
104
  wire  [7:0] attr_data_out;
105
  wire [10:0] vga_addr;  // 2K byte character buffer
106
  wire [15:0] out_data;
107
  wire        fg_or_bg;
108
  wire        stb;
109
  wire        brown_bg;
110
  wire        brown_fg;
111
 
112
  // Module instantiation
113
  char_rom vdu_char_rom (
114
    .clk   (wb_clk_i),
115
    .rst   (wb_rst_i),
116
    .cs    (char_cs),
117
    .we    (char_we),
118
    .addr  (char_addr),
119
    .wdata (char_data_in),
120
    .rdata (char_data_out)
121
  );
122
 
123
  ram_2k char_buff_ram (
124
    .clk   (wb_clk_i),
125
    .rst   (wb_rst_i),
126
    .cs    (vga_cs),
127
    .we    (buff_we),
128
    .addr  (buff_addr),
129
    .wdata (buff_data_in),
130
    .rdata (vga_data_out)
131
  );
132
 
133
  ram_2k_attr attr_buff_ram (
134
    .clk   (wb_clk_i),
135
    .rst   (wb_rst_i),
136
    .cs    (vga_cs),
137
    .we    (attr_we),
138
    .addr  (attr_addr),
139
    .wdata (attr_data_in),
140
    .rdata (attr_data_out)
141
  );
142
 
143
  // Assignments
144
  assign video_on1  = video_on_h && video_on_v;
145
  assign cursor_on1 = cursor_on_h && cursor_on_v;
146
  assign char_cs    = 1'b1;
147
  assign char_we    = 1'b0;
148
  assign char_data_in = 8'b0;
149
  assign char_addr  = { vga_data_out, v_count[3:0] };
150
  assign vga_addr   = { 4'b0, hor_addr} + { ver_addr, 4'b0 };
151
  assign out_data   = {attr_data_out, vga_data_out};
152
 
153
  assign vga_cs     = 1'b1;
154
  assign stb        = wb_stb_i && wb_cyc_i;
155
 
156
  assign fg_or_bg    = vga_shift[7] ^ cursor_on;
157
  assign brown_fg    = (vga_fg_colour==3'd6) && !intense;
158
  assign brown_bg    = (vga_bg_colour==3'd6);
159
 
160
  assign wr_pos = wb_tga_i & wb_stb_i & wb_cyc_i & wb_we_i;
161
 
162
  // Behaviour
163
 
164
  // CPU write interface
165
  always @(posedge wb_clk_i)
166
    if (wb_rst_i)
167
      begin
168
        attr0_addr    <= 11'b0;
169
        attr0_we      <= 1'b0;
170
        attr_data_in  <= 8'h0;
171
        buff0_addr    <= 11'b0;
172
        buff0_we      <= 1'b0;
173
        buff_data_in  <= 8'h0;
174
      end
175
    else
176
      begin
177
        if (stb && !wb_tga_i)
178
          begin
179
            attr0_addr   <= wb_adr_i;
180
            attr0_we     <= wb_we_i & wb_sel_i[1];
181
            attr_data_in <= wb_dat_i[15:8];
182
            buff0_addr   <= wb_adr_i;
183
            buff0_we     <= wb_we_i & wb_sel_i[0];
184
            buff_data_in <= wb_dat_i[7:0];
185
          end
186
      end
187
 
188
  // CPU read interface
189
  always @(posedge wb_clk_i)
190
    if (wb_rst_i)
191
      begin
192
        wb_dat_o <= 16'h0;
193
        wb_ack_o <= 16'h0;
194
      end
195
    else
196
      begin
197
        wb_dat_o <= vga4_rw ? out_data : wb_dat_o;
198
        wb_ack_o <= vga4_rw ? 1'b1 : (wb_ack_o && stb);
199
      end
200
 
201
  // Cursor pos register
202
  always @(posedge wb_clk_i)
203
    {reg_vcursor, reg_hcursor} <= wb_rst_i ? 12'h0
204
      : (wr_pos ? {wb_dat_i[12:8], wb_dat_i[6:0]}
205
                : {reg_vcursor, reg_hcursor});
206
 
207
  // Sync generation & timing process
208
  // Generate horizontal and vertical timing signals for video signal
209
  always @(posedge wb_clk_i)
210
    if (wb_rst_i)
211
      begin
212
        h_count     <= 10'b0;
213
        horiz_sync  <= 1'b1;
214
        v_count     <= 9'b0;
215
        vert_sync   <= 1'b1;
216
        video_on_h  <= 1'b1;
217
        video_on_v  <= 1'b1;
218
        cursor_on_h <= 1'b0;
219
        cursor_on_v <= 1'b0;
220
        blink_count <= 22'b0;
221
      end
222
    else
223
      begin
224
        h_count    <= (h_count==HOR_SCAN_END) ? 10'b0 : h_count + 10'b1;
225
        horiz_sync <= (h_count==HOR_SYNC_BEG) ? 1'b0
226
                    : ((h_count==HOR_SYNC_END) ? 1'b1 : horiz_sync);
227
        v_count    <= (v_count==VER_SCAN_END && h_count==HOR_SCAN_END) ? 9'b0
228
                    : ((h_count==HOR_SYNC_END) ? v_count + 9'b1 : v_count);
229
        vert_sync  <= (v_count==VER_SYNC_BEG) ? 1'b0
230
                    : ((v_count==VER_SYNC_END) ? 1'b1 : vert_sync);
231
        video_on_h <= (h_count==HOR_SCAN_END) ? 1'b1
232
                    : ((h_count==HOR_DISP_END) ? 1'b0 : video_on_h);
233
        video_on_v <= (v_count==VER_SYNC_BEG) ? 1'b1
234
                    : ((v_count==VER_DISP_END) ? 1'b0 : video_on_v);
235
        cursor_on_h <= (h_count[9:3] == reg_hcursor[6:0]);
236
        cursor_on_v <= (v_count[8:2] == { reg_vcursor[4:0], 2'b11 })
237
                    && (v_count[1] ^ v_count[0]);
238
        blink_count <= blink_count + 22'd1;
239
      end
240
 
241
  // Video memory access
242
  always @(posedge wb_clk_i)
243
    if (wb_rst_i)
244
      begin
245
        vga0_we <= 1'b0;
246
        vga0_rw <= 1'b1;
247
        row_addr <= 5'b0;
248
        col_addr <= 7'b0;
249
 
250
        vga1_we  <= 1'b0;
251
        vga1_rw  <= 1'b1;
252
        row1_addr <= 5'b0;
253
        col1_addr <= 7'b0;
254
 
255
        vga2_we  <= 1'b0;
256
        vga2_rw  <= 1'b0;
257
        vga3_rw  <= 1'b0;
258
        vga4_rw  <= 1'b0;
259
        ver_addr <= 7'b0;
260
        hor_addr <= 7'b0;
261
 
262
        buff_addr <= 10'b0;
263
        attr_addr <= 10'b0;
264
        buff_we   <= 1'b0;
265
        attr_we   <= 1'b0;
266
      end
267
    else
268
      begin
269
        // on h_count = 0 initiate character write
270
        // all other cycles are reads
271
        case (h_count[2:0])
272
          3'b000:   // pipeline character write
273
            begin
274
              vga0_we <= wb_we_i;
275
              vga0_rw <= stb;
276
            end
277
          default:  // other 6 cycles free
278
            begin
279
              vga0_we <= 1'b0;
280
              vga0_rw <= 1'b0;
281
              col_addr <= h_count[9:3];
282
              row_addr <= v_count[8:4];
283
            end
284
        endcase
285
 
286
        // on vdu_clk + 1 round off row address
287
        // row1_addr = (row_addr % 80)
288
        vga1_we <= vga0_we;
289
        vga1_rw <= vga0_rw;
290
        row1_addr <= (row_addr < VER_DISP_CHR) ? row_addr
291
                    : row_addr - VER_DISP_CHR;
292
        col1_addr <= col_addr;
293
 
294
        // on vdu_clk + 2 calculate vertical address
295
        // ver_addr = (row_addr % 80) x 5
296
        vga2_we <= vga1_we;
297
        vga2_rw <= vga1_rw;
298
        ver_addr <= { 2'b00, row1_addr } + { row1_addr, 2'b00 }; // x5
299
        hor_addr <= col1_addr;
300
 
301
        // on vdu_clk + 3 calculate memory address
302
        // vga_addr = (row_addr % 80) * 80 + hor_addr
303
        buff_addr <= vga2_rw ? buff0_addr : vga_addr;
304
        attr_addr <= vga2_rw ? attr0_addr : vga_addr;
305
        buff_we   <= vga2_rw ? (buff0_we & vga2_we) : 1'b0;
306
        attr_we   <= vga2_rw ? (attr0_we & vga2_we) : 1'b0;
307
        vga3_rw   <= vga2_rw;
308
        vga4_rw   <= vga3_rw;
309
      end
310
 
311
  // Video shift register
312
  always @(posedge wb_clk_i)
313
    if (wb_rst_i)
314
      begin
315
        video_on      <= 1'b0;
316
        cursor_on     <= 1'b0;
317
        vga_bg_colour <= 3'b000;
318
        vga_fg_colour <= 3'b111;
319
        vga_shift     <= 8'b00000000;
320
        vga_red_o     <= 1'b0;
321
        vga_green_o   <= 1'b0;
322
        vga_blue_o    <= 1'b0;
323
      end
324
    else
325
      begin
326
        if (h_count[2:0] == 3'b000)
327
          begin
328
            video_on      <= video_on1;
329
            cursor_on     <= (cursor_on1 | attr_data_out[7]) & blink_count[22];
330
            vga_fg_colour <= attr_data_out[2:0];
331
            vga_bg_colour <= attr_data_out[6:4];
332
            intense       <= attr_data_out[3];
333
            vga_shift     <= char_data_out;
334
          end
335
        else vga_shift <= { vga_shift[6:0], 1'b0 };
336
 
337
        //
338
        // Colour mask is
339
        //  7  6  5  4  3  2  1  0
340
        //  X BR BG BB  X FR FG FB
341
        //
342
        vga_blue_o   <= video_on ? (fg_or_bg ? { vga_fg_colour[0], intense }
343
                                            : { vga_bg_colour[0], 1'b0 })
344
                                : 2'b0;
345
 
346
        // Green color exception with color brown
347
        // http://en.wikipedia.org/wiki/Color_Graphics_Adapter#With_an_RGBI_monitor
348
        vga_green_o  <= video_on ?
349
           (fg_or_bg ? (brown_fg ? 2'b01 : { vga_fg_colour[1], intense })
350
                     : (brown_bg ? 2'b01 : { vga_bg_colour[1], 1'b0 }))
351
                                : 2'b0;
352
        vga_red_o    <= video_on ? (fg_or_bg ? { vga_fg_colour[2], intense }
353
                                            : { vga_bg_colour[2], 1'b0 })
354
                                : 2'b0;
355
      end
356
endmodule

powered by: WebSVN 2.1.0

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