1 | ----------------------------------------------------------------------------------
|
2 | -- Engineer: Ralph_H Stand 17.02.2011
|
3 | -- Module Name: BWS_2011_TFT
|
4 | ----------------------------------------------------------------------------------
|
5 | library IEEE;
|
6 | use IEEE.STD_LOGIC_1164.ALL;
|
7 | use IEEE.NUMERIC_STD.ALL ; --nötig für die Zähler !
|
8 |
|
9 | entity BWS_2011_TFT is
|
10 | Port (
|
11 | ADR : in STD_LOGIC_VECTOR (15 downto 0);
|
12 | DB : inout STD_LOGIC_VECTOR (7 downto 0) ;
|
13 | MREQ : in STD_LOGIC;
|
14 | WR : in STD_LOGIC;
|
15 | RD : in STD_LOGIC;
|
16 | Reset : in STD_LOGIC;
|
17 | IORQ : in STD_LOGIC;
|
18 | MEMDI : in STD_LOGIC; -- L wenn Speicher daktiviert
|
19 | MEMDI_Mod1: in STD_LOGIC; -- L wenn Modul1 deaktiviert (damit AC1 Speicher)
|
20 | -- dieses Signal ist auch das "CPM ein" Signal vom AC1 2010
|
21 | RAMADR : out STD_LOGIC_VECTOR (10 downto 0);-- Adresse BWSRAM
|
22 | RAMDB : inout STD_LOGIC_VECTOR (7 downto 0) ;-- bidirektional
|
23 | RAMWR : out STD_LOGIC; -- WR Signal für RAM
|
24 | ZGADR : out STD_LOGIC_VECTOR (2 downto 0); -- Adresse A0..A2 ZG-Eprom
|
25 | CSD35_36 : out STD_LOGIC; -- Clock Signal zum Laden Latch 74LS374 L/H Flanke
|
26 | ZG_Out : in STD_LOGIC_VECTOR (5 downto 0); -- Ausgänge ZG-Eprom
|
27 | ZGADR11 : out STD_LOGIC; --Umschaltung ZG ACC<-->SCCH Modus
|
28 | Video_out : out STD_LOGIC; -- VideoSignal negiert (wegen Treiber)
|
29 | HK_Sync : out STD_LOGIC; -- HK SynchronImpuls negiert (wegen Treiber)
|
30 | VK_Sync : out STD_LOGIC; -- VK SynchronImpuls negiert (wegen Treiber)
|
31 | Takt_in : in STD_LOGIC -- 20 Mhz Eingangstakt
|
32 | );
|
33 |
|
34 | end BWS_2011_TFT;
|
35 |
|
36 | architecture VERHALTEN of BWS_2011_TFT is
|
37 | signal VDCLK : STD_LOGIC := '0' ;-- VDCLK = Punkttakt 16Mhz
|
38 | signal QD19 : UNSIGNED (2 downto 0) := (others => '0') ; -- Ausgang D19 6:1 Taktteiler
|
39 | signal TaktD41 : STD_LOGIC := '0' ; -- Takt für D41
|
40 | signal QD41_42 : UNSIGNED (6 downto 0) := (others => '0'); -- Ausgang D41 und 42 Zeichenzähler
|
41 | signal Takt_Zeile : STD_LOGIC := '0' ; -- Takt für 2.Zeile wegen TFT
|
42 | signal QD_TFT : UNSIGNED (1 downto 0) := (others => '0'); -- 2:1 Teiler wegen TFT Modus
|
43 | signal TaktD43 : STD_LOGIC := '0' ; -- Takt für Zeilen pro ZeichenZähler D43
|
44 | signal QD43_44_20 : UNSIGNED (8 downto 0) := (others => '0'); -- Ausgang D43,D44,D20 Zähler
|
45 | signal CPU_Zugriff : STD_LOGIC := '0' ; --Signal 1 für Zugriff der CPU auf BWS (nur Adresse ausgewählt)
|
46 | signal BWS_Zugriff : STD_LOGIC := '0' ; --Signal 1 für Zugriff auf BWS, Umschaltung Adressen & DB Umschaltung
|
47 | signal BWS_RW : STD_LOGIC := '0' ; --Signal 1 wenn WR oder (RD & !! RW Modus)
|
48 | signal BWS_aus : STD_LOGIC := '1' ; --Signal 0 wenn BWS ausgeschaltet
|
49 | signal D35_36 : STD_LOGIC_VECTOR(7 downto 0) := (others => '0') ; -- Latch Adresse für ZG
|
50 | signal SR_ZG_Out : STD_LOGIC_VECTOR (5 downto 0) := (others => '0') ; -- Ausgänge Schieberegister ZG
|
51 | signal DG13 : STD_LOGIC := '0' ; -- Dunkeltastung = 1 bei Strahlrücklauf
|
52 | signal DTVDU : STD_LOGIC := '0' ; -- Dunkeltastung BWS Zugriff und
|
53 | signal BWS_INV : STD_LOGIC := '0' ; -- BWS INVERS Umschaltung
|
54 | signal Zei_INV : STD_LOGIC := '0' ; -- Zeichen INVERS Umschaltung
|
55 | signal IO5_Latch : STD_LOGIC := '0' ; -- PIO Port B ZG Umschaltung
|
56 | signal IO11_Latch : STD_LOGIC := '0' ; -- LatchIO11 Bit1=H Bildschirm INVERS
|
57 |
|
58 | -- ***********************************************************************************
|
59 | begin
|
60 | -- ab hier nun der CPLD Programmcode
|
61 |
|
62 | -- IO5 Latch fängt Ausgaben an PIO Port B ab (ZG Umschaltung)
|
63 | IO5_Latch <= DB(3) when
|
64 | (ADR(7 downto 0) = x"05" and IORQ = '0' and WR = '0')
|
65 | else IO5_Latch ;
|
66 | ZGADR11 <= IO5_Latch ; -- ZG-Umschaltung
|
67 |
|
68 | -- IO11H Register.. nur DB Bit 1 = Invers Umschaltung H=INVERS L=Standart
|
69 | IO11_Latch <= '0' when Reset = '0'
|
70 | else DB(1) when (ADR(7 downto 0) = x"11" and IORQ = '0' and WR = '0')
|
71 | else IO11_Latch ;
|
72 |
|
73 | -- Takteingang auf intern VDCLK legen..
|
74 | VDCLK <= Takt_In ; -- 20Mhz Eingangstakt = VDCLK
|
75 |
|
76 | -- Takterzeugung mit D19 (Basis ist VDCLK)
|
77 | D19:
|
78 | process(VDCLK) -- Basis ist VDCLK Takt der durch 6 geteilt wird
|
79 | begin
|
80 | if rising_edge(VDCLK) then QD19 <= QD19 + 1 ; end if ;--zählen..
|
81 | if QD19 = 6 then QD19 <= "000" ; end if ;--max. bis 6
|
82 | end process D19;
|
83 | TaktD41 <= '1' when QD19 = 0 Else '0' ; --Zählerstand 0 decodieren OK=0
|
84 | -- Hinweis, das beste Bild liefert weiterschalten bei Zählerstand 0,
|
85 | -- Latch D35_36 laden und SR Rausschieben (falling_edge) bei Zählerstand 5
|
86 | -- Takttiming: Zählerstand 0 weiterschalten Zeichenzähler
|
87 | -- Zählerstand 5 laden DB, Latches und Schieberegister laden
|
88 |
|
89 | -- Latch D35_36 welches Zeichen für ZG speichert laden
|
90 | D35_36 <= RAMDB when QD19 = 5 Else D35_36 ; -- 5 LD Impuls(H-aktiv)
|
91 | -- der Zeitpunkt des Ladens bestimmt offensichtlich wie breit der INVERS Balken ist ???
|
92 | CSD35_36 <= '1' when QD19 = 5 else '0' ; -- Clock Signal für Latch 74LS374 L/H speichert
|
93 |
|
94 | -- ZG Daten ins Schieberegister SR_ZG_Out holen
|
95 | ZG_Out_ausschieben: --ZG Daten aus D38&39=SR_ZG_Out(0) rausschieben
|
96 | process(VDCLK) -- Zeichentakt
|
97 | begin
|
98 | if falling_edge(VDCLK) then
|
99 | if QD19 = 5 then SR_ZG_Out(5 downto 0) <= ZG_Out(5 downto 0) ; -- parallel laden
|
100 | else SR_ZG_Out <= '0' & SR_ZG_Out(5 downto 1) ; -- serial schieben
|
101 | end if;
|
102 | end if;
|
103 | end process ZG_Out_ausschieben; -- fertig Videodaten ausschieben
|
104 |
|
105 | -- *** ab hier Zählerkette ********************************************************
|
106 | -- ZeichenZähler pro Zeile (64 Zeichen) mit D41 & D42
|
107 | D41_42:
|
108 | process(TaktD41) -- Basis ist Zählerstand 0 von Zähler D19
|
109 | begin
|
110 | if rising_edge(TaktD41) then QD41_42 <= QD41_42 + 1 ; end if ;--zählen..
|
111 | if QD41_42 = 84 then QD41_42 <= "0000000" ; end if ;--bis 84 64 Zeichen/Zeile
|
112 | end process D41_42;
|
113 |
|
114 | Takt_Zeile <= '1' when QD41_42 = 84 Else '0' ; -- Zählerstand 84 als Takt
|
115 |
|
116 | -- der 2:1 Teiler D_TFT der hier eingeschoben wird, bewirkt ein 2.Mal Schreiben der Zeile
|
117 | -- und gleichzeitig die Halbierung des VK-Taktes, was durch den höheren Bildtakt nötig ist
|
118 | D_TFT:
|
119 | process(Takt_Zeile) -- Basis ist Zählerstand 84 oder 104 von Zähler QD41_42
|
120 | begin
|
121 | if rising_edge(Takt_Zeile) then QD_TFT <= QD_TFT + 1 ; end if ;--zählen..
|
122 | if QD_TFT = 2 then QD_TFT <= "00" ; end if ;--max. bis 2
|
123 | end process D_TFT;
|
124 | TaktD43 <= QD_TFT(0) ; -- Takt für Zeilenzähler
|
125 |
|
126 | -- ZeilenZähler D43 & D44 & D20 zählt Zeilen 0 bis 320
|
127 | D43_44_20:
|
128 | process(TaktD43) -- Basis ist QD_TFT(0) 84Zeichen * 2
|
129 | begin
|
130 | if rising_edge(TaktD43) then QD43_44_20 <= QD43_44_20 + 1 ; end if ; --zählen..
|
131 | if QD43_44_20 = 320 then QD43_44_20 <= "000000000" ; end if ; --max. bis 320
|
132 | end process D43_44_20;
|
133 | -- *** BWS Zählerkette --Ende----------------------------------------------
|
134 | -- hier wird Adressdekodierung & Zugriff für BWS gemacht 1000H..17FFH
|
135 | CPU_Zugriff <= '1' when ADR(15 downto 12) =x"1" -- Adresse 1xxxH
|
136 | and ADR(11)='0' -- Adresse 1000H..17FFH
|
137 | and MREQ='0' -- Speicherzugriff
|
138 | and BWS_aus = '0' -- wenn BWS aktiv sein darf
|
139 | else '0' ; -- BWS auslesen
|
140 |
|
141 | -- Signal BWS_aus bilden, immer wenn der BWS mittels MEMDI deaktiviert wird
|
142 | BWS_aus <= '1' when MEMDI_Mod1 = '0' -- Modul 3 Zugriff
|
143 | or
|
144 | MEMDI ='1' -- CPM Zugriff
|
145 | else '0' ;
|
146 |
|
147 | -- hier wirklicher Zugriff auf BWS, vorerst ohne WAIT
|
148 | BWS_Zugriff <= '1' when CPU_Zugriff='1' else '0' ;
|
149 |
|
150 | -- WR Signal für den BWS-RAM (zusätzlich ist noch ein Widerstand gegen +5V)
|
151 | RAMWR <= '0' when BWS_Zugriff = '1' and WR = '0' else '1' ; --WR Signal RAM
|
152 |
|
153 | -- ** Adressmultiplexer ** ------------------------------------------------
|
154 | -- .. wenn BWS_Zugriff=1 dann Adressen von ADR.. sonst Zähleradressen
|
155 | RAMADR(5 downto 0) <= not ADR(5 downto 0) when BWS_Zugriff = '1'
|
156 | else STD_LOGIC_VECTOR(QD41_42(5 downto 0)) ;-- A5..A0
|
157 |
|
158 | RAMADR(10 downto 6) <= not ADR(10 downto 6) when BWS_Zugriff = '1' -- AC1 BWS Zugriff
|
159 | else STD_LOGIC_VECTOR(QD43_44_20(7 downto 3));
|
160 | -- ** Adressmultiplexer ** OK** ------------------------------------------------
|
161 |
|
162 | -- ** BWS RAM Datenbussteuerung ** ** ------------------------------------------------
|
163 | RAMDB <= DB when BWS_Zugriff = '1' and WR = '0' ELSE "ZZZZZZZZ" ; -- RAMDB TriState wenn kein WR
|
164 | -- das Einlesen der RAM-Daten auf RAMDB erfolgt immer nur zum Zeitpunkt des Laden des Latches
|
165 | DB <= RAMDB when BWS_Zugriff = '1' and RD = '0' ELSE "ZZZZZZZZ" ; -- DB TriState wenn kein BWS Read
|
166 |
|
167 | -- ZG Adresse erzeugen
|
168 | ZGADR(2 downto 0) <= STD_LOGIC_VECTOR(QD43_44_20(2 downto 0)) ; -- Bits 0..2 D43
|
169 |
|
170 | -- INVERS Modus 10H/11H
|
171 | Zei_INV <= '1' when D35_36 = x"11" -- InversModus ein
|
172 | else '0' when D35_36 = x"10" -- InversModus aus
|
173 | or QD41_42 = 65 ; -- InversModus aus Zeilenende
|
174 | -- INVERS-Auswertung
|
175 | BWS_Inv <= IO11_Latch when Zei_INV ='0' -- Umschaltung INVERS
|
176 | else not IO11_Latch ; -- Umschaltung Invertieren
|
177 |
|
178 | -- Hinweis.. durch die Treiber nach dem CPLD muss die Invertierung des Signales beachtet werden!
|
179 | Video_Out <= '1' when DTVDU = '1' -- Dunkeltastung
|
180 | or BWS_Zugriff ='1' -- BWS Zugriff dunkeltasten
|
181 | else SR_ZG_out(0) when BWS_INV = '1' -- INVERS oder NICHT INVERS
|
182 | else not SR_ZG_out(0) ; -- Ausgang Schieberegister ;
|
183 |
|
184 | -- Signal DTVDU bilden.. das ist das Dunkeltastsignal für die Ränder und Austastlücken
|
185 | DTVDU <= '1' when DG13 = '1' -- Ausgang FlipFlop DG13
|
186 | or QD43_44_20(8)='1' -- invertierter D20
|
187 | else '0' ;
|
188 |
|
189 | -- Signal DG13 bilden, es stellt die Zeit des Strahlrücklaufes dar und wird bei
|
190 | -- ZeichenZählerstand(D41_42) 2 rückgesetzt und bei 66 gesetzt
|
191 | DG13 <= '1' when QD41_42 = 66 -- Setzen bei Zählerstand 66
|
192 | else '0' when QD41_42 = 2; -- rücksetzen bei Zählerstand 2
|
193 |
|
194 | -- ******** Erzeugung HK Synchronimpuls aus Zählerkette
|
195 |
|
196 | -- HK Impuls startet bei Zählerstand 69 von QD41_42 und sollte 4,7us=4700ns lang sein
|
197 | HK_Sync <= '1' when QD41_42 = 69 -- 69 im Normalmodus Start bei 69
|
198 | else '0'
|
199 | when QD41_42 = 82 -- 83 im Normalmodus Ende bei 82 (nicht84!")
|
200 | ;
|
201 | -- dieses FlipFlop funktioniert nicht richtig bei CPLD POWER MODE "STD"
|
202 |
|
203 | -- 69 bis 84 wenn Bild steht dann ist es synchron (69..83 wäre richtig) aber Zeilenanfang Schatten
|
204 | -- 69 bis 82 liefert perfektes Bild !!
|
205 |
|
206 | -- ***Ende HK_Sync Impuls ****************************************************************
|
207 |
|
208 | -- ******** Erzeugung VK Synchronimpuls aus Zählerkette
|
209 | -- VK Impuls startet bei Zählerstand 290 von QD43_44_20 und sollte 2,5x64uS=160us(=160.000ns)
|
210 |
|
211 | VK_Sync <= '1' when QD43_44_20 = 290 -- setzen bei 290
|
212 | else '0'
|
213 | when QD43_44_20 = 293 ;
|
214 | -- dieses FlipFlop funktioniert nicht richtig bei CPLD POWER MODE "STD"
|
215 |
|
216 | -- ***Ende VK_Sync Impuls ****************************************************************
|
217 |
|
218 | end VERHALTEN;
|