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

Subversion Repositories System09

[/] [System09/] [trunk/] [rtl/] [VHDL/] [vdu8_new.vhd] - Blame information for rev 101

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

Line No. Rev Author Line
1 65 davidgb
-- ---------------------------------------------------
2
-- Video Display terminal
3
-- ---------------------------------------------------
4
-- John Kent
5
-- 3th September 2004
6
-- Assumes a pixel clock input of 25 MHz
7
--
8
-- Display Format is:
9
-- 80 characters across by 25 characters down.
10
-- 8 horizontal pixels / character
11
-- 16 vertical scan lines / character (2 scan lines/row)
12
--
13
-- Modified by Bert Cuzeau for compliance and code cleanliness
14
-- The effort is not over.
15
-- There are still signal initialized, which is BAD.\
16
--
17
-- 7th Februaury 2007 - John Kent
18
-- Added generics for VGA Timing
19
--
20
 
21
Library IEEE;
22
   use ieee.std_logic_1164.all;
23
   use IEEE.STD_LOGIC_ARITH.ALL;
24
   use IEEE.STD_LOGIC_UNSIGNED.ALL;
25
   use ieee.numeric_std.all;
26
library unisim;
27
   use unisim.vcomponents.all;
28
 
29
Entity vdu8 is
30
  generic(
31
        VDU_CLOCK_FREQUENCY    : integer := 25000000; -- HZ
32
        VGA_CLOCK_FREQUENCY    : integer := 25000000; -- HZ
33
             VGA_HOR_CHARS          : integer := 80; -- CHARACTERS
34
             VGA_VER_CHARS          : integer := 25; -- CHARACTERS
35
             VGA_PIXELS_PER_CHAR    : integer := 8;  -- PIXELS
36
             VGA_LINES_PER_CHAR     : integer := 16; -- LINES
37
             VGA_HOR_BACK_PORCH     : integer := 40; -- PIXELS
38
             VGA_HOR_SYNC           : integer := 96; -- PIXELS
39
             VGA_HOR_FRONT_PORCH    : integer := 24; -- PIXELS
40
             VGA_VER_BACK_PORCH     : integer := 13; -- LINES
41
             VGA_VER_SYNC           : integer := 2;  -- LINES
42
             VGA_VER_FRONT_PORCH    : integer := 36  -- LINES
43
  );
44
  port(
45
    -- control register interface
46
    vdu_clk      : in  std_logic;       -- 12.5/25 MHz CPU Clock
47
    vdu_rst      : in  std_logic;
48
    vdu_cs       : in  std_logic;
49
    vdu_rw       : in  std_logic;
50
    vdu_addr     : in  std_logic_vector(2 downto 0);
51
    vdu_data_in  : in  std_logic_vector(7 downto 0);
52
    vdu_data_out : out std_logic_vector(7 downto 0);
53
 
54
    -- vga port connections
55
    vga_clk      : in  std_logic;       -- 25MHz clock
56
    vga_red_o    : out std_logic;
57
    vga_green_o  : out std_logic;
58
    vga_blue_o   : out std_logic;
59
    vga_hsync_o  : out std_logic;
60
    vga_vsync_o  : out std_logic
61
    );
62
end vdu8;
63
 
64
Architecture RTL of vdu8 is
65
  --
66
  -- Synchronisation constants
67
  --
68
  -- Displayed Characters per row
69
  constant HOR_DISP_CHR : integer := VGA_HOR_CHARS;
70
  -- Last horizontal pixel displayed
71
  constant HOR_DISP_END : integer := HOR_DISP_CHR * VGA_PIXELS_PER_CHAR;
72
  -- Start of horizontal synch pulse
73
  constant HOR_SYNC_BEG : integer := HOR_DISP_END + VGA_HOR_BACK_PORCH;
74
  -- End of Horizontal Synch pulse
75
  constant HOR_SYNC_END : integer := HOR_SYNC_BEG + VGA_HOR_SYNC;
76
  -- Last pixel in scan line
77
  constant HOR_SCAN_END : integer := HOR_SYNC_END + VGA_HOR_FRONT_PORCH;
78
  -- Total Characters across the screen
79
  constant HOR_TOTAL_CHAR : integer := HOR_SCAN_END/VGA_PIXELS_PER_CHAR;
