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

Subversion Repositories System09

[/] [System09/] [trunk/] [rtl/] [VHDL/] [crtc6845.vhd] - Blame information for rev 209

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

Line No. Rev Author Line
1 130 dilbert57
--===========================================================================--
2
--                                                                           --
3
--  S Y N T H E S I Z A B L E    CRTC6845   C O R E                          --
4
--                                                                           --
5
--  www.opencores.org - January 2000                                         --
6
--  This IP core adheres to the GNU public license.                          --
7
--                                                                           --
8
--  VHDL model of MC6845 compatible CRTC                                     --
9
--                                                                           --
10
--  This model doesn't implement interlace mode. Everything else is          --
11
--  (probably) according to original MC6845 data sheet (except VTOTADJ).     --
12
--                                                                           --
13
--  Implementation in Xilinx Virtex XCV50-6 runs at 50 MHz (character clock).--
14
--  With external pixel generator this CRTC could handle 450MHz pixel rate   --
15
--  (see MC6845 data-sheet for typical application).                         --
16
--                                                                           --
17
--  Author:   Damjan Lampret, lampret@opencores.org                          --
18
--  Reworked: John Kent,      dilbert57@opencores.org                        --
19
--                                                                           --
20
--  TO DO:                                                                   --
21
--                                                                           --
22
--   - testbench                                                             --
23
--                                                                           --
24
--   - interlace mode support, extend VSYNC for V.Total Adjust value (R5)    --
25
--                                                                           --
26
--   - verification in a real application                                    --
27
--                                                                           --
28
--===========================================================================--
29
--
30
-- Revision History
31
--
32
-- Version  Date        Author          Modification
33
-- 1.0      2000-01-??  Damjan Lampret  Original Version
34
-- 2.0      2012-04-07  John Kent       Substantial rework for System09
35
--                                      Added vertical synch width to hsw_reg
36
--                                      Made light pen strobe positive going
37
-- 
38
library IEEE;
39
   use ieee.std_logic_1164.all;
40
   use IEEE.STD_LOGIC_ARITH.ALL;
41
   use IEEE.STD_LOGIC_UNSIGNED.ALL;
42
   use ieee.numeric_std.all;
43
 
44
entity crtc6845 is
45
  generic (
46
    DB_WIDTH : integer :=  8;
47
    MA_WIDTH : integer := 14;
48
    RA_WIDTH : integer :=  5
49
    );
50
  port (
51
    clk       : in  STD_LOGIC;                             -- cpu clock (falling edge)
52
    rst       : in  STD_LOGIC;                             -- reset (active high)
53
    cs        : in  STD_LOGIC;                             -- register chip select
54
    addr      : in  STD_LOGIC;                             -- register select
55
    rw        : in  STD_LOGIC;                             -- register read write
56
    data_in   : in  STD_LOGIC_VECTOR(DB_WIDTH-1 downto 0); -- register data bus in
57
    data_out  : out STD_LOGIC_VECTOR(DB_WIDTH-1 downto 0); -- register data bus out
58
 
59
    chr_clk   : in  STD_LOGIC;                             -- character clock input (rising edge)
60
    MA        : out STD_LOGIC_VECTOR(MA_WIDTH-1 downto 0); -- memory address (characters)
61
    RA        : out STD_LOGIC_VECTOR(RA_WIDTH-1 downto 0); -- row address (character generator lines)
62
    HSYNC     : out STD_LOGIC;                             -- Horizontal synch
63
    VSYNC     : out STD_LOGIC;                             -- Vertical synch
64
    dsp_ena   : out STD_LOGIC;                             -- Display enable
65
    cur_ena   : out STD_LOGIC;                             -- Cursor enable
66
    lpn_stb   : in  STD_LOGIC                              -- light pen strobe input (active high)
67
    );
68
end crtc6845;
69
 
70
architecture rtl of crtc6845 is
71
 
72
constant AR_WIDTH  : integer :=  5;
73
 
