Subversion Repositories pentevo

Rev

Rev 1063 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1055 lvd 1
// ZX-Evo SDLoad Configuration (c) NedoPC 2023
2
//
3
// video sync module
4
 
5
/*
6
    This file is part of ZX-Evo Base Configuration firmware.
7
 
8
    ZX-Evo Base Configuration firmware is free software:
9
    you can redistribute it and/or modify it under the terms of
10
    the GNU General Public License as published by
11
    the Free Software Foundation, either version 3 of the License, or
12
    (at your option) any later version.
13
 
14
    ZX-Evo Base Configuration firmware is distributed in the hope that
15
    it will be useful, but WITHOUT ANY WARRANTY; without even
16
    the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17
    See the GNU General Public License for more details.
18
 
19
    You should have received a copy of the GNU General Public License
20
    along with ZX-Evo Base Configuration firmware.
21
    If not, see <http://www.gnu.org/licenses/>.
22
*/
23
 
24
module video_sync
25
(
26
        input  wire clk,
27
        input  wire rst_n,
28
 
29
        input  wire vga_on,
1059 lvd 30
        input  wire hsync_polarity, // 1 - positive polarity, 0 - negative
1061 lvd 31
        input  wire vsync_polarity, //
1055 lvd 32
 
1061 lvd 33
        // pixel strobe -- everything happens enabled by this signal
34
        output reg  pix_stb,
1055 lvd 35
 
1061 lvd 36
        // initial sync signals
1063 lvd 37
        output reg  i_hsync,
38
        output reg  i_vsync,
39
        output reg  i_hpix,
40
        output reg  i_vpix,
1061 lvd 41
 
42
        // fetch synchronizing signals
1063 lvd 43
        output reg  v_init, // prepare fetching whole screen
1064 lvd 44
        output reg  v_step, // step to the next screen line
45
        output reg  v_char, // step to the next char line
46
 
1063 lvd 47
        output reg  h_init, // prepare fetching/displaying single line 
48
        output reg  h_char  // strobes 6 pix_stb's before the pix_stb that begins h_pix,
49
                            // then continues throughout the visible area. Ends also 6 pix_stb's
50
                            // before the end of h_pix
1055 lvd 51
);
52
 
53
        parameter H_PERIOD = 9'd448; // in 7MHz clock
54
        //
55
        parameter H_TV_SYNC_END  = 9'd33; // counting starts with HSYNC going active
56
        parameter H_TV_PIX_START = 9'd78;
1059 lvd 57
        parameter H_TV_PIX_STOP  = 9'd438;
1055 lvd 58
        //
59
        parameter H_VGA_SYNC_END  = 9'd53;
60
        parameter H_VGA_PIX_START = 9'd79;
1059 lvd 61
        parameter H_VGA_PIX_STOP  = 9'd439;
1055 lvd 62
 
63
 
64
        parameter V_PERIOD = 9'd262; // in 15625Hz clock
65
        //
1059 lvd 66
        parameter V_SYNC_END = 9'd2; // in TV mode, must be a little longer than exact 2 HSYNC periods. Addition is 78 7MHz clocks
1055 lvd 67
        parameter V_PIX_START = 9'd18;
1059 lvd 68
        parameter V_PIX_STOP  = 9'd258;
1055 lvd 69
 
70
 
71
        reg [1:0] pix_divider = 2'b0;
72
 
73
 
74
        reg [8:0] h_counter = 9'd0;
75
 
76
 
77
        reg v_div2 = 1'b0;
78
 
79
        reg [8:0] v_counter = 9'd0;
80
 
1059 lvd 81
 
1055 lvd 82
 
83
 
84
        // pixel clock strobes
85
        always @(posedge clk)
86
                pix_divider[1:0] <= { pix_divider[0], ~pix_divider[1] };
87
        //
88
        always @(posedge clk)
89
                pix_stb <= vga_on ? (~^pix_divider) : (&pix_divider);
90
 
91
 
92
 
93
        // horizontal counter: counts from 1 to 448
94
        wire h_count_end = &h_counter[8:6]; // 448 is 0x1C0
95
        //
96
        always @(posedge clk)
97
        if( pix_stb )
98
        begin
99
                if( h_count_end )
100
                        h_counter <= 9'd1;
101
                else
102
                        h_counter <= h_counter + 9'd1;
103
        end
104
 
105
        // hsync on/off
106
        wire hsync_on  = h_count_end;
107
        wire hsync_off = vga_on ? (h_counter==H_VGA_SYNC_END) : (h_counter==H_TV_SYNC_END);
108
 
109
        // hpix on/off
110
        wire hpix_on  = vga_on ? (h_counter==H_VGA_PIX_START) : (h_counter==H_TV_PIX_START);
111
        wire hpix_off = vga_on ? (h_counter==H_VGA_PIX_STOP) : (h_counter==H_TV_PIX_STOP);
112
 
113
 
114
        // skip every second vertical count in vga mode
115
        always @(posedge clk)
116
        if( pix_stb && h_count_end )
117
                v_div2 <= vga_on ? (~v_div2) : 1'b1;
118
 
119
        // vertical count strobe
120
        wire v_stb = pix_stb & h_count_end & v_div2;
121
 
122
        // vertical counter: from 1 to 262
123
        wire v_count_end = v_counter[8] & (&v_counter[2:1]); // 262 is 0x106