80
 
81
  -- Displayed Characters per Column
82
  constant VER_DISP_CHR   : integer := VGA_VER_CHARS;
83
  -- last row displayed
84
  constant VER_DISP_END   : integer := VER_DISP_CHR * VGA_LINES_PER_CHAR;
85
  -- start of vertical synch pulse
86
  constant VER_SYNC_BEG   : integer := VER_DISP_END + VGA_VER_BACK_PORCH;
87
  -- end of vertical synch pulse
88
  constant VER_SYNC_END   : integer := VER_SYNC_BEG + VGA_VER_SYNC;
89
  -- Last scan row in the frame
90
  constant VER_SCAN_END   : integer := VER_SYNC_END + VGA_VER_FRONT_PORCH;
91
  -- Total Characters down the screen
92
  constant VER_TOTAL_CHAR : integer := VER_SCAN_END/VGA_LINES_PER_CHAR;
93
 
94
  constant BLINK_PERIOD   : integer := 500; -- Blink Rate in msec
95
  constant BLINK_RATE     : integer := BLINK_PERIOD * (VGA_CLOCK_FREQUENCY/1000);
96
 
97
  signal vga_rst       : std_logic;
98
  signal horiz_sync    : std_logic := '0';
99
  signal vert_sync     : std_logic := '0';
100
  signal cursor_on_v   : std_logic := '0';
101
  signal cursor_on_h   : std_logic := '0';
102
  signal video_on_v    : std_logic := '0';
103
  signal video_on_h    : std_logic := '0';
104
  signal h_count       : natural range 0 to HOR_SCAN_END := 0;
105
  signal v_count       : natural range 0 to VER_SCAN_END := 0;
106
  signal p_count       : natural range 0 to VGA_PIXELS_PER_CHAR-1 := 0;
107
  signal l_count       : std_logic_vector(3 downto 0) := "0000";
108
  signal c_count       : std_logic_vector(6 downto 0) := "0000000";
109
  signal r_count       : std_logic_vector(5 downto 0) := "000000";
110
  signal blink_count   : natural range 0 to BLINK_RATE := 0;
111
  --
112
  -- Character generator ROM
113
  --
114
  signal char_addr     : std_logic_vector(10 downto 0);
115
  signal char_data_out : std_logic_vector(7 downto 0);
116
 
117
  --
118
  -- Control Registers
119
  --
120
  signal reg_character : std_logic_vector(7 downto 0);
121
  signal reg_colour    : std_logic_vector(7 downto 0);
122
  signal reg_hcursor   : std_logic_vector(6 downto 0);   -- 80 columns
123
  signal reg_vcursor   : std_logic_vector(4 downto 0);   -- 25 rows
124
  signal reg_voffset   : std_logic_vector(4 downto 0);   -- 25 rows
125
  --
126
  -- Video Shift register
127
  --
128
  signal vga_shift     : std_logic_vector(7 downto 0);
129
  signal vga_fg_colour : std_logic_vector(2 downto 0);
130
  signal vga_bg_colour : std_logic_vector(2 downto 0);
131
  signal cursor_on     : std_logic := '0';
132
  signal cursor_on1    : std_logic := '0';
133
  signal video_on      : std_logic := '0';
134
  signal video_on1     : std_logic := '0';
135
  signal video_on2     : std_logic := '0';
136
  --
137
  -- vga character ram access bus
138
  --
139
  signal col_addr      : std_logic_vector(6 downto 0) := (others=>'0'); -- 0 to 79
140
  signal row_addr      : std_logic_vector(5 downto 0) := (others=>'0'); -- 0 to 49 (25 * 2 -1)
141
  signal col1_addr     : std_logic_vector(6 downto 0) := (others=>'0'); -- 0 to 79
142
  signal row1_addr     : std_logic_vector(5 downto 0) := (others=>'0'); -- 0 to 49 (25 * 2 - 1)
143
  signal hor_addr      : std_logic_vector(6 downto 0) := (others=>'0'); -- 0 to 79
144
  signal ver_addr      : std_logic_vector(6 downto 0) := (others=>'0'); -- 0 to 124
145
  signal vga0_cs       : std_logic;