74
--
75
-- 6845 Register Index Numbers
76
--
77
constant hto_ind   : STD_LOGIC_VECTOR(AR_WIDTH-1 downto 0) := "00000"; -- Horizontal Total          (Characters) WO
78
constant hds_ind   : STD_LOGIC_VECTOR(AR_WIDTH-1 downto 0) := "00001"; -- Horizontal Displayed      (Characters) WO
79
constant hsp_ind   : STD_LOGIC_VECTOR(AR_WIDTH-1 downto 0) := "00010"; -- Horizontal Synch position (Characters) WO
80
constant hsw_ind   : STD_LOGIC_VECTOR(AR_WIDTH-1 downto 0) := "00011"; -- Sync Width (Ver & Hor)    (SL / Chars) WO
81
constant vto_ind   : STD_LOGIC_VECTOR(AR_WIDTH-1 downto 0) := "00100"; -- Vertical Total            (Char Rows)  WO
82
constant adj_ind   : STD_LOGIC_VECTOR(AR_WIDTH-1 downto 0) := "00101"; -- Vertical Total Adjust     (Scan Lines) WO
83
constant vds_ind   : STD_LOGIC_VECTOR(AR_WIDTH-1 downto 0) := "00110"; -- Vertical Displayed        (Char Rows)  WO
84
constant vsp_ind   : STD_LOGIC_VECTOR(AR_WIDTH-1 downto 0) := "00111"; -- Vertical Synch position   (Char Rows)  WO
85
constant imd_ind   : STD_LOGIC_VECTOR(AR_WIDTH-1 downto 0) := "01000"; -- Interlace Mode & Skew                  WO
86
constant sln_ind   : STD_LOGIC_VECTOR(AR_WIDTH-1 downto 0) := "01001"; -- Maximum Scan Line Address (Scan Lines) WO
87
constant cur_s_ind : STD_LOGIC_VECTOR(AR_WIDTH-1 downto 0) := "01010"; -- Cursor Start              (Scan Lines) WO Bit 5 BP, Bit 6 BE
88
constant cur_e_ind : STD_LOGIC_VECTOR(AR_WIDTH-1 downto 0) := "01011"; -- Cursor End                (Scan Lines) WO
89
constant sta_h_ind : STD_LOGIC_VECTOR(AR_WIDTH-1 downto 0) := "01100"; -- Start Address High                     RW
90
constant sta_l_ind : STD_LOGIC_VECTOR(AR_WIDTH-1 downto 0) := "01101"; -- Start Address Low                      RW
91
constant cur_h_ind : STD_LOGIC_VECTOR(AR_WIDTH-1 downto 0) := "01110"; -- Cursor Position High                   RW
92
constant cur_l_ind : STD_LOGIC_VECTOR(AR_WIDTH-1 downto 0) := "01111"; -- Cusror Position Low                    RW
93
constant lpn_h_ind : STD_LOGIC_VECTOR(AR_WIDTH-1 downto 0) := "10000"; -- Light Pen Position High                RO
94
constant lpn_l_ind : STD_LOGIC_VECTOR(AR_WIDTH-1 downto 0) := "10001"; -- Light Pen Position Low                 RO
95
 
96
--
97
-- I/O address register
98
--
99
signal ind_reg     : STD_LOGIC_VECTOR(AR_WIDTH-1 downto 0);
100
 