124
        //
125
        always @(posedge clk)
126
        if( v_stb )
127
        begin
128
                if( v_count_end )
129
                        v_counter <= 9'd1;
130
                else
131
                        v_counter <= v_counter + 9'd1;
132
        end
133
 
134
        // vsync on/off
135
        wire vsync_on  = v_count_end;
136
        wire vsync_off = (v_counter==V_SYNC_END);
137
 
138
        // vpix on/off
139
        wire vpix_on  = (v_counter==V_PIX_START);
140
        wire vpix_off = (v_counter==V_PIX_STOP);
141
 
142
 
1059 lvd 143
        // make initial sync signals
144
        always @(posedge clk)
145
        if( pix_stb )
146
        begin
147
                if( hsync_on )
148
                        i_hsync <= hsync_polarity;
149
                else if( hsync_off )
150
                        i_hsync <= ~hsync_polarity;
1055 lvd 151
 
1059 lvd 152
                if( hpix_on )
153
                        i_hpix <= 1'b1;
154
                else if( hpix_off )
155
                        i_hpix <= 1'b0;
156
        end
157
        //
158
        // vsync in tv mode must be 78 pix_stb's longer
159
        reg [7:0] extra_vsync_count;
160
        reg       extra_vsync_count_r;
161
        always @(posedge clk)
162
        if( v_stb && vsync_off )
163
                        extra_vsync_count <= 8'd77 + 8'h80;
164
        else if( pix_stb && extra_vsync_count[7] )
165
                        extra_vsync_count <= extra_vsync_count - 8'd1;
166
        //
167
        always @(posedge clk)
168
        if( pix_stb )
169
                extra_vsync_count_r <= extra_vsync_count[7];
170
        //
171
        always @(posedge clk)
172
        begin
173
                if( v_stb && vsync_on )
174
                        i_vsync <= vsync_polarity;
175
                else if( vga_on ? (v_stb && vsync_off) : (pix_stb && extra_vsync_count_r && !extra_vsync_count[7]) )
176
                        i_vsync <= ~vsync_polarity;
177
        end
178
        //
179
        always @(posedge clk)
180
        if( v_stb )
181
        begin
182
                if( vpix_on )
183
                        i_vpix <= 1'b1;
184
                else if( vpix_off )
185
                        i_vpix <= 1'b0;
186
        end
1055 lvd 187
 
188
 
189
 
1064 lvd 190
        // vertical fetch syncs
191
 
1061 lvd 192
        always @(posedge clk)
193
        if( pix_stb )
194
        begin
195
                if( v_stb && vsync_off )
196
                        v_init <= 1'b1;
197
                else
198
                        v_init <= 1'b0;
199
        end
1064 lvd 200
 
201
 
202
        reg [2:0] vctr_6;
1061 lvd 203
        always @(posedge clk)
204
        if( pix_stb )
205
        begin
1064 lvd 206
                if( ?? )
207
                        vctr_6
208
                else if( v_stb )
209
                        vctr_6 <= (vctr_6[2] & vctr_6[0]) ? 3'd0 : (vctr_6 + 3'd1);
1061 lvd 210
        end
1064 lvd 211
 
212
 
1061 lvd 213
        always @(posedge clk)
214
        if( pix_stb )
215
        begin
216
                if( i_vpix && v_stb )
1064 lvd 217
                        v_step <= 1'b1;
1061 lvd 218
                else
1064 lvd 219
                        v_step <= 1'b0;
1061 lvd 220
        end
1064 lvd 221
 
1059 lvd 222
 
1064 lvd 223
 
224
 
225
        // horizontal fetch syncs
226
 
227
        always @(posedge clk)
228
        if( pix_stb )
229
        begin
230
                if( hsync_off )
231
                        h_init <= 1'b1;
232
                else
233
                        h_init <= 1'b0;
234
        end
235
 
1063 lvd 236
 
237
        wire start_char = vga_on ? (h_counter==(H_VGA_PIX_START-7)) : (h_counter==(H_TV_PIX_START-7));
238
        wire stop_char  = vga_on ? (h_counter==(H_VGA_PIX_STOP -7)) : (h_counter==(H_TV_PIX_STOP -7));
1059 lvd 239
 
1063 lvd 240
        reg char;
241
        always @(posedge clk)
242
        if( pix_stb )
243
                if( start_char )
244
                        char <= 1'b1;
245
                else if( stop_char )
246
                        char <= 1'b0;
247
 
248
        // MOD 6 counter
249
        reg [2:0] char_ctr;
250
        //
251
        always @(posedge clk)
252
        if( pix_stb )
253
        begin
254
                if( start_char )
255
                        char_ctr <= 3'd0;
256
                else
257
                        char_ctr <= (char_ctr[2] & char_ctr[0]) ? 3'd0 : (char_ctr + 3'd1);
258
        end
259
        //
260
 
261
        //
262
        always @(posedge clk)
263
        if( pix_stb )
264
        begin
265
                if( start_char )
266
                        h_char <= 1'b1;
267
                else if( char && (char_ctr[2] & char_ctr[0]) )
268
                        h_char <= 1'b1;
269
                else
270
                        h_char <= 1'b0;
271
        end
272
 
273
 
274
 
275
 
1055 lvd 276
endmodule
277