146
  signal vga0_rw       : std_logic;
147
  signal vga1_cs       : std_logic;
148
  signal vga1_rw       : std_logic;
149
  signal vga2_cs       : std_logic;
150
  signal vga2_rw       : std_logic;
151
  signal vga_cs        : std_logic;
152
  signal vga_rw        : std_logic;
153
  signal vga_addr      : std_logic_vector(10 downto 0) := (others=>'0');  -- 2K byte character buffer
154
  signal vga_data_out  : std_logic_vector(7 downto 0);
155
  signal attr_data_out : std_logic_vector(7 downto 0);
156
 
157
  --
158
  -- Character write handshake signals
159
  --
160
  signal req_write     : std_logic;     -- request character write
161
  signal ack_write     : std_logic;
162
 
163
  --
164
  -- Block Ram Character gen
165
  --
166
  component char_rom
167
    port (
168
      clk   : in  std_logic;
169
      rst   : in  std_logic;
170
      cs    : in  std_logic;
171
      rw    : in  std_logic;
172
      addr  : in  std_logic_vector (10 downto 0);
173
      wdata : in std_logic_vector (7 downto 0);
174
      rdata : out std_logic_vector (7 downto 0)
175
      );
176
  end component;
177
 
178
  component ram_2k
179
    port (
180
      clk   : in  std_logic;
181
      rst   : in  std_logic;
182
      cs    : in  std_logic;
183
      rw    : in  std_logic;
184
      addr  : in  std_logic_vector (10 downto 0);
185
      wdata : in  std_logic_vector (7 downto 0);
186
      rdata : out std_logic_vector (7 downto 0)
187
      );
188
  end component;
189
 
190
begin
191
 
192
--
193
-- instantiate Character generator ROM
194
--
195
vdu_char_rom : char_rom port map(
196
    clk   => vga_clk,
197
         rst   => vga_rst,
198
         cs    => '1',
199
         rw    => '1',
200
    addr  => char_addr,
201
    wdata => "00000000",
202
    rdata => char_data_out
203
    );
204
 
205
--
206
-- Character buffer RAM
207
--
208
char_buff_ram : ram_2k port map(
209
    clk   => vga_clk,
210
    rst   => vga_rst,
211
    cs    => vga_cs,
212
    rw    => vga_rw,
213
    addr  => vga_addr,
214
    wdata => reg_character,
215
    rdata => vga_data_out
216
    );
217
 
218
--
219
-- Attribute buffer RAM
220
--
221
  attr_buff_ram : ram_2k port map(
222
    clk   => vga_clk,
223
    rst   => vga_rst,
224
    cs    => vga_cs,
225
    rw    => vga_rw,
226
    addr  => vga_addr,
227
    wdata => reg_colour,
228
    rdata => attr_data_out
229
    );
230
 
231
--
232
-- CPU Write interface
233
--
234
  vga_cpu_write : process(vdu_clk, vdu_rst)
235
  begin
236
    if vdu_rst = '1' then
237
      reg_character <= "00000000";
238
      reg_colour    <= "00000111";
239
      reg_hcursor   <= "0000000";
240
      reg_vcursor   <= "00000";
241
      reg_voffset   <= "00000";
242
      req_write     <= '0';
243
 
244
    elsif falling_edge(vdu_clk) then
245
      if (vdu_cs = '1') and (vdu_rw = '0') then
246
        case vdu_addr is
247
          when "000" =>
248
            reg_character <= vdu_data_in;
249
            req_write     <= '1';
250
          when "001" =>
251
            reg_colour    <= vdu_data_in;
252
          when "010" =>
253
            reg_hcursor   <= vdu_data_in(6 downto 0);
254
          when "011" =>
255
            reg_vcursor   <= vdu_data_in(4 downto 0);
256
          when others =>
257
            reg_voffset   <= vdu_data_in(4 downto 0);
258
        end case;
259
      else
260
 
261
        if (req_write = '1') and (ack_write = '1') then
262
          req_write <= '0';
263
        else
264
          req_write <= req_write;
265
        end if;
266
 
267
      end if;
268
    end if;
269
  end process;
270
  --
271
  -- CPU Read interface
272
  --