101
--
102
-- 6845 Registers R0-R17
103
--
104
signal hto_reg     : STD_LOGIC_VECTOR(7 downto 0); -- Horizontal Total          (Chars) WO
105
signal hds_reg    : STD_LOGIC_VECTOR(7 downto 0); -- Horizontal Display        (Chars) WO
106
signal hsp_reg    : STD_LOGIC_VECTOR(7 downto 0); -- Horizontal Synch Position (Chars) WO
107
signal hsw_reg    : STD_LOGIC_VECTOR(7 downto 0); -- Horizontal Synch Width    (Chars) WO
108
signal vto_reg    : STD_LOGIC_VECTOR(6 downto 0); -- Vertical Total            (Rows)  WO
109
signal adj_reg    : STD_LOGIC_VECTOR(4 downto 0); -- Vertical Total Adjust     (Lines) WO
110
signal vds_reg    : STD_LOGIC_VECTOR(6 downto 0); -- Vertcal Display           (Rows)  WO
111
signal vsp_reg    : STD_LOGIC_VECTOR(6 downto 0); -- Vertical Synch Position   (Rows)  WO
112
signal imd_reg    : STD_LOGIC_VECTOR(1 downto 0); -- Interlace Mode & Skew             WO
113
signal sln_reg    : STD_LOGIC_VECTOR(4 downto 0); -- Maximum Scan Line Address (Lines) WO
114
signal cur_s_reg  : STD_LOGIC_VECTOR(6 downto 0); -- Cursor Start              (Lines) WO
115
signal cur_e_reg  : STD_LOGIC_VECTOR(4 downto 0); -- Cursor End                (Lines) WO
116
signal sta_h_reg  : STD_LOGIC_VECTOR(5 downto 0); -- Start Address High                RW
117
signal sta_l_reg  : STD_LOGIC_VECTOR(7 downto 0); -- Start Address Low                 RW
118
signal cur_h_reg  : STD_LOGIC_VECTOR(5 downto 0); -- Cursor Position High              RW
119
signal cur_l_reg  : STD_LOGIC_VECTOR(7 downto 0); -- Cursor Position Low               RW
120
signal lpn_h_reg  : STD_LOGIC_VECTOR(5 downto 0); -- Light Pen Address High            RO
121
signal lpn_l_reg  : STD_LOGIC_VECTOR(7 downto 0); -- Light Pen Address Low             RO
122
 
123
--
124
-- Counters
125
--
126
signal hor_ctr    : STD_LOGIC_VECTOR( 7 downto 0); -- Horizontal Counter             (Chars)
127
signal hsw_ctr          : STD_LOGIC_VECTOR( 3 downto 0); -- Horizontal Synch Width Counter (Chars)
128
signal sln_ctr          : STD_LOGIC_VECTOR( 4 downto 0); -- Scan Line Counter              (Lines)
129
signal ver_ctr     : STD_LOGIC_VECTOR( 6 downto 0); -- Vertical Counter               (Rows)
130
signal vsw_ctr          : STD_LOGIC_VECTOR( 3 downto 0); -- Vertical Synch widtrh Counter  (Lines)
131
signal row_ctr    : STD_LOGIC_VECTOR(13 downto 0); -- Vertical Row counter
132
signal lag_ctr          : STD_LOGIC_VECTOR(13 downto 0); -- Linear Address Generator Counter
133
signal bnk_ctr    : STD_LOGIC_VECTOR( 4 downto 0); -- Blink Counter
134
 
135
--
136
-- Interconnect signals
137
--
138
signal hor_end    : STD_LOGIC; -- Horizontal display end
139
signal ver_end    : STD_LOGIC; -- Vertical display end
140
signal hor_syn    : STD_LOGIC; -- Horizontal Synch
141
signal ver_syn    : STD_LOGIC; -- Vertical Synch
142
signal hor_dsp    : STD_LOGIC; -- Horizontal Display Enable
143
signal ver_dsp    : STD_LOGIC; -- Vertical Display Enable
144
signal hor_rst    : STD_LOGIC; -- Horizontal Reset (End of Line)
145
signal ver_rst    : STD_LOGIC; -- Vertical Reset   (End of Frame)
146
signal sln_rst    : STD_LOGIC; -- Scan Line Reset  (End of Row)
147
signal sln_adj    : STD_LOGIC; -- Scan Line Adjust (End of Frame)
148
signal cur_act    : STD_LOGIC; -- Cursor active
149
 
150
begin
151
 
