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

Subversion Repositories System09

[/] [System09/] [rev_86/] [rtl/] [VHDL/] [vdu8_mono.vhd] - Blame information for rev 219

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

Line No. Rev Author Line
1 19 dilbert57
-- ---------------------------------------------------
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
-- 3rd February 2007 - John Kent
18
-- changed vdu_clk to be derived externally from cpu_clk.
19
-- Removed attibute memory for monochrome character only version.
20
--
21
-- 1st July 20007 - John Kent
22
-- Added generics for timing specification.
23
--
24
 
25
Library IEEE;
26
  use IEEE.std_logic_1164.all;
27
  use IEEE.numeric_std.all;
28
library unisim;
29
  use unisim.vcomponents.all;
30
 
31
Entity vdu8_mono is
32
  generic(
33
        VDU_CLOCK_FREQUENCY    : integer := 12500000; -- HZ
34
        VGA_CLOCK_FREQUENCY    : integer := 25000000; -- HZ
35
             VGA_HOR_CHARS          : integer := 80; -- CHARACTERS
36
             VGA_VER_CHARS          : integer := 25; -- CHARACTERS
37
             VGA_PIXELS_PER_CHAR    : integer := 8;  -- PIXELS
38
             VGA_LINES_PER_CHAR     : integer := 16; -- LINES
39
             VGA_HOR_BACK_PORCH     : integer := 40; -- PIXELS
40
             VGA_HOR_SYNC           : integer := 96; -- PIXELS
41
             VGA_HOR_FRONT_PORCH    : integer := 24; -- PIXELS
42
             VGA_VER_BACK_PORCH     : integer := 13; -- LINES
43
             VGA_VER_SYNC           : integer := 1;  -- LINES
44
             VGA_VER_FRONT_PORCH    : integer := 36  -- LINES
45
  );
46
  port(
47
    -- control register interface
48
    vdu_clk      : in  std_logic;       -- 12.5/25 MHz CPU Clock
49
    vdu_rst      : in  std_logic;
50
    vdu_cs       : in  std_logic;
51
    vdu_rw       : in  std_logic;
52
    vdu_addr     : in  std_logic_vector(2 downto 0);
53
    vdu_data_in  : in  std_logic_vector(7 downto 0);
54
    vdu_data_out : out std_logic_vector(7 downto 0);
55
 
56
    -- vga port connections
57
    vga_clk      : in  std_logic;       -- 25MHz clock
58
    vga_red_o    : out std_logic;
59
    vga_green_o  : out std_logic;
60
    vga_blue_o   : out std_logic;
61
    vga_hsync_o  : out std_logic;
62
    vga_vsync_o  : out std_logic
63
    );
64
end vdu8_mono;
65
 
66
Architecture RTL of vdu8_mono is
67
 
68
  --
69
  -- Synchronisation constants
70
  --
71
  -- Displayed Characters per row
72
  constant HOR_DISP_CHR : integer := VGA_HOR_CHARS;
73
  -- Last horizontal pixel displayed
74
  constant HOR_DISP_END : integer := (HOR_DISP_CHR * VGA_PIXELS_PER_CHAR) - 1;
75
  -- Start of horizontal synch pulse
76
  constant HOR_SYNC_BEG : integer := HOR_DISP_END + VGA_HOR_BACK_PORCH;
77
  -- End of Horizontal Synch pulse
78
  constant HOR_SYNC_END : integer := HOR_SYNC_BEG + VGA_HOR_SYNC;
79
  -- Last pixel in scan line
80
  constant HOR_SCAN_END : integer := HOR_SYNC_END + VGA_HOR_FRONT_PORCH;
81
 
82
  -- Displayed Characters per Column
83
  constant VER_DISP_CHR : integer := VGA_VER_CHARS;
84
  -- last row displayed
85
  constant VER_DISP_END : integer := (VER_DISP_CHR * VGA_LINES_PER_CHAR) - 1;
86
  -- start of vertical synch pulse