273
  vga_cpu_read : process(vdu_addr, vdu_cs,
274
                         reg_character, reg_colour,
275
                         reg_hcursor, reg_vcursor, reg_voffset)
276
  begin
277
    case vdu_addr is
278
      when "000" =>
279
        vdu_data_out <= reg_character;
280
      when "001" =>
281
        vdu_data_out <= reg_colour;
282
      when "010" =>
283
        vdu_data_out <= "0" & reg_hcursor;
284
      when "011" =>
285
        vdu_data_out <= "000" & reg_vcursor;
286
      when others =>
287
        vdu_data_out <= "000" & reg_voffset;
288
    end case;
289
  end process;
290
 
291
  --
292
  -- Video memory access
293
  --
294
  vga_addr_proc : process(vga_clk, vga_rst)
295
  begin
296
 
297
    if vga_rst = '1' then
298
      vga0_cs   <= '0';
299
      vga0_rw   <= '1';
300
      row_addr  <= "000000";
301
      col_addr  <= "0000000";
302
      --
303
      vga1_cs   <= '0';
304
      vga1_rw   <= '1';
305
      row1_addr <= "000000";
306
      col1_addr <= "0000000";
307
      --
308
      vga2_cs   <= '0';
309
      vga2_rw   <= '1';
310
      ver_addr  <= "0000000";
311
      hor_addr  <= "0000000";
312
      --
313
      vga_cs    <= '0';
314
      vga_rw    <= '1';
315
      vga_addr  <= "00000000000";
316
 
317
    elsif falling_edge(vga_clk) then
318
      --
319
      -- on h_count = 0 initiate character write.
320
      -- all other cycles are reads.
321
      --
322
      case p_count is
323
        when 0 =>                   -- pipeline character write
324
          vga0_cs  <= req_write;
325
          vga0_rw  <= '0';
326
          col_addr <= reg_hcursor(6 downto 0);
327
          row_addr <= ("0" & reg_vcursor(4 downto 0)) + ("0" & reg_voffset(4 downto 0));
328
        when others =>                  -- other 7 cycles free
329
          vga0_cs  <= '1';
330
          vga0_rw  <= '1';
331
          col_addr <= c_count;
332
          row_addr <= r_count + ("0" & reg_voffset(4 downto 0));
333
      end case;
334
 
335
      --
336
      -- on vga_clk + 1 round off row address
337
      --
338
      vga1_cs <= vga0_cs;
339
      vga1_rw <= vga0_rw;
340
      if row_addr < VER_DISP_CHR then
341
        row1_addr <= row_addr;
342
      else
343
        row1_addr <= row_addr - VER_DISP_CHR;
344
      end if;
345
      col1_addr <= col_addr;
346
      --
347
      -- on vga_clk + 2 calculate vertical address
348
      --
349
      vga2_cs   <= vga1_cs;
350
      vga2_rw   <= vga1_rw;
351
      ver_addr  <= ("00" & row1_addr(4 downto 0)) + (row1_addr(4 downto 0) & "00");
352
      hor_addr  <= col1_addr;
353
      --
354
      -- on vga_clk + 3 calculate memory address
355
      --
356
      vga_cs    <= vga2_cs;
357
      vga_rw    <= vga2_rw;
358
      vga_addr  <= ("0000" & hor_addr) + (ver_addr & "0000");
359
    end if;
360
  end process;
361
--
362
-- Video shift register
363
--
364
  vga_shift_proc : process( vga_clk, vga_rst)
365
  begin
366
    if vga_rst = '1' then
367
      ack_write     <= '0';
368
      video_on2     <= '0';
369
      video_on      <= '0';
370
      cursor_on     <= '0';
371
      vga_bg_colour <= "000";
372
      vga_fg_colour <= "111";
373
      vga_shift     <= "00000000";
374
      vga_red_o     <= '0';
375
      vga_green_o   <= '0';
376
      vga_blue_o    <= '0';
377
      -- Put all video signals through DFFs to elminate any delays that cause a blurry image
378
 
379
    elsif falling_edge(vga_clk) then
380
           --
381
      -- p_count = 0 load pixel shift register
382
                --
383
      if p_count = 0 then
384
        if (req_write = '1') and (ack_write = '0') then
385
          ack_write <= '1';