152
--
153
-- Read CRTC6845 registers
154
--
155
crtc_read: process(addr, ind_reg, sta_h_reg, sta_l_reg, cur_h_reg, cur_l_reg, lpn_h_reg, lpn_l_reg )
156
begin
157
  if addr = '0' then
158
    --
159
    -- Read register address
160
    --
161
    data_out(AR_WIDTH-1 downto 0) <= ind_reg;
162
    data_out(7 downto AR_WIDTH)   <= (others=>'0');
163
  else
164
    --
165
    -- Read register value
166
    --
167
         case ind_reg is
168
    when sta_h_ind =>
169
      data_out <= "00" & sta_h_reg;
170
    when sta_l_ind =>
171
      data_out <= sta_l_reg;
172
    when cur_h_ind =>
173
      data_out <= "00" & cur_h_reg;
174
    when cur_l_ind =>
175
                data_out <= cur_l_reg;
176
    when lpn_h_ind =>
177
                data_out <= "00" & lpn_h_reg;
178
    when lpn_l_ind =>
179
      data_out <= lpn_l_reg;
180
    when others =>
181
      data_out <= (others => '0');
182
         end case;
183
  end if;
184
end process;
185
 
186
--
187
-- Write CRTC registers
188
--
189
crtc_write: process(clk, rst, cs, rw, addr, data_in)
190
begin
191
  if falling_edge(clk) then
192
    if rst = '1' then
193
      ind_reg    <= b"0" & x"0";
194
      hto_reg    <= x"65";
195
                hds_reg    <= x"50";
196
                hsp_reg    <= x"56";
197
                hsw_reg    <= x"F9";
198
                sln_reg    <= '0' & x"b";
199
                vto_reg    <= b"001" & x"8"; --18
200
                adj_reg    <= b"0" & x"a";
201
                vds_reg    <= b"001" & x"8"; --18
202
                vsp_reg    <= b"001" & x"8"; --18
203
      imd_reg    <= b"00";
204
                cur_s_reg  <= b"000" & x"0";
205
                cur_e_reg  <= b"0" & x"B";
206
                sta_h_reg  <= b"00" & x"0";
207
                sta_l_reg  <= x"80";
208
                cur_h_reg  <= b"00" & x"0";
209
                cur_l_reg  <= x"80";
210
 
211
    elsif cs = '1' and rw = '0' then
212
      if addr = '0' then
213
        ind_reg <= data_in(AR_WIDTH-1 downto 0);
214
      else
215
        case ind_reg is
216
                  when hto_ind =>
217
                    hto_reg <= data_in;
218
                  when hds_ind =>
219
                         hds_reg <= data_in;
220
                  when hsp_ind =>
221
                         hsp_reg <= data_in;
222
                  when hsw_ind =>
223
                         hsw_reg <= data_in;
224
                  when sln_ind =>
225
                         sln_reg <= data_in(4 downto 0);
226
                  when vto_ind =>
227
                         vto_reg <= data_in(6 downto 0);
228
                  when adj_ind =>
229
                         adj_reg <= data_in(4 downto 0);
230
                  when vds_ind =>
231
                         vds_reg <= data_in(6 downto 0);
232
                  when vsp_ind =>
233
                         vsp_reg <= data_in(6 downto 0);
234
        when imd_ind =>
235
          imd_reg <= data_in(1 downto 0);
236
                  when cur_s_ind =>
237
                         cur_s_reg <= data_in(6 downto 0);
238
                  when cur_e_ind =>
239
                         cur_e_reg <= data_in(4 downto 0);
240
                  when sta_h_ind =>
241
                         sta_h_reg <= data_in(5 downto 0);
242
                  when sta_l_ind =>
243
                         sta_l_reg <= data_in;
244
                  when cur_h_ind =>
245
                         cur_h_reg <= data_in(5 downto 0);
246
                  when cur_l_ind =>
247
                         cur_l_reg <= data_in;
248
                  when others =>
249
                         null;
250
                  end case;
251
      end if; -- addr
252
    end if; -- cs