87
  constant VER_SYNC_BEG : integer := VER_DISP_END + VGA_VER_BACK_PORCH;
88
  -- end of vertical synch pulse
89
  constant VER_SYNC_END : integer := VER_SYNC_BEG + VGA_VER_SYNC;
90
  -- Last scan row in the frame
91
  constant VER_SCAN_END : integer := VER_SYNC_END + VGA_VER_FRONT_PORCH;
92
 
93
  signal horiz_sync    : std_logic := '1';
94
  signal vert_sync     : std_logic := '1';
95
  signal cursor_on_v   : std_logic;
96
  signal cursor_on_h   : std_logic;
97
  signal video_on_v    : std_logic := '0';
98
  signal video_on_h    : std_logic := '0';
99
  signal h_count       : std_logic_vector(9 downto 0) := (others=>'0');
100
  signal v_count       : std_logic_vector(8 downto 0) := (others=>'0');  -- 0 to VER_SCAN_END
101
  signal blink_count   : std_logic_vector(22 downto 0):= (others=>'1');
102
  --
103
  -- Character generator ROM
104
  --
105
  signal char_addr     : std_logic_vector(10 downto 0);
106
  signal char_data_out : std_logic_vector(7 downto 0);
107
 
108
  --
109
  -- Control Registers
110
  --
111
  signal reg_character : std_logic_vector(7 downto 0);
112
  signal reg_colour    : std_logic_vector(7 downto 0);
113
  signal reg_hcursor   : std_logic_vector(6 downto 0);   -- 80 columns
114
  signal reg_vcursor   : std_logic_vector(4 downto 0);   -- 25 rows
115
  signal reg_voffset   : std_logic_vector(4 downto 0);   -- 25 rows
116
  --
117
  -- Video Shift register
118
  --
119
  signal vga_shift     : std_logic_vector(7 downto 0);
120
  signal cursor_on     : std_logic;
121
  signal cursor_on1    : std_logic;
122
  signal video_on      : std_logic := '0';
123
  signal video_on1     : std_logic := '0';
124
  signal video_on2     : std_logic := '0';
125
  --
126
  -- vga character ram access bus
127
  --
128
  signal col_addr      : std_logic_vector(6 downto 0) := (others=>'0'); -- 0 to 79
129
  signal row_addr      : unsigned(5 downto 0)         := (others=>'0'); -- 0 to 49 (25 * 2 -1)
130
  signal col1_addr     : std_logic_vector(6 downto 0) := (others=>'0'); -- 0 to 79
131
  signal row1_addr     : unsigned(5 downto 0)         := (others=>'0'); -- 0 to 49 (25 * 2 - 1)
132
  signal hor_addr      : std_logic_vector(6 downto 0) := (others=>'0'); -- 0 to 79
133
  signal ver_addr      : std_logic_vector(6 downto 0) := (others=>'0'); -- 0 to 124
134
  signal vga0_cs       : std_logic;
135
  signal vga0_rw       : std_logic;
136
  signal vga1_cs       : std_logic;
137
  signal vga1_rw       : std_logic;
138
  signal vga2_cs       : std_logic;
139
  signal vga2_rw       : std_logic;
140
  signal vga_cs        : std_logic;
141
  signal vga_rw        : std_logic;
142
  signal vga_addr      : std_logic_vector(10 downto 0) := (others=>'0');  -- 2K byte character buffer
143
  signal vga_data_out  : std_logic_vector(7 downto 0);
144
  --
145
  -- Character write handshake signals
146
  --
147
  signal req_write     : std_logic;     -- request character write
148
  signal ack_write     : std_logic;
149
 
150
  --
151
  -- Block Ram Character gen
152
  --
153
  component char_rom
154
    port (
155
      clk   : in  std_logic;
156
      rst   : in  std_logic;
157
      cs    : in  std_logic;
158
      rw    : in  std_logic;
159
      addr  : in  std_logic_vector (10 downto 0);
160
      wdata : in std_logic_vector (7 downto 0);
161
      rdata : out std_logic_vector (7 downto 0)
162
      );