386
        elsif (req_write = '0') and (ack_write = '1') then
387
          ack_write <= '0';
388
        else
389
          ack_write <= ack_write;
390
        end if;
391
 
392
                  --
393
                  -- Pipeline video enable
394
                  --
395
        video_on2     <= video_on1;
396
        video_on      <= video_on2;
397
                  --
398
                  -- Blink Cursor
399
                  --
400
                  if blink_count > (BLINK_RATE/2) then
401
           cursor_on  <= cursor_on1 or attr_data_out(3);
402
        else
403
                     cursor_on  <= '0';
404
        end if;
405
                  --
406
                  -- Set forground and background colours
407
                  --
408
        vga_fg_colour <= attr_data_out(2 downto 0);
409
        vga_bg_colour <= attr_data_out(6 downto 4);
410
                  --
411
                  -- Attribute bit 7
412
                  --   0 => text
413
                  --   1 => chunky graphics
414
                  --
415
        if attr_data_out(7) = '0' then
416
          vga_shift <= char_data_out;
417
        else
418
          case l_count(3 downto 2) is
419
            when "00" =>
420
              vga_shift(7 downto 4) <= vga_data_out(0) & vga_data_out(0) & vga_data_out(0) & vga_data_out(0);
421
              vga_shift(3 downto 0) <= vga_data_out(1) & vga_data_out(1) & vga_data_out(1) & vga_data_out(1);
422
            when "01" =>
423
              vga_shift(7 downto 4) <= vga_data_out(2) & vga_data_out(2) & vga_data_out(2) & vga_data_out(2);
424
              vga_shift(3 downto 0) <= vga_data_out(3) & vga_data_out(3) & vga_data_out(3) & vga_data_out(3);
425
            when "10" =>
426
              vga_shift(7 downto 4) <= vga_data_out(4) & vga_data_out(4) & vga_data_out(4) & vga_data_out(4);
427
              vga_shift(3 downto 0) <= vga_data_out(5) & vga_data_out(5) & vga_data_out(5) & vga_data_out(5);
428
            when others =>
429
              vga_shift(7 downto 4) <= vga_data_out(6) & vga_data_out(6) & vga_data_out(6) & vga_data_out(6);
430
              vga_shift(3 downto 0) <= vga_data_out(7) & vga_data_out(7) & vga_data_out(7) & vga_data_out(7);
431
          end case;
432
        end if;
433
      else
434
                  --
435
                  -- p_count /= 0 shift out pixel shift register
436
                  --
437
        vga_shift <= vga_shift(6 downto 0) & '0';
438
      end if;
439
 
440
      --
441
      -- Colour mask is
442
      --  7  6  5  4  3  2  1  0
443
      --  X BG BB BR  X FG FB FR
444
      --
445
      if vga_shift(7) = (not cursor_on) then
446
        vga_red_o   <= video_on and vga_fg_colour(0);
447
        vga_green_o <= video_on and vga_fg_colour(1);
448
        vga_blue_o  <= video_on and vga_fg_colour(2);
449
      else
450
        vga_red_o   <= video_on and vga_bg_colour(0);
451
        vga_green_o <= video_on and vga_bg_colour(1);
452
        vga_blue_o  <= video_on and vga_bg_colour(2);
453
      end if;
454
    end if;
455
  end process;
456
 
457
 
458
--
459
-- Sync generator & timing process
460
-- Generate Horizontal and Vertical Timing Signals for Video Signal
461
--
462
  vga_sync : process(vga_clk, vga_rst)
463
  begin
464
    if vga_rst = '1' then
465
        h_count     <= 0;
466
                  c_count     <= "0000000";
467
                  p_count     <= 0;
468
        v_count     <= 0;
469
                  l_count     <= "0000";
470
                  r_count     <= "000000";
471
        horiz_sync  <= '0';
472
        vert_sync   <= '0';
473
        video_on_h  <= '0';
474
        video_on_v  <= '0';
475
        cursor_on_h <= '0';
476
        cursor_on_v <= '0';
477
                  blink_count <= BLINK_RATE;
478
    elsif falling_edge(vga_clk) then
479
      --
480
      -- H_count counts pixels (640 + extra time for sync signals)
481
      --