253
  end if; -- E
254
 
255
end process;
256
 
257
--------------------------------------------
258
-- Horizontal Counter                     --
259
--------------------------------------------
260
--
261
-- hor_ctr (horizontal counter) increments
262
-- until it reaches the horizontal total 
263
-- then resets to zero
264
--
265
crtc_hor_ctr_p : process(chr_clk, rst, hor_rst, hor_ctr)
266
begin
267
  if rising_edge(chr_clk) then
268
    if rst = '1' then
269
                hor_ctr <= (others => '0');
270
    else
271
                if hor_rst = '1' then
272
                  hor_ctr <= (others => '0');
273
      else
274
        hor_ctr <= hor_ctr + 1;
275
      end if;
276
    end if;
277
  end if;
278
end process;
279
 
280
--------------------------------------------
281
-- Horizontal Reset                     --
282
--------------------------------------------
283
--
284
-- hor_rst (horizontal reset) goes high
285
-- for one horizontal character cycle
286
-- when the horizontal counte reaches 
287
-- the horizontal total, then it goes low
288
--
289
crtc_hor_rst_p : process(hor_ctr, hto_reg)
290
begin
291
  if hor_ctr = hto_reg then
292
    hor_rst <= '1';
293
  else
294
    hor_rst <= '0';
295
  end if;
296
end process;
297
 
298
--------------------------------------------
299
-- Horizontal Display End                 --
300
--------------------------------------------
301
--
302
-- hor_end (horizontal end) goes high
303
-- for one horizontal character clock cycles
304
-- when the horizontal counter reaches
305
-- the horizontal display count
306
--
307
crtc_hor_end_p: process(hor_ctr, hds_reg)
308
begin
309
        if hor_ctr = hds_reg then
310
                hor_end <= '1';
311
        else
312
                hor_end <= '0';
313
        end if;
314
end process;
315
 
316
--------------------------------------------
317
-- Horizontal Display Enable              --
318
--------------------------------------------
319
--
320
-- Horizontal display goes high on a
321
-- horizontal reset and goes low at
322
-- horizontal end.
323
--
324
crtc_hor_dsp_p: process(chr_clk, rst, hor_rst, hor_end )
325
begin
326
 
327
  if rising_edge( chr_clk ) then
328
    if rst = '1' then
329
      hor_dsp <= '0';
330
    elsif hor_rst = '1' and hor_end = '0' then
331
      hor_dsp <= '1';
332
    elsif hor_rst = '0' and hor_end = '1' then
333
      hor_dsp <= '0';
334
    end if;
335
  end if;
336
end process;
337
 
338
--------------------------------------------
339
-- Horizontal Horizontal Synch            --
340
--------------------------------------------
341
--
342
-- hor_syn (horizontal synch) goes high
343
-- when the horizontal counter reaches 
344
-- the the value in the horizontal synch position
345
-- register. It is reset when the horizontal
346
-- synch width counter reaches the value
347
-- in the horizontal synch width register
348
--
349
crtc_hor_syn_p: process(chr_clk, rst, hor_ctr, hsp_reg, hsw_reg, hor_syn)
350
begin
351
  if rising_edge(chr_clk) then
352
    if rst = '1' then
353
      hor_syn <= '0';
354
         elsif hor_ctr = hsp_reg then
355
                hor_syn <= '1';
356
         elsif hsw_ctr = hsw_reg(3 downto 0) then
357
      hor_syn <= '0';
358
         end if;
359
  end if;
360
  HSYNC <= hor_syn;
361
 
362
end process;
363
 
364
--------------------------------------------
365
-- Horizontal Synch Width Counter         --
366
--------------------------------------------
367
--
368
-- The horizaontal synch width counter
369
-- increments each character clock cycle
370
-- while the horizontal synch pulse is high
371
-- It is reset when horizontal synch goes low
372
--
373
crtc_hsw_ctr_p: process(chr_clk, rst, hor_syn, hsw_ctr)
374
begin
375
  if rising_edge(chr_clk) then