163
  end component;
164
 
165
  component ram_2k
166
    port (
167
      clk   : in  std_logic;
168
      rst   : in  std_logic;
169
      cs    : in  std_logic;
170
--      r_wn  : 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
begin
179
 
180
--
181
-- instantiate Character generator ROM
182
--
183
vdu_char_rom : char_rom port map(
184
    clk   => vga_clk,
185
         rst   => vdu_rst,
186
         cs    => '1',
187
         rw    => '1',
188
    addr  => char_addr,
189
    wdata => "00000000",
190
    rdata => char_data_out
191
    );
192
 
193
--
194
-- Character buffer RAM
195
--
196
char_buff_ram : ram_2k port map(
197
    clk   => vga_clk,
198
    rst   => vdu_rst,
199
    cs    => vga_cs,
200
--    r_wn  => vga_rw,
201
    rw    => vga_rw,
202
    addr  => vga_addr,
203
    wdata => reg_character,
204
    rdata => vga_data_out
205
    );
206
 
207
--
208
-- CPU Write interface
209
--
210
  vga_cpu_write : process(vdu_clk, vdu_rst)
211
  begin
212
    if vdu_rst = '1' then
213
      reg_character <= "00000000";
214
      reg_colour    <= "00000111";
215
      reg_hcursor   <= "0000000";
216
      reg_vcursor   <= "00000";
217
      reg_voffset   <= "00000";
218
      req_write     <= '0';
219
 
220
    elsif vdu_clk'event and vdu_clk = '0' then
221
      if (vdu_cs = '1') and (vdu_rw = '0') then
222
        case vdu_addr is
223
          when "000" =>
224
            reg_character <= vdu_data_in;
225
            req_write     <= '1';
226
          when "001" =>
227
            reg_colour    <= vdu_data_in;
228
          when "010" =>
229
            reg_hcursor   <= vdu_data_in(6 downto 0);
230
          when "011" =>
231
            reg_vcursor   <= vdu_data_in(4 downto 0);
232
          when others =>
233
            reg_voffset   <= vdu_data_in(4 downto 0);
234
        end case;
235
      else
236
 
237
        if (req_write = '1') and (ack_write = '1') then
238
          req_write <= '0';
239
        else
240
          req_write <= req_write;
241
        end if;
242
 
243
      end if;
244
    end if;
245
  end process;
246
--
247
-- CPU Read interface
248
--
249
  vga_cpu_read : process(vdu_addr, vdu_cs,
250
                          reg_character, reg_colour,
251
                          reg_hcursor, reg_vcursor, reg_voffset)
252
  begin
253
    case vdu_addr is
254
      when "000" =>
255
        vdu_data_out <= reg_character;
256
      when "001" =>
257
        vdu_data_out <= reg_colour;
258
      when "010" =>
259
        vdu_data_out <= "0" & reg_hcursor;
260
      when "011" =>
261
        vdu_data_out <= "000" & reg_vcursor;
262
      when others =>
263
        vdu_data_out <= "000" & reg_voffset;
264
    end case;
265
  end process;
266
 
267
--
268
-- Video memory access
269
--
270
  vga_addr_proc : process(vga_clk, vdu_rst)
271
  begin
272
 
273
    if vdu_rst = '1' then
274
      vga0_cs   <= '0';
275
      vga0_rw   <= '1';
276
      row_addr  <= "000000";
277
      col_addr  <= "0000000";
278
      --
279
      vga1_cs   <= '0';
280
      vga1_rw   <= '1';
281
      row1_addr <= "000000";
282
      col1_addr <= "0000000";
283
      --
284
      vga2_cs   <= '0';
285
      vga2_rw   <= '1';
286
      ver_addr  <= "0000000";
287
      hor_addr  <= "0000000";
288
      --
289
      vga_cs    <= '0';
290
      vga_rw    <= '1';
291
      vga_addr  <= "00000000000";
292
 
293
    elsif vga_clk'event and vga_clk = '0' then
294
      --
295
      -- on h_count = 0 initiate character write.
296
      -- all other cycles are reads.
297
      --
298
      case h_count(2 downto 0) is
299
        when "000" =>                   -- pipeline character write
300
          vga0_cs  <= req_write;
301
          vga0_rw  <= '0';
302
          col_addr <= reg_hcursor(6 downto 0);
303
          row_addr <= unsigned("0" & reg_vcursor(4 downto 0)) + unsigned("0" & reg_voffset(4 downto 0));
304
        when others =>                  -- other 6 cycles free
305
          vga0_cs  <= '1';
306
          vga0_rw  <= '1';
307
          col_addr <= h_count(9 downto 3);
308
          row_addr <= unsigned("0" & v_count(8 downto 4)) + unsigned("0" & reg_voffset(4 downto 0));
309
      end case;
310
      --
311
      -- on vga_clk + 1 round off row address
312
      --
313
      vga1_cs <= vga0_cs;
314
      vga1_rw <= vga0_rw;
315
      if row_addr < VER_DISP_CHR then
316
        row1_addr <= row_addr;
317
      else
318
        row1_addr <= row_addr - VER_DISP_CHR;
319
      end if;
320
      col1_addr <= col_addr;
321
      --
322
      -- on vga_clk + 2 calculate vertical address
323
      --
324
      vga2_cs   <= vga1_cs;
325
      vga2_rw   <= vga1_rw;
326
      ver_addr  <= std_logic_vector(unsigned("00" & row1_addr(4 downto 0)) + unsigned(row1_addr(4 downto 0) & "00"));
327
      hor_addr  <= col1_addr;
328
      --
329
      -- on vga_clk + 3 calculate memory address
330
      --
331
      vga_cs    <= vga2_cs;
332
      vga_rw    <= vga2_rw;
333
      vga_addr  <= std_logic_vector(unsigned("0000" & hor_addr) + unsigned(ver_addr & "0000"));
334
    end if;
335
  end process;
336
--
337
-- Video shift register
338
--
339
  vga_shift_proc : process( vga_clk, vdu_rst)
340
  begin
341
    if vdu_rst = '1' then
342
      ack_write     <= '0';
343
      video_on2     <= '0';
344
      video_on      <= '0';
345
      cursor_on     <= '0';
346
      vga_shift     <= "00000000";
347
      vga_red_o     <= '0';
348
      vga_green_o   <= '0';
349
      vga_blue_o    <= '0';
350
      -- Put all video signals through DFFs to elminate any delays that cause a blurry image
351
 
352
    elsif vga_clk'event and vga_clk = '0' then
353
      -- Character Data valid on 1 count
354
      if h_count(2 downto 0) = "000" then
355
        if (req_write = '1') and (ack_write = '0') then
356
          ack_write <= '1';
357
        elsif (req_write = '0') and (ack_write = '1') then
358
          ack_write <= '0';
359
        else
360
          ack_write <= ack_write;
361
        end if;
362
        video_on2     <= video_on1;
363
        video_on      <= video_on2;
364
        cursor_on     <= cursor_on1 and blink_count(22);
365
        vga_shift     <= char_data_out;
366
      else
367
        vga_shift     <= vga_shift(6 downto 0) & '0';
368
      end if;
369
 
370
      --
371
      -- Colour mask is
372
      --  7  6  5  4  3  2  1  0
373
      --  X BG BB BR  X FG FB FR
374
      --
375
      if vga_shift(7) = (not cursor_on) then
376
        vga_red_o   <= video_on;
377
        vga_green_o <= video_on;
378
        vga_blue_o  <= video_on;
379
      else
380
        vga_red_o   <= '0';
381
        vga_green_o <= '0';
382
        vga_blue_o  <= '0';
383
      end if;
384
    end if;
385
  end process;
386
 
387
 
388
--
389
-- Sync generator & timing process
390
-- Generate Horizontal and Vertical Timing Signals for Video Signal
391
--
392
  vga_sync : process(vga_clk)
393
  begin
394
    if vga_clk'event and vga_clk = '0' then
395
      --
396
      -- H_count counts pixels (640 + extra time for sync signals)
397
      --
398
      --  Horiz_sync  -----------------------------__________--------
399
      --  H_count       0                640      659       755    799
400
      --
401
      if unsigned(h_count) = HOR_SCAN_END then
402
        h_count <= (others=>'0');
403
      else
404
        h_count <= std_logic_vector(unsigned(h_count) + 1);
405
      end if;
406
--
407
-- Generate Horizontal Sync Signal using H_count
408
--
409
      if unsigned(h_count) = HOR_SYNC_BEG then
410
        horiz_sync <= '0';
411
      elsif unsigned(h_count) = HOR_SYNC_END then
412
        horiz_sync <= '1';
413
      else
414
        horiz_sync <= horiz_sync;
415
      end if;
416
--
417
-- V_count counts rows of pixels
418
-- 400 lines + extra time for sync signals
419
-- 25 rows * 16 scan lines
420
--
421
--  Vert_sync      ---------------------------------_______------------
422
--  V_count         0                       400    413     414        444
423
--
424
      if (unsigned(v_count) = VER_SCAN_END) and (unsigned(h_count) = HOR_SCAN_END) then
425
        v_count <= "000000000";
426
      elsif unsigned(h_count) = HOR_SYNC_END then
427
        v_count <= std_logic_vector(unsigned(v_count) + 1);
428
      end if;
429
--
430
-- Generate Vertical Sync Signal using V_count
431
--
432
      if unsigned(v_count) = VER_SYNC_BEG then
433
        vert_sync <= '0';
434
      elsif unsigned(v_count) = VER_SYNC_END then
435
        vert_sync <= '1';
436
      else
437
        vert_sync <= vert_sync;
438
      end if;
439
 
440
-- Generate Video on Screen Signals for Pixel Data
441
      if unsigned(h_count) = HOR_SCAN_END then
442
        video_on_h <= '1';
443
      elsif unsigned(h_count) = HOR_DISP_END then
444
        video_on_h <= '0';
445
      else
446
        video_on_h <= video_on_h;
447
      end if;
448
 
449
      if unsigned(v_count) = VER_SCAN_END then
450
        video_on_v <= '1';
451
      elsif unsigned(v_count) = VER_DISP_END then
452
        video_on_v <= '0';
453
      else
454
        video_on_v <= video_on_v;
455
      end if;
456
 
457
 
458
      if h_count(9 downto 3) = reg_hcursor(6 downto 0) then
459
        cursor_on_h <= '1';
460
      else
461
        cursor_on_h <= '0';
462
      end if;
463
 
464
      if (v_count(8 downto 4) = reg_vcursor(4 downto 0)) then
465
        cursor_on_v <= '1';
466
      else
467
        cursor_on_v <= '0';
468
      end if;
469
 
470
      -- cursor_on is only active when on selected character
471
      blink_count <= std_logic_vector(unsigned(blink_count) + 1);
472
    end if;
473
 
474
  end process;
475
 
476
  -- video_on is high only when RGB data is displayed
477
  vga_hsync_o <= horiz_sync;
478
  vga_vsync_o <= vert_sync;
479
  video_on1   <= video_on_H and video_on_V;
480
  cursor_on1  <= cursor_on_h and cursor_on_v;
481
 
482
--
483
-- Here to look up character ROM
484
-- This will take one clock cycle
485
-- and should be performed on h_count = "111"
486
--
487
  char_addr(10 downto 4) <= vga_data_out(6 downto 0);
488
  char_addr(3 downto 0)  <= v_count(3 downto 0);
489
 
490
end RTL;

powered by: WebSVN 2.1.0

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