482
      --  Horiz_sync  -----------------------------__________--------
483
      --  H_count       0                640      659       755    799
484
      --
485
      if h_count = HOR_SCAN_END then
486
        h_count <= 0;
487
                  c_count <= "0000000";
488
                  p_count <= 0;
489
      else
490
        h_count <= h_count + 1;
491
                  p_count <= p_count + 1;
492
                  if p_count = VGA_PIXELS_PER_CHAR-1 then
493
                    p_count <= 0;
494
                    c_count <= c_count + "0000001";
495
                  end if;
496
      end if;
497
 
498
      --
499
      -- V_count counts rows of pixels
500
      -- 400 lines + extra time for sync signals
501
      -- 25 rows * 16 scan lines
502
      --
503
      --  Vert_sync      ---------------------------------_______------------
504
      --  V_count         0                       400    413     414        444
505
      --
506
      if (v_count = VER_SCAN_END) and (h_count = HOR_SCAN_END) then
507
        v_count <= 0;
508
                  l_count <= "0000";
509
                  r_count <= "000000";
510
      elsif h_count = HOR_SYNC_END then
511
        v_count <= v_count + 1;
512
        l_count <= l_count + "0001";
513
                  if l_count = VGA_LINES_PER_CHAR-1 then
514
                    l_count <= "0000";
515
                    r_count <= r_count + "000001";
516
                  end if;
517
      end if;
518
 
519
      --
520
      -- Generate Horizontal Sync Signal
521
      --
522
      if h_count = HOR_SYNC_BEG then
523
        horiz_sync <= '1';
524
      elsif h_count = HOR_SYNC_END then
525
        horiz_sync <= '0';
526
      end if;
527
 
528
      --
529
      -- Generate Vertical Sync Signal
530
      --
531
      if v_count = VER_SYNC_BEG then
532
        vert_sync <= '1';
533
      elsif v_count = VER_SYNC_END then
534
        vert_sync <= '0';
535
      end if;
536
 
537
                --
538
      -- Horizontal display enable
539
                --
540
      if h_count = 0 then
541
        video_on_h <= '1';
542
      elsif h_count = HOR_DISP_END then
543
        video_on_h <= '0';
544
      end if;
545
 
546
                --
547
      -- Verical display enable
548
                --
549
      if v_count = 0 then
550
        video_on_v <= '1';
551
      elsif v_count = VER_DISP_END then
552
        video_on_v <= '0';
553
      end if;
554
 
555
                --
556
                -- Horizontal cursor on
557
                --
558
      if c_count = reg_hcursor(6 downto 0) then
559
        cursor_on_h <= '1';
560
      else
561
        cursor_on_h <= '0';
562
      end if;
563
 
564
                --
565
                -- Vertical cursor on
566
                --
567
      if r_count = ("0" & reg_vcursor(4 downto 0)) then
568
        cursor_on_v <= '1';
569
      else
570
        cursor_on_v <= '0';
571
      end if;
572
 
573
      -- cursor_on is only active when on selected character
574
                if blink_count = 0 then
575
                  blink_count <= BLINK_RATE;
576
                else
577
        blink_count <= blink_count - 1;
578
      end if;
579
    end if;
580
 
581
  end process;
582
  --
583
  -- VGA reset = VDU reset
584
  -- VGA = timing section
585
  -- VDU = CPU registers
586
  --
587
  vga_rst <= vdu_rst;
588
  --
589
  -- VGA Sync for 640 pixels x 400 lines
590
  -- negative horizonal sync
591
  -- positive verical sync
592
  --
593
  vga_hsync_o <= not horiz_sync;
594
  vga_vsync_o <= vert_sync;
595
  --
596
  -- video_on is high only when RGB data is displayed
597
  --
598
  video_on1   <= video_on_H and video_on_V;
599
  cursor_on1  <= cursor_on_h and cursor_on_v;
600
 
601
--
602
-- Here to look up character ROM
603
-- This will take one clock cycle
604
-- and should be performed on p_count = "111"
605
--
606
  char_addr(10 downto 4) <= vga_data_out(6 downto 0);
607
  char_addr(3 downto 0)  <= l_count;
608
 
609
end RTL;

powered by: WebSVN 2.1.0

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