376
    if rst = '1' then
377
                hsw_ctr <= (others => '0');
378
         else
379
                if hor_syn = '1' then
380
                        hsw_ctr <= hsw_ctr + 1;
381
                else
382
                        hsw_ctr <= (others => '0');
383
                end if;
384
    end if;
385
  end if;
386
end process;
387
 
388
--------------------------------------------
389
-- Scan Line Counter                      --
390
--------------------------------------------
391
--
392
-- The Scan line counter increments
393
-- when horizontal reset goes high.
394
-- It is reset when the scan line counter
395
-- reaches the value in the scan line register
396
-- The Scan line counter is used to generate
397
-- the row address of the character generator
398
--
399
crtc_sln_ctr_p: process(chr_clk, rst, hor_rst, sln_rst, sln_ctr )
400
begin
401
  if rising_edge(chr_clk) then
402
    if rst = '1' then
403
      sln_ctr <= (others => '0');
404
    elsif sln_rst = '1' then
405
      sln_ctr <= (others => '0');
406
         elsif hor_rst = '1' then
407
      sln_ctr <= sln_ctr + 1;
408
    end if;
409
  end if;
410
  RA <= sln_ctr;
411
end process;
412
 
413
--------------------------------------------
414
-- Scan Line Reset                        --
415
--------------------------------------------
416
--
417
-- Scan line reset is goes high when the
418
-- scan line counter reaches the value in
419
-- the scan line register and is zero otherwise
420
--
421
crtc_sln_rst_p: process(sln_reg, sln_ctr)
422
begin
423
  if sln_ctr = sln_reg then
424
    sln_rst <= '1';
425
  else
426
    sln_rst <= '0';
427
  end if;
428
end process;
429
 
430
--------------------------------------------
431
-- Scan Line Adjust                       --
432
--------------------------------------------
433
--
434
-- Scan line Adjust goes high when the
435
-- scan line counter reaches the value
436
-- in the scan line adjust register.
437
-- It is use to reset the vertical counter
438
-- when it reaches the vertical total
439
--
440
crtc_sln_adj_p: process(sln_ctr, adj_reg)
441
begin
442
        if sln_ctr = adj_reg then
443
                sln_adj <= '1';
444
        else
445
                sln_adj <= '0';
446
        end if;
447
end process;
448
 
449
--------------------------------------------
450
-- Vertical Row Counter                   --
451
--------------------------------------------
452
--
453
-- The Vertical Row counter is incremenented
454
-- when there is a scan line reset and there
455
-- is a horizontal reset.
456
-- The vertical row counter is reset when
457
-- there is a vertical reset due to the
458
-- vertical counter reaching the value in
459
-- the vertical total register and a
460
-- scan line adjust signal is generated
461
--
462
ctrc_ver_ctr_p: process(chr_clk, rst, sln_rst)
463
begin
464
  if rising_edge(chr_clk) then
465
    if rst = '1' then
466
                ver_ctr <= (others => '0');
467
         elsif ver_rst = '1' then
468
      ver_ctr <= (others => '0');
469
         elsif sln_rst = '1' and hor_rst = '1' then
470
      ver_ctr <= ver_ctr + 1;
471
    end if;
472
  end if;
473
end process;
474
 
475
--------------------------------------------
476
-- Vertical Reset                         --
477
--------------------------------------------
478
--
479
-- Vertical reset is generated when the
480
-- vertical counter reaches the value in
481
-- the vertical total register and the
482
-- scan line counter reaches the scan
483
-- line adjust register value
484
--
485
ctrc_ver_rst_p: process(ver_ctr, vto_reg, sln_adj )
486
begin
487
 
488
  if ver_ctr = vto_reg and sln_adj = '1' then
489
         ver_rst <= '1';
490
  else
491
         ver_rst <= '0';
492
  end if;
493
 
494
end process;
495
 
496
--------------------------------------------
497
-- Vertical Display End Process           --
498
--------------------------------------------
499
--
500
-- Vertical end is generated when the
501
-- vertical counter reaches the value in
502
-- the display end register
503
--
504
crtc_ver_end_p: process(ver_ctr, vds_reg)
505
begin
506
        if ver_ctr = vds_reg then
507
                ver_end <= '1';
508
        else
509
                ver_end <= '0';
510
        end if;
511
end process;
512
 
513
--------------------------------------------
514
-- Vertical Display Enable                --
515
--------------------------------------------
516
 
517
crtc_ver_dsp_p: process(chr_clk, rst, ver_rst, ver_end )
518
begin
519
 
520
  if rising_edge( chr_clk ) then
521
    if rst = '1' then
522
      ver_dsp <= '0';
523
    elsif ver_rst = '1' and ver_end = '0' then
524
      ver_dsp <= '1';
525
    elsif ver_rst = '0' and ver_end = '1' then
526
      ver_dsp <= '0';
527
    end if;
528
  end if;
529
 
530
end process;
531
 
532
--------------------------------------------
533
-- Vertical Synch Width Counter           --
534
--------------------------------------------
535
--
536
-- The Vertical Synch Width Counter
537
-- is incremented when vertical synch goes high
538
-- as a result of the Vertical Counter reaching
539
-- the Vertical Synch Width Position and horizontal
540
-- reset goes high.
541
-- The Vertical synch width counter is reset
542
-- when Vertical synch goes low.
543
--
544
crtc_vsw_ctr_p: process(chr_clk, rst, hor_rst, ver_ctr, vsp_reg, vsw_ctr)
545
begin
546
  if rising_edge(chr_clk) then
547
    if rst = '1' then
548
      vsw_ctr <= (others => '0');
549
         elsif ver_syn = '0' then
550
      vsw_ctr <= (others => '0');
551
         elsif ver_syn = '1' and  hor_rst = '1' then
552
      vsw_ctr <= vsw_ctr + 1;
553
    end if;
554
  end if;
555
end process;
556
 
557
--------------------------------------------
558
-- Vertical Synch                         --
559
--------------------------------------------
560
--
561
-- The Vertical Synch goes high when the
562
-- vertical counter reaches the value in the
563
-- vertical synch position register.
564
-- It is reset when the vertical synch width
565
-- counter reaches 16.
566
--
567
crtc_ver_syn_p: process(chr_clk, rst, ver_ctr, vsp_reg, vsw_ctr, hsw_reg, ver_syn)
568
begin
569
  if rising_edge(chr_clk) then
570
    if rst = '1' then
571
      ver_syn <= '0';
572
         elsif ver_ctr = vsp_reg then
573
      ver_syn <= '1';
574
         elsif vsw_ctr = hsw_reg(7 downto 4) then
575
      ver_syn <= '0';
576
    end if;
577
  end if;
578
  VSYNC <= ver_syn;
579
end process;
580
 
581
--------------------------------------------
582
-- Vertical Row Counter                   --
583
--------------------------------------------
584
--
585
-- The character row counter is incremented 
586
-- by the horizontal display count 
587
-- on a scan line reset and a horizontal reset.
588
-- It is reset to the start address on a vertical reset
589
--
590
crtc_row_ctr_p: process(chr_clk, rst, sln_rst, ver_rst, hor_rst, sta_h_reg, sta_l_reg)
591
begin
592
  if rising_edge(chr_clk) then
593
    if rst = '1' then
594
                row_ctr <= sta_h_reg & sta_l_reg;
595
         elsif sln_rst = '1' and hor_rst = '1' then
596
                row_ctr <= row_ctr + hds_reg;
597
                if ver_rst = '1' then
598
                        row_ctr <= sta_h_reg & sta_l_reg;
599
                end if;
600
    end if;
601
  end if;
602
end process;
603
 
604
--------------------------------------------
605
-- Display Enable                         --
606
--------------------------------------------
607
--
608
-- Display enable is active when both
609
-- horizantal display and vertical displays 
610
-- are active
611
--
612
crtc_dsp_ena_p: process(hor_dsp, ver_dsp)
613
begin
614
 
615
  dsp_ena <= hor_dsp and ver_dsp;
616
 
617
end process;
618
 
619
 
620
--------------------------------------------
621
-- Linear Address Generator               --
622
--------------------------------------------
623
 
624
crtc_lag_p: process(chr_clk, rst, hor_rst, sta_h_reg, sta_l_reg, lag_ctr)
625
begin
626
  if rising_edge(chr_clk) then
627
    if rst = '1' then
628
                lag_ctr <= sta_h_reg & sta_l_reg;
629
         else
630
                if hor_rst = '1' then
631
                  lag_ctr <= row_ctr;
632
                end if;
633
                lag_ctr <= lag_ctr + 1;
634
    end if;
635
  end if;
636
  MA <= lag_ctr;
637
end process;
638
 
639
--------------------------------------------
640
-- Cursor Control Unit Instantiation      --
641
--------------------------------------------
642
--
643
-- Cursor active when the Linear Address Generator
644
-- reaches the value in the Cursor position register
645
--
646
crtc_cur_act_p: process(lag_ctr, cur_h_reg, cur_l_reg)
647
begin
648
        if lag_ctr = (cur_h_reg & cur_l_reg) then
649
                cur_act <= '1';
650
        else
651
                cur_act <= '0';
652
        end if;
653
end process;
654
 
655
--------------------------------------------
656
-- Cursor Blink Counter                   --
657
--------------------------------------------
658
--
659
-- The Cursor Blink Counter increments
660
-- every frame
661
--
662
crtc_blink_ctr_p: process (chr_clk, rst, hor_rst, ver_rst)
663
begin
664
  if rising_edge(chr_clk) then
665
         if rst = '1' then
666
                bnk_ctr <= (others => '0');
667
         elsif hor_rst = '1' and ver_rst = '1' then
668
                bnk_ctr <= bnk_ctr + 1;
669
    end if;
670
  end if;
671
end process;
672
 
673
--------------------------------------------
674
-- Cursor Enable                          --
675
--------------------------------------------
676
--
677
-- The Cursor is enabled when the Scan line
678
-- counter is great or equal to the Cursor Start Line
679
-- and the scan line counter is less than or equal
680
-- to the Cursor End line and the Cusor is active 
681
--
682
crtc_cur_ena_p: process (sln_ctr, cur_s_reg, cur_e_reg, cur_act, bnk_ctr)
683
begin
684
        if sln_ctr >= cur_s_reg(4 downto 0) and sln_ctr <= cur_e_reg and cur_act = '1' then
685
                case cur_s_reg(6 downto 5) is
686
                when "00" =>
687
                        cur_ena <= '1';
688
                when "10" =>
689
                        cur_ena <= bnk_ctr(3);
690
                when "11" =>
691
                        cur_ena <= bnk_ctr(4);
692
                when others =>
693
                        cur_ena <= '0';
694
                end case;
695
        else
696
                cur_ena <= '0';
697
        end if;
698
end process;
699
 
700
--------------------------------------------
701
-- Light Pen Capture                      --
702
--------------------------------------------
703
--
704
-- The light pen resister is loaded
705
-- when ther is a high on the light
706
-- pen strobe input
707
--
708
ctrc_lpn_stb_p: process(chr_clk, rst, lpn_stb)
709
begin
710
  if rising_edge(chr_clk) then
711
    if rst = '1' then
712
      lpn_h_reg <= (others => '0');
713
      lpn_l_reg <= (others => '0');
714
    elsif lpn_stb = '1' then
715
      lpn_h_reg <= lag_ctr(13 downto 8);
716
      lpn_l_reg <= lag_ctr(7 downto 0);
717
         end if;
718
  end if;
719
end process;
720
 
721
end rtl;
722
 

powered by: WebSVN 2.1.0

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