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

Subversion Repositories ao486

[/] [ao486/] [trunk/] [rtl/] [soc/] [vga/] [vga.v] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 alfik
/*
2
 * Copyright (c) 2014, Aleksander Osman
3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions are met:
7
 *
8
 * * Redistributions of source code must retain the above copyright notice, this
9
 *   list of conditions and the following disclaimer.
10
 *
11
 * * Redistributions in binary form must reproduce the above copyright notice,
12
 *   this list of conditions and the following disclaimer in the documentation
13
 *   and/or other materials provided with the distribution.
14
 *
15
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
 */
26
 
27
module vga(
28
    input               clk_26,
29
    input               rst_n,
30
 
31
    //avalon slave for system overlay
32
    input       [7:0]   sys_address,
33
    input               sys_read,
34
    output      [31:0]  sys_readdata,
35
    input               sys_write,
36
    input       [31:0]  sys_writedata,
37
 
38
    //avalon slave vga io
39
    input       [3:0]   io_b_address,
40
    input               io_b_read,
41
    output      [7:0]   io_b_readdata,
42
    input               io_b_write,
43
    input       [7:0]   io_b_writedata,
44
 
45
    //avalon slave vga io
46
    input       [3:0]   io_c_address,
47
    input               io_c_read,
48
    output      [7:0]   io_c_readdata,
49
    input               io_c_write,
50
    input       [7:0]   io_c_writedata,
51
 
52
    //avalon slave vga io
53
    input       [3:0]   io_d_address,
54
    input               io_d_read,
55
    output      [7:0]   io_d_readdata,
56
    input               io_d_write,
57
    input       [7:0]   io_d_writedata,
58
 
59
    //avalon slave vga memory
60
    input       [16:0]  mem_address,
61
    input               mem_read,
62
    output      [7:0]   mem_readdata,
63
    input               mem_write,
64
    input       [7:0]   mem_writedata,
65
 
66
    //vga
67
    output              vga_clock,
68
    output              vga_sync_n,
69
    output              vga_blank_n,
70
    output              vga_horiz_sync,
71
    output              vga_vert_sync,
72
 
73
    output      [7:0]   vga_r,
74
    output      [7:0]   vga_g,
75
    output      [7:0]   vga_b
76
);
77
 
78
//------------------------------------------------------------------------------
79
 
80
//not needed sys_read_valid
81
 
82
reg io_b_read_last;
83
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) io_b_read_last <= 1'b0; else if(io_b_read_last) io_b_read_last <= 1'b0; else io_b_read_last <= io_b_read; end
84
wire io_b_read_valid = io_b_read && io_b_read_last == 1'b0;
85
 
86
reg io_c_read_last;
87
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) io_c_read_last <= 1'b0; else if(io_c_read_last) io_c_read_last <= 1'b0; else io_c_read_last <= io_c_read; end
88
wire io_c_read_valid = io_c_read && io_c_read_last == 1'b0;
89
 
90
reg io_d_read_last;
91
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) io_d_read_last <= 1'b0; else if(io_d_read_last) io_d_read_last <= 1'b0; else io_d_read_last <= io_d_read; end
92
wire io_d_read_valid = io_d_read && io_d_read_last == 1'b0;
93
 
94
reg mem_read_last;
95
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) mem_read_last <= 1'b0; else if(mem_read_last) mem_read_last <= 1'b0; else mem_read_last <= mem_read; end
96
wire mem_read_valid = mem_read && mem_read_last == 1'b0;
97
 
98
//------------------------------------------------------------------------------
99
 
100
wire [7:0] io_writedata =
101
    (io_b_write)?   io_b_writedata :
102
    (io_c_write)?   io_c_writedata :
103
                    io_d_writedata;
104
 
105
//------------------------------------------------------------------------------ sequencer io
106
 
107
reg seq_async_reset_n;
108
reg seq_sync_reset_n;
109
 
110
reg seq_8dot_char;
111
 
112
reg seq_dotclock_divided;
113
 
114
reg seq_screen_disable; //sync works, data blank
115
 
116
reg [3:0] seq_map_write_enable;
117
 
118
reg [2:0] seq_char_map_a; // depends on seq_access_256kb
119
reg [2:0] seq_char_map_b; // depends on seq_access_256kb
120
 
121
reg seq_access_256kb;
122
reg seq_access_odd_even_disabled;
123
reg seq_access_chain4;
124
 
125
// not implemented sequencer regs: 
126
reg seq_not_impl_shift_load_2;
127
reg seq_not_impl_shift_load_4;
128
 
129
//------------------------------------------------------------------------------
130
 
131
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) seq_async_reset_n <= 1'b1; else if(seq_io_write && seq_io_index == 3'd0) seq_async_reset_n <= io_writedata[0]; end
132
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) seq_sync_reset_n  <= 1'b1; else if(seq_io_write && seq_io_index == 3'd0) seq_sync_reset_n  <= io_writedata[1]; end
133
 
134
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) seq_8dot_char        <= 1'b1; else if(seq_io_write && seq_io_index == 3'd1) seq_8dot_char        <= io_writedata[0]; end
135
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) seq_dotclock_divided <= 1'b0; else if(seq_io_write && seq_io_index == 3'd1) seq_dotclock_divided <= io_writedata[3]; end
136
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) seq_screen_disable   <= 1'b0; else if(seq_io_write && seq_io_index == 3'd1) seq_screen_disable   <= io_writedata[5]; end
137
 
138
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) seq_map_write_enable <= 4'hF; else if(seq_io_write && seq_io_index == 3'd2) seq_map_write_enable <= io_writedata[3:0]; end
139
 
140
always @(posedge clk_26 or negedge rst_n) begin
141
    if(rst_n == 1'b0)                               seq_char_map_a <= 3'd0;
142
    else if(seq_io_write && seq_io_index == 3'd3)   seq_char_map_a <= { io_writedata[5], io_writedata[3:2] };
143
    else if(seq_sync_reset_n || seq_async_reset_n)  seq_char_map_a <= 3'd0;
144
end
145
 
146
always @(posedge clk_26 or negedge rst_n) begin
147
    if(rst_n == 1'b0)                               seq_char_map_b <= 3'd0;
148
    else if(seq_io_write && seq_io_index == 3'd3)   seq_char_map_b <= { io_writedata[4], io_writedata[1:0] };
149
    else if(seq_sync_reset_n || seq_async_reset_n)  seq_char_map_b <= 3'd0;
150
end
151
 
152
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) seq_access_256kb             <= 1'b1; else if(seq_io_write && seq_io_index == 3'd4) seq_access_256kb             <= io_writedata[1]; end
153
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) seq_access_odd_even_disabled <= 1'b1; else if(seq_io_write && seq_io_index == 3'd4) seq_access_odd_even_disabled <= io_writedata[2]; end
154
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) seq_access_chain4            <= 1'b1; else if(seq_io_write && seq_io_index == 3'd4) seq_access_chain4            <= io_writedata[3]; end
155
 
156
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) seq_not_impl_shift_load_2 <= 1'b0; else if(seq_io_write && seq_io_index == 3'd1) seq_not_impl_shift_load_2 <= io_writedata[2]; end
157
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) seq_not_impl_shift_load_4 <= 1'b0; else if(seq_io_write && seq_io_index == 3'd1) seq_not_impl_shift_load_4 <= io_writedata[4]; end
158
 
159
//------------------------------------------------------------------------------
160
 
161
wire [7:0] host_io_read_seq =
162
    (seq_io_index == 3'd0)?     { 6'd0, seq_sync_reset_n, seq_async_reset_n } :
163
    (seq_io_index == 3'd1)?     { 2'd0, seq_screen_disable, seq_not_impl_shift_load_4, seq_dotclock_divided, seq_not_impl_shift_load_2, 1'b0, seq_8dot_char } :
164
    (seq_io_index == 3'd2)?     { 4'd0, seq_map_write_enable } :
165
    (seq_io_index == 3'd3)?     { 2'd0, seq_char_map_a[2], seq_char_map_b[2], seq_char_map_a[1:0], seq_char_map_b[1:0] } :
166
    (seq_io_index == 3'd4)?     { 4'd0, seq_access_chain4, seq_access_odd_even_disabled, seq_access_256kb, 1'b0 } :
167
                                8'h00;
168
 
169
//------------------------------------------------------------------------------ crtc io
170
 
171
reg [7:0]   crtc_horizontal_total;
172
reg [7:0]   crtc_horizontal_display_size;
173
reg [7:0]   crtc_horizontal_blanking_start;
174
reg [5:0]   crtc_horizontal_blanking_end;
175
reg [7:0]   crtc_horizontal_retrace_start;
176
reg [1:0]   crtc_horizontal_retrace_skew;
177
reg [4:0]   crtc_horizontal_retrace_end;
178
 
179
reg [9:0]   crtc_vertical_total;
180
reg [9:0]   crtc_vertical_retrace_start;
181
reg [3:0]   crtc_vertical_retrace_end;
182
reg [9:0]   crtc_vertical_display_size;
183
reg [9:0]   crtc_vertical_blanking_start;
184
reg [7:0]   crtc_vertical_blanking_end;
185
 
186
reg         crtc_vertical_doublescan;
187
 
188
reg [4:0]   crtc_row_preset;
189
reg [4:0]   crtc_row_max;
190
reg [4:0]   crtc_row_underline;
191
 
192
reg         crtc_cursor_off;
193
reg [4:0]   crtc_cursor_row_start;
194
reg [4:0]   crtc_cursor_row_end;
195
reg [1:0]   crtc_cursor_skew;
196
 
197
reg [15:0]  crtc_address_start;
198
reg [1:0]   crtc_address_byte_panning;
199
reg [7:0]   crtc_address_offset;
200
reg [15:0]  crtc_address_cursor;
201
reg         crtc_address_doubleword;
202
reg         crtc_address_byte;
203
reg         crtc_address_bit0;
204
reg         crtc_address_bit13;
205
reg         crtc_address_bit14;
206
 
207
reg         crtc_enable_sync;
208
 
209
reg [9:0]   crtc_line_compare;
210
 
211
reg         crtc_protect;
212
 
213
//not implemented crtc regs:
214
reg [1:0]   crtc_not_impl_display_enable_skew;
215
reg         crtc_not_impl_clear_vert_int;
216
reg         crtc_not_impl_enable_vert_int;
217
reg         crtc_not_impl_5_refresh_cycles;
218
reg         crtc_not_impl_scan_line_clk_div_2;
219
reg         crtc_not_impl_address_clk_div_2;
220
reg         crtc_not_impl_address_clk_div_4;
221
 
222
//------------------------------------------------------------------------------
223
 
224
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) crtc_horizontal_total          <= 8'd95; else if(crtc_io_write && crtc_io_index == 5'h00) crtc_horizontal_total          <= io_writedata[7:0]; end
225
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) crtc_horizontal_display_size   <= 8'd79; else if(crtc_io_write && crtc_io_index == 5'h01) crtc_horizontal_display_size   <= io_writedata[7:0]; end
226
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) crtc_horizontal_blanking_start <= 8'd80; else if(crtc_io_write && crtc_io_index == 5'h02) crtc_horizontal_blanking_start <= io_writedata[7:0]; end
227
 
228
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) crtc_not_impl_display_enable_skew <= 2'd0; else if(crtc_io_write && crtc_io_index == 5'h03) crtc_not_impl_display_enable_skew <= io_writedata[6:5]; end
229
 
230
always @(posedge clk_26 or negedge rst_n) begin
231
    if(rst_n == 1'b0)                                   crtc_horizontal_blanking_end <= 6'd34;
232
    else if(crtc_io_write && crtc_io_index == 5'h03)    crtc_horizontal_blanking_end <= { crtc_horizontal_blanking_end[5], io_writedata[4:0] };
233
    else if(crtc_io_write && crtc_io_index == 5'h05)    crtc_horizontal_blanking_end <= { io_writedata[7], crtc_horizontal_blanking_end[4:0] };
234
end
235
 
236
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) crtc_horizontal_retrace_start <= 8'd84; else if(crtc_io_write && crtc_io_index == 5'h04) crtc_horizontal_retrace_start <= io_writedata[7:0]; end
237
 
238
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) crtc_horizontal_retrace_skew <= 2'd0; else if(crtc_io_write && crtc_io_index == 5'h05) crtc_horizontal_retrace_skew <= io_writedata[6:5]; end
239
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) crtc_horizontal_retrace_end  <= 5'd0; else if(crtc_io_write && crtc_io_index == 5'h05) crtc_horizontal_retrace_end  <= io_writedata[4:0]; end
240
 
241
always @(posedge clk_26 or negedge rst_n) begin
242
    if(rst_n == 1'b0)                                   crtc_vertical_total <= 10'd447;
243
    else if(crtc_io_write && crtc_io_index == 5'h06)    crtc_vertical_total <= { crtc_vertical_total[9:8], io_writedata[7:0] };
244
    else if(crtc_io_write && crtc_io_index == 5'h07)    crtc_vertical_total <= { io_writedata[5], io_writedata[0], crtc_vertical_total[7:0] };
245
end
246
 
247
always @(posedge clk_26 or negedge rst_n) begin
248
    if(rst_n == 1'b0)                                   crtc_vertical_retrace_start <= 10'd412;
249
    else if(crtc_io_write && crtc_io_index == 5'h10)    crtc_vertical_retrace_start <= { crtc_vertical_retrace_start[9:8], io_writedata[7:0] };
250
    else if(crtc_io_write && crtc_io_index == 5'h07)    crtc_vertical_retrace_start <= { io_writedata[7], io_writedata[2], crtc_vertical_retrace_start[7:0] };
251
end
252
 
253
always @(posedge clk_26 or negedge rst_n) begin
254
    if(rst_n == 1'b0)                                   crtc_vertical_display_size <= 10'd399;
255
    else if(crtc_io_write && crtc_io_index == 5'h12)    crtc_vertical_display_size <= { crtc_vertical_display_size[9:8], io_writedata[7:0] };
256
    else if(crtc_io_write && crtc_io_index == 5'h07)    crtc_vertical_display_size <= { io_writedata[6], io_writedata[1], crtc_vertical_display_size[7:0] };
257
end
258
 
259
always @(posedge clk_26 or negedge rst_n) begin
260
    if(rst_n == 1'b0)                                           crtc_line_compare <= 10'd1023;
261
    else if(crtc_io_write_compare && crtc_io_index == 5'h18)    crtc_line_compare <= { crtc_line_compare[9:8], io_writedata[7:0] };
262
    else if(crtc_io_write_compare && crtc_io_index == 5'h07)    crtc_line_compare <= { crtc_line_compare[9], io_writedata[4], crtc_line_compare[7:0] };
263
    else if(crtc_io_write_compare && crtc_io_index == 5'h09)    crtc_line_compare <= { io_writedata[6], crtc_line_compare[8:0] };
264
end
265
 
266
always @(posedge clk_26 or negedge rst_n) begin
267
    if(rst_n == 1'b0)                                   crtc_vertical_blanking_start <= 10'd406;
268
    else if(crtc_io_write && crtc_io_index == 5'h15)    crtc_vertical_blanking_start <= { crtc_vertical_blanking_start[9:8], io_writedata[7:0] };
269
    else if(crtc_io_write && crtc_io_index == 5'h07)    crtc_vertical_blanking_start <= { crtc_vertical_blanking_start[9], io_writedata[3], crtc_vertical_blanking_start[7:0] };
270
    else if(crtc_io_write && crtc_io_index == 5'h09)    crtc_vertical_blanking_start <= { io_writedata[5], crtc_vertical_blanking_start[8:0] };
271
end
272
 
273
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) crtc_address_byte_panning <= 2'd0; else if(crtc_io_write && crtc_io_index == 5'h08) crtc_address_byte_panning <= io_writedata[6:5]; end
274
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) crtc_row_preset           <= 5'd0; else if(crtc_io_write && crtc_io_index == 5'h08) crtc_row_preset           <= io_writedata[4:0]; end
275
 
276
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) crtc_vertical_doublescan  <= 1'd0; else if(crtc_io_write && crtc_io_index == 5'h09) crtc_vertical_doublescan  <= io_writedata[7]; end
277
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) crtc_row_max              <= 5'd1; else if(crtc_io_write && crtc_io_index == 5'h09) crtc_row_max              <= io_writedata[4:0]; end
278
 
279
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) crtc_cursor_off           <= 1'd0; else if(crtc_io_write && crtc_io_index == 5'h0A) crtc_cursor_off           <= io_writedata[5]; end
280
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) crtc_cursor_row_start     <= 5'd0; else if(crtc_io_write && crtc_io_index == 5'h0A) crtc_cursor_row_start     <= io_writedata[4:0]; end
281
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) crtc_cursor_skew          <= 2'd0; else if(crtc_io_write && crtc_io_index == 5'h0B) crtc_cursor_skew          <= io_writedata[6:5]; end
282
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) crtc_cursor_row_end       <= 5'd0; else if(crtc_io_write && crtc_io_index == 5'h0B) crtc_cursor_row_end       <= io_writedata[4:0]; end
283
 
284
always @(posedge clk_26 or negedge rst_n) begin
285
    if(rst_n == 1'b0)                                   crtc_address_start <= 16'd0;
286
    else if(crtc_io_write && crtc_io_index == 5'h0C)    crtc_address_start <= { io_writedata[7:0], crtc_address_start[7:0] };
287
    else if(crtc_io_write && crtc_io_index == 5'h0D)    crtc_address_start <= { crtc_address_start[15:8], io_writedata[7:0] };
288
end
289
 
290
always @(posedge clk_26 or negedge rst_n) begin
291
    if(rst_n == 1'b0)                                   crtc_address_cursor <= 16'd0;
292
    else if(crtc_io_write && crtc_io_index == 5'h0E)    crtc_address_cursor <= { io_writedata[7:0], crtc_address_cursor[7:0] };
293
    else if(crtc_io_write && crtc_io_index == 5'h0F)    crtc_address_cursor <= { crtc_address_cursor[15:8], io_writedata[7:0] };
294
end
295
 
296
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) crtc_protect                   <= 1'd1;  else if(crtc_io_write && crtc_io_index == 5'h11) crtc_protect                   <= io_writedata[7]; end
297
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) crtc_not_impl_5_refresh_cycles <= 1'd0;  else if(crtc_io_write && crtc_io_index == 5'h11) crtc_not_impl_5_refresh_cycles <= io_writedata[6]; end
298
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) crtc_not_impl_enable_vert_int  <= 1'd0;  else if(crtc_io_write && crtc_io_index == 5'h11) crtc_not_impl_enable_vert_int  <= io_writedata[5]; end
299
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) crtc_not_impl_clear_vert_int   <= 1'd0;  else if(crtc_io_write && crtc_io_index == 5'h11) crtc_not_impl_clear_vert_int   <= io_writedata[4]; end
300
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) crtc_vertical_retrace_end      <= 4'd14; else if(crtc_io_write && crtc_io_index == 5'h11) crtc_vertical_retrace_end      <= io_writedata[3:0]; end
301
 
302
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) crtc_address_offset            <= 8'd40; else if(crtc_io_write && crtc_io_index == 5'h13) crtc_address_offset            <= io_writedata[7:0]; end
303
 
304
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) crtc_address_doubleword         <= 1'b1; else if(crtc_io_write && crtc_io_index == 5'h14) crtc_address_doubleword        <= io_writedata[6]; end
305
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) crtc_not_impl_address_clk_div_4 <= 1'b0; else if(crtc_io_write && crtc_io_index == 5'h14) crtc_not_impl_address_clk_div_4<= io_writedata[5]; end
306
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) crtc_row_underline              <= 5'd0; else if(crtc_io_write && crtc_io_index == 5'h14) crtc_row_underline             <= io_writedata[4:0]; end
307
 
308
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) crtc_vertical_blanking_end <= 8'd185; else if(crtc_io_write && crtc_io_index == 5'h16) crtc_vertical_blanking_end <= io_writedata[7:0]; end
309
 
310
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) crtc_enable_sync                  <= 1'd1;  else if(crtc_io_write && crtc_io_index == 5'h17) crtc_enable_sync                  <= io_writedata[7]; end
311
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) crtc_address_byte                 <= 1'd0;  else if(crtc_io_write && crtc_io_index == 5'h17) crtc_address_byte                 <= io_writedata[6]; end
312
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) crtc_address_bit0                 <= 1'd1;  else if(crtc_io_write && crtc_io_index == 5'h17) crtc_address_bit0                 <= io_writedata[5]; end
313
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) crtc_not_impl_address_clk_div_2   <= 1'd0;  else if(crtc_io_write && crtc_io_index == 5'h17) crtc_not_impl_address_clk_div_2   <= io_writedata[3]; end
314
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) crtc_not_impl_scan_line_clk_div_2 <= 1'd0;  else if(crtc_io_write && crtc_io_index == 5'h17) crtc_not_impl_scan_line_clk_div_2 <= io_writedata[2]; end
315
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) crtc_address_bit14                <= 1'd1;  else if(crtc_io_write && crtc_io_index == 5'h17) crtc_address_bit14                <= io_writedata[1]; end
316
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) crtc_address_bit13                <= 1'd1;  else if(crtc_io_write && crtc_io_index == 5'h17) crtc_address_bit13                <= io_writedata[0]; end
317
 
318
//------------------------------------------------------------------------------
319
 
320
wire [7:0] host_io_read_crtc =
321
    (crtc_io_index == 5'h00)?       crtc_horizontal_total :
322
    (crtc_io_index == 5'h01)?       crtc_horizontal_display_size :
323
    (crtc_io_index == 5'h02)?       crtc_horizontal_blanking_start :
324
    (crtc_io_index == 5'h03)?       { 1'b1, crtc_not_impl_display_enable_skew, crtc_horizontal_blanking_end[4:0] } :
325
    (crtc_io_index == 5'h04)?       crtc_horizontal_retrace_start :
326
    (crtc_io_index == 5'h05)?       { crtc_horizontal_blanking_end[5], crtc_horizontal_retrace_skew, crtc_horizontal_retrace_end } :
327
    (crtc_io_index == 5'h06)?       crtc_vertical_total[7:0] :
328
    (crtc_io_index == 5'h07)?       { crtc_vertical_retrace_start[9], crtc_vertical_display_size[9], crtc_vertical_total[9], crtc_line_compare[8], crtc_vertical_blanking_start[8],
329
                                      crtc_vertical_retrace_start[8], crtc_vertical_display_size[8], crtc_vertical_total[8] } :
330
    (crtc_io_index == 5'h08)?       { 1'b0, crtc_address_byte_panning, crtc_row_preset } :
331
    (crtc_io_index == 5'h09)?       { crtc_vertical_doublescan, crtc_line_compare[9], crtc_vertical_blanking_start[9], crtc_row_max } :
332
    (crtc_io_index == 5'h0A)?       { 2'b0, crtc_cursor_off, crtc_cursor_row_start } :
333
    (crtc_io_index == 5'h0B)?       { 1'b0, crtc_cursor_skew, crtc_cursor_row_end } :
334
    (crtc_io_index == 5'h0C)?       crtc_address_start[15:8] :
335
    (crtc_io_index == 5'h0D)?       crtc_address_start[7:0] :
336
    (crtc_io_index == 5'h0E)?       crtc_address_cursor[15:8] :
337
    (crtc_io_index == 5'h0F)?       crtc_address_cursor[7:0] :
338
    (crtc_io_index == 5'h10)?       crtc_vertical_retrace_start[7:0] :
339
    (crtc_io_index == 5'h11)?       { crtc_protect, crtc_not_impl_5_refresh_cycles, crtc_not_impl_enable_vert_int, crtc_not_impl_clear_vert_int, crtc_vertical_retrace_end } :
340
    (crtc_io_index == 5'h12)?       crtc_vertical_display_size[7:0] :
341
    (crtc_io_index == 5'h13)?       crtc_address_offset :
342
    (crtc_io_index == 5'h14)?       { 1'b0, crtc_address_doubleword, crtc_not_impl_address_clk_div_4, crtc_row_underline } :
343
    (crtc_io_index == 5'h15)?       crtc_vertical_blanking_start[7:0] :
344
    (crtc_io_index == 5'h16)?       crtc_vertical_blanking_end :
345
    (crtc_io_index == 5'h17)?       { crtc_enable_sync, crtc_address_byte, crtc_address_bit0, 1'b0, crtc_not_impl_address_clk_div_2, crtc_not_impl_scan_line_clk_div_2, crtc_address_bit14, crtc_address_bit13 } :
346
    (crtc_io_index == 5'h18)?       crtc_line_compare[7:0] :
347
                                    8'h00;
348
 
349
//------------------------------------------------------------------------------ graphic io                                    
350
 
351
reg [3:0] graph_color_compare_map;
352
reg [3:0] graph_color_compare_dont_care;
353
 
354
reg [3:0] graph_write_set_map;
355
reg [3:0] graph_write_enable_map;
356
reg [1:0] graph_write_function;
357
reg [2:0] graph_write_rotate;
358
reg [7:0] graph_write_mask;
359
reg [1:0] graph_write_mode;
360
 
361
reg [1:0] graph_read_map_select;
362
reg       graph_read_mode;
363
 
364
reg [1:0] graph_shift_mode;
365
 
366
reg [1:0] graph_system_memory;
367
 
368
//not implemented graphic regs:
369
reg       graph_not_impl_chain_odd_even;
370
reg       graph_not_impl_host_odd_even;
371
reg       graph_not_impl_graphic_mode;
372
 
373
//------------------------------------------------------------------------------
374
 
375
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) graph_write_set_map     <= 4'd0; else if(graph_io_write && graph_io_index == 4'd0) graph_write_set_map     <= io_writedata[3:0]; end
376
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) graph_write_enable_map  <= 4'd0; else if(graph_io_write && graph_io_index == 4'd1) graph_write_enable_map  <= io_writedata[3:0]; end
377
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) graph_color_compare_map <= 4'd0; else if(graph_io_write && graph_io_index == 4'd2) graph_color_compare_map <= io_writedata[3:0]; end
378
 
379
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) graph_write_function <= 2'd0; else if(graph_io_write && graph_io_index == 4'd3) graph_write_function <= io_writedata[4:3]; end
380
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) graph_write_rotate   <= 3'd0; else if(graph_io_write && graph_io_index == 4'd3) graph_write_rotate   <= io_writedata[2:0]; end
381
 
382
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) graph_read_map_select<= 2'd0; else if(graph_io_write && graph_io_index == 4'd4) graph_read_map_select <= io_writedata[1:0]; end
383
 
384
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) graph_shift_mode             <= 2'd2; else if(graph_io_write && graph_io_index == 4'd5) graph_shift_mode             <= io_writedata[6:5]; end
385
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) graph_not_impl_host_odd_even <= 1'd0; else if(graph_io_write && graph_io_index == 4'd5) graph_not_impl_host_odd_even <= io_writedata[4]; end
386
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) graph_read_mode              <= 1'd0; else if(graph_io_write && graph_io_index == 4'd5) graph_read_mode              <= io_writedata[3]; end
387
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) graph_write_mode             <= 2'd0; else if(graph_io_write && graph_io_index == 4'd5) graph_write_mode             <= io_writedata[1:0]; end
388
 
389
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) graph_system_memory           <= 2'd1; else if(graph_io_write && graph_io_index == 4'd6) graph_system_memory           <= io_writedata[3:2]; end
390
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) graph_not_impl_chain_odd_even <= 1'd0; else if(graph_io_write && graph_io_index == 4'd6) graph_not_impl_chain_odd_even <= io_writedata[1]; end
391
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) graph_not_impl_graphic_mode   <= 1'd1; else if(graph_io_write && graph_io_index == 4'd6) graph_not_impl_graphic_mode   <= io_writedata[0]; end
392
 
393
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) graph_color_compare_dont_care <= 4'hF; else if(graph_io_write && graph_io_index == 4'd7) graph_color_compare_dont_care <= io_writedata[3:0]; end
394
 
395
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) graph_write_mask <= 8'hFF; else if(graph_io_write && graph_io_index == 4'd8) graph_write_mask <= io_writedata[7:0]; end
396
 
397
//------------------------------------------------------------------------------
398
 
399
wire [7:0] host_io_read_graph =
400
    (graph_io_index == 4'd0)?       { 4'b0, graph_write_set_map } :
401
    (graph_io_index == 4'd1)?       { 4'b0, graph_write_enable_map } :
402
    (graph_io_index == 4'd2)?       { 4'b0, graph_color_compare_map } :
403
    (graph_io_index == 4'd3)?       { 3'b0, graph_write_function, graph_write_rotate } :
404
    (graph_io_index == 4'd4)?       { 6'd0, graph_read_map_select } :
405
    (graph_io_index == 4'd5)?       { 1'b0, graph_shift_mode, graph_not_impl_host_odd_even, graph_read_mode, 1'b0, graph_write_mode } :
406
    (graph_io_index == 4'd6)?       { 4'd0, graph_system_memory, graph_not_impl_chain_odd_even, graph_not_impl_graphic_mode } :
407
    (graph_io_index == 4'd7)?       { 4'd0, graph_color_compare_dont_care } :
408
    (graph_io_index == 4'd8)?       graph_write_mask :
409
                                    8'h00;
410
 
411
//------------------------------------------------------------------------------ attribute io
412
 
413
reg       attrib_color_8bit_enable;
414
 
415
reg       attrib_color_bit5_4_enable;
416
reg [1:0] attrib_color_bit7_6_value;
417
reg [1:0] attrib_color_bit5_4_value;
418
 
419
reg       attrib_panning_after_compare_match;
420
 
421
reg [3:0] attrib_panning_value;
422
 
423
reg       attrib_blinking;
424
 
425
reg       attrib_9bit_same_as_8bit;
426
 
427
reg       attrib_graphic_mode;
428
 
429
reg [7:0] attrib_color_overscan;
430
 
431
reg [3:0] attrib_mask;
432
 
433
//not implemented attribute regs:
434
reg attrib_not_impl_mono_emulation;
435
 
436
//------------------------------------------------------------------------------
437
 
438
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) attrib_color_bit5_4_enable         <= 1'd0; else if(attrib_io_write && attrib_io_index == 5'h10) attrib_color_bit5_4_enable         <= io_writedata[7]; end
439
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) attrib_color_8bit_enable           <= 1'd1; else if(attrib_io_write && attrib_io_index == 5'h10) attrib_color_8bit_enable           <= io_writedata[6]; end
440
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) attrib_panning_after_compare_match <= 1'd0; else if(attrib_io_write && attrib_io_index == 5'h10) attrib_panning_after_compare_match <= io_writedata[5]; end
441
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) attrib_blinking                    <= 1'd0; else if(attrib_io_write && attrib_io_index == 5'h10) attrib_blinking                    <= io_writedata[3]; end
442
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) attrib_9bit_same_as_8bit           <= 1'd0; else if(attrib_io_write && attrib_io_index == 5'h10) attrib_9bit_same_as_8bit           <= io_writedata[2]; end
443
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) attrib_not_impl_mono_emulation     <= 1'd0; else if(attrib_io_write && attrib_io_index == 5'h10) attrib_not_impl_mono_emulation     <= io_writedata[1]; end
444
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) attrib_graphic_mode                <= 1'd1; else if(attrib_io_write && attrib_io_index == 5'h10) attrib_graphic_mode                <= io_writedata[0]; end
445
 
446
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) attrib_color_overscan <= 8'd0;        else if(attrib_io_write && attrib_io_index == 5'h11) attrib_color_overscan <= io_writedata[7:0]; end
447
 
448
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) attrib_mask <= 4'hF;                  else if(attrib_io_write && attrib_io_index == 5'h12) attrib_mask <= io_writedata[3:0]; end
449
 
450
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) attrib_panning_value <= 4'd0;         else if(attrib_io_write && attrib_io_index == 5'h13) attrib_panning_value <= io_writedata[3:0]; end
451
 
452
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) attrib_color_bit7_6_value <= 2'd0;    else if(attrib_io_write && attrib_io_index == 5'h14) attrib_color_bit7_6_value <= io_writedata[3:2]; end
453
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) attrib_color_bit5_4_value <= 2'd0;    else if(attrib_io_write && attrib_io_index == 5'h14) attrib_color_bit5_4_value <= io_writedata[1:0]; end
454
 
455
//------------------------------------------------------------------------------
456
 
457
wire [7:0] host_io_read_attrib =
458
    (attrib_io_index == 5'h10)?     { attrib_color_bit5_4_enable, attrib_color_8bit_enable, attrib_panning_after_compare_match, 1'b0,
459
                                      attrib_blinking, attrib_9bit_same_as_8bit, attrib_not_impl_mono_emulation, attrib_graphic_mode } :
460
    (attrib_io_index == 5'h11)?     attrib_color_overscan :
461
    (attrib_io_index == 5'h12)?     { 4'd0, attrib_mask } :
462
    (attrib_io_index == 5'h13)?     { 4'd0, attrib_panning_value } :
463
    (attrib_io_index == 5'h14)?     { 4'd0, attrib_color_bit7_6_value, attrib_color_bit5_4_value } :
464
                                    8'h00;
465
 
466
//------------------------------------------------------------------------------ external io
467
 
468
reg general_vsync;
469
reg general_hsync;
470
 
471
reg general_enable_ram;
472
reg general_io_space;
473
 
474
//not implemented external regs:
475
reg [1:0] general_not_impl_clock_select;
476
reg       general_not_impl_odd_even_page;
477
 
478
//------------------------------------------------------------------------------
479
 
480
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) general_vsync <= 1'd0;                    else if(general_io_write_misc) general_vsync <= io_writedata[7]; end
481
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) general_hsync <= 1'd1;                    else if(general_io_write_misc) general_hsync <= io_writedata[6]; end
482
 
483
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) general_not_impl_odd_even_page <= 1'd1;   else if(general_io_write_misc) general_not_impl_odd_even_page <= io_writedata[5]; end
484
 
485
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) general_not_impl_clock_select <= 2'd0;    else if(general_io_write_misc) general_not_impl_clock_select <= io_writedata[3:2]; end
486
 
487
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) general_enable_ram <= 1'd1;               else if(general_io_write_misc) general_enable_ram <= io_writedata[1]; end
488
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) general_io_space   <= 1'd1;               else if(general_io_write_misc) general_io_space   <= io_writedata[0]; end
489
 
490
//------------------------------------------------------------------------------ io
491
 
492
wire host_io_ignored =
493
    (general_io_space    && (io_b_read_valid || io_b_write)) ||
494
    (~(general_io_space) && (io_d_read_valid || io_d_write));
495
 
496
 
497
reg [3:0] host_io_read_address_last;
498
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) host_io_read_address_last <= 4'd0; else if(io_c_read_valid) host_io_read_address_last <= io_c_address; end
499
 
500
reg [2:0]   seq_io_index;
501
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) seq_io_index <= 3'd0; else if(io_c_write && io_c_address == 4'h4) seq_io_index <= io_writedata[2:0]; end
502
 
503
wire        seq_io_write = io_c_write && io_c_address == 4'h5;
504
 
505
reg [4:0]   crtc_io_index;
506
always @(posedge clk_26 or negedge rst_n) begin
507
    if(rst_n == 1'b0)                                                   crtc_io_index <= 5'd0;
508
    else if(io_b_write && io_b_address == 4'h4 && ~(host_io_ignored))   crtc_io_index <= io_b_writedata[4:0];
509
    else if(io_d_write && io_d_address == 4'h4 && ~(host_io_ignored))   crtc_io_index <= io_d_writedata[4:0];
510
end
511
 
512
wire crtc_io_write = ((io_b_write && io_b_address == 4'd5) || (io_d_write && io_d_address == 4'd5)) && ~(host_io_ignored) && (~(crtc_protect) || crtc_io_index >= 5'd8);
513
 
514
wire crtc_io_write_compare = ((io_b_write && io_b_address == 4'd5) || (io_d_write && io_d_address == 4'd5)) && ~(host_io_ignored);
515
 
516
reg [3:0]   graph_io_index;
517
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) graph_io_index <= 4'd0; else if(io_c_write && io_c_address == 4'hE) graph_io_index <= io_c_writedata[3:0]; end
518
 
519
wire        graph_io_write = io_c_write && io_c_address == 4'hF;
520
 
521
reg [4:0]   attrib_io_index;
522
reg         attrib_video_enable;
523
reg         attrib_flip_flop;
524
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) attrib_video_enable <= 1'd1; else if(io_c_write && io_c_address == 4'h0 && ~(attrib_flip_flop)) attrib_video_enable <= io_c_writedata[5]; end
525
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) attrib_io_index     <= 5'd0; else if(io_c_write && io_c_address == 4'h0 && ~(attrib_flip_flop)) attrib_io_index     <= io_c_writedata[4:0]; end
526
 
527
always @(posedge clk_26 or negedge rst_n) begin
528
    if(rst_n == 1'b0)                                                                                                       attrib_flip_flop <= 1'b0;
529
    else if(((io_b_read_valid && io_b_address == 4'hA) || (io_d_read_valid && io_d_address == 4'hA)) && ~(host_io_ignored)) attrib_flip_flop <= 1'b0;
530
    else if(io_c_write && io_c_address == 4'h0)                                                                             attrib_flip_flop <= ~attrib_flip_flop;
531
end
532
 
533
wire attrib_io_write = io_c_write && io_c_address == 4'h0 && attrib_flip_flop == 1'b1;
534
 
535
wire general_io_write_misc = io_c_write && io_c_address == 4'h2;
536
 
537
//------------------------------------------------------------------------------
538
 
539
reg [7:0] dac_mask;
540
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) dac_mask <= 8'hFF; else if(io_c_write && io_c_address == 4'h6) dac_mask <= io_c_writedata[7:0]; end
541
 
542
reg       dac_is_read;
543
always @(posedge clk_26 or negedge rst_n) begin
544
    if(rst_n == 1'b0)                           dac_is_read <= 1'd0;
545
    else if(io_c_write && io_c_address == 4'h7) dac_is_read <= 1'b1;
546
    else if(io_c_write && io_c_address == 4'h8) dac_is_read <= 1'b0;
547
end
548
 
549
reg [11:0] dac_write_buffer;
550
always @(posedge clk_26 or negedge rst_n) begin
551
    if(rst_n == 1'b0)                           dac_write_buffer <= 12'd0;
552
    else if(io_c_write && io_c_address == 4'h9) dac_write_buffer <= { dac_write_buffer[5:0], io_c_writedata[5:0] };
553
end
554
 
555
reg [7:0] dac_write_index;
556
always @(posedge clk_26 or negedge rst_n) begin
557
    if(rst_n == 1'b0)                                               dac_write_index <= 8'd0;
558
    else if(io_c_write && io_c_address == 4'h8)                     dac_write_index <= io_c_writedata[7:0];
559
    else if(io_c_write && io_c_address == 4'h9 && dac_cnt == 2'd2)  dac_write_index <= dac_write_index + 8'd1;
560
end
561
 
562
reg [7:0] dac_read_index;
563
always @(posedge clk_26 or negedge rst_n) begin
564
    if(rst_n == 1'b0)                                                       dac_read_index <= 8'd0;
565
    else if(io_c_write && io_c_address == 4'h7)                             dac_read_index <= io_c_writedata[7:0];
566
    else if(io_c_read_valid  && io_c_address == 4'h9 && dac_cnt == 2'd2)    dac_read_index <= dac_read_index + 8'd1;
567
end
568
 
569
reg [1:0] dac_cnt;
570
always @(posedge clk_26 or negedge rst_n) begin
571
    if(rst_n == 1'b0)                                                                   dac_cnt <= 2'd0;
572
    else if(io_c_write && io_c_address == 4'h7)                                         dac_cnt <= 2'd0;
573
    else if(io_c_write && io_c_address == 4'h8)                                         dac_cnt <= 2'd0;
574
    else if((io_c_read_valid || io_c_write) && io_c_address == 4'h9 && dac_cnt == 2'd2) dac_cnt <= 2'd0;
575
    else if((io_c_read_valid || io_c_write) && io_c_address == 4'h9)                    dac_cnt <= dac_cnt + 2'd1;
576
end
577
 
578
//------------------------------------------------------------------------------
579
 
580
wire host_io_vertical_retrace;
581
wire host_io_not_displaying;
582
 
583
wire [7:0]  host_io_read_wire =
584
    (host_io_ignored)?                                  8'hFF :
585
    (io_c_read_valid && io_c_address == 4'hC)?          { general_vsync, general_hsync, general_not_impl_odd_even_page, 1'b0, general_not_impl_clock_select, general_enable_ram, general_io_space } : //misc output reg
586
    (io_c_read_valid && io_c_address == 4'h2)?          { 3'b0, 1'b1, 4'b0 } : //input status 0
587
    ((io_b_read_valid && io_b_address == 4'hA) || (io_d_read_valid && io_d_address == 4'hA))?
588
                                                        { 4'b0, host_io_vertical_retrace, 2'b0, host_io_not_displaying } : //input status 1
589
    (io_c_read_valid && io_c_address == 4'h0 && attrib_flip_flop)?
590
                                                        8'h00 : //attrib index in write mode
591
    (io_c_read_valid && io_c_address == 4'h0)?          { 2'b0, attrib_video_enable, attrib_io_index } : //attrib in address mode
592
    (io_c_read_valid && io_c_address == 4'h1)?          host_io_read_attrib : //attrib read
593
    (io_c_read_valid && io_c_address == 4'h4)?          { 5'd0, seq_io_index } : //seq index
594
    (io_c_read_valid && io_c_address == 4'h5)?          host_io_read_seq : //seq data
595
    (io_c_read_valid && io_c_address == 4'h6)?          dac_mask : //pel mask
596
    (io_c_read_valid && io_c_address == 4'h7)?          { 6'd0, dac_is_read? 2'b11 : 2'b00 } : //dac state
597
    (io_c_read_valid && io_c_address == 4'h8)?          dac_write_index :
598
    (io_c_read_valid && io_c_address == 4'hE)?          { 4'd0, graph_io_index } :
599
    (io_c_read_valid && io_c_address == 4'hF)?          host_io_read_graph :
600
    (io_d_read_valid && io_d_address == 4'h4)?          { 3'b0, crtc_io_index } :
601
    ((io_b_read_valid && io_b_address == 4'h5) || (io_d_read_valid && io_d_address == 4'h5))?
602
                                                        host_io_read_crtc :
603
    (io_b_read_valid || io_d_read_valid)?               8'hFF :
604
                                                        8'h00; // 6'h1A (Feature Control Register)
605
 
606
reg [7:0] host_io_read_reg;
607
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) host_io_read_reg <= 8'd0; else host_io_read_reg <= host_io_read_wire; end
608
 
609
wire [5:0]  host_palette_q;
610
wire [17:0] dac_read_q;
611
 
612
assign io_c_readdata =
613
    (host_io_read_address_last == 4'h1 && attrib_io_index <= 5'hF)?     { 2'b0, host_palette_q } :
614
    (host_io_read_address_last == 4'h9 && ~(dac_is_read))?              8'h3F :
615
    (host_io_read_address_last == 4'h9 && dac_cnt == 2'd1)?             { 2'b0, dac_read_q[17:12] } :
616
    (host_io_read_address_last == 4'h9 && dac_cnt == 2'd2)?             { 2'b0, dac_read_q[11:6] } :
617
    (host_io_read_address_last == 4'h9 && dac_cnt == 2'd0)?             { 2'b0, dac_read_q[5:0] } :
618
                                                                        host_io_read_reg;
619
 
620
assign io_b_readdata = host_io_read_reg;
621
assign io_d_readdata = host_io_read_reg;
622
 
623
//------------------------------------------------------------------------------
624
 
625
//------------------------------------------------------------------------------
626
 
627
wire host_memory_out_of_bounds =
628
    (graph_system_memory == 2'd1 && mem_address > 17'h0FFFF) ||
629
    (graph_system_memory == 2'd2 && (mem_address < 17'h10000 || mem_address > 17'h17FFF)) ||
630
    (graph_system_memory == 2'd3 && mem_address < 17'h17FFF);
631
 
632
wire [16:0] host_address_reduced =
633
    (graph_system_memory == 2'd1)?  { 1'b0, mem_address[15:0] } :
634
    (graph_system_memory == 2'd2)?  { 2'b0, mem_address[14:0] } :
635
    (graph_system_memory == 2'd3)?  { 2'b0, mem_address[14:0] } :
636
                                    mem_address;
637
 
638
wire [15:0] host_address =
639
    (seq_access_chain4)?                { host_address_reduced[15:2], 2'b00 } :
640
    (~(seq_access_odd_even_disabled))?  { host_address_reduced[15:1], 1'b0 } :
641
                                        host_address_reduced[15:0];
642
 
643
//------------------------------------------------------------------------------ mem read
644
 
645
wire [7:0] host_ram0_q;
646
wire [7:0] host_ram1_q;
647
wire [7:0] host_ram2_q;
648
wire [7:0] host_ram3_q;
649
 
650
reg [7:0] host_ram0_reg;
651
reg [7:0] host_ram1_reg;
652
reg [7:0] host_ram2_reg;
653
reg [7:0] host_ram3_reg;
654
 
655
reg host_read_out_of_bounds;
656
always @(posedge clk_26 or negedge rst_n) begin
657
    if(rst_n == 1'b0)                                       host_read_out_of_bounds <= 1'b0;
658
    else if(mem_read_valid && host_memory_out_of_bounds)    host_read_out_of_bounds <= 1'b1;
659
    else                                                    host_read_out_of_bounds <= 1'b0;
660
end
661
 
662
reg [16:0] host_address_reduced_last;
663
always @(posedge clk_26 or negedge rst_n) begin
664
    if(rst_n == 1'b0)       host_address_reduced_last <= 17'd0;
665
    else if(mem_read_valid) host_address_reduced_last <= host_address_reduced;
666
end
667
 
668
reg host_read_last;
669
always @(posedge clk_26 or negedge rst_n) begin
670
    if(rst_n == 1'b0)   host_read_last <= 1'd0;
671
    else                host_read_last <= mem_read_valid && ~(host_memory_out_of_bounds);
672
end
673
 
674
wire [7:0] host_read_mode_1 = {
675
    (graph_color_compare_dont_care[0]? ~(host_ram0_q[7] ^ graph_color_compare_map[0]) : 1'b1) & (graph_color_compare_dont_care[1]? ~(host_ram1_q[7] ^ graph_color_compare_map[1]) : 1'b1) &
676
    (graph_color_compare_dont_care[2]? ~(host_ram2_q[7] ^ graph_color_compare_map[2]) : 1'b1) & (graph_color_compare_dont_care[3]? ~(host_ram3_q[7] ^ graph_color_compare_map[3]) : 1'b1),
677
    (graph_color_compare_dont_care[0]? ~(host_ram0_q[6] ^ graph_color_compare_map[0]) : 1'b1) & (graph_color_compare_dont_care[1]? ~(host_ram1_q[6] ^ graph_color_compare_map[1]) : 1'b1) &
678
    (graph_color_compare_dont_care[2]? ~(host_ram2_q[6] ^ graph_color_compare_map[2]) : 1'b1) & (graph_color_compare_dont_care[3]? ~(host_ram3_q[6] ^ graph_color_compare_map[3]) : 1'b1),
679
    (graph_color_compare_dont_care[0]? ~(host_ram0_q[5] ^ graph_color_compare_map[0]) : 1'b1) & (graph_color_compare_dont_care[1]? ~(host_ram1_q[5] ^ graph_color_compare_map[1]) : 1'b1) &
680
    (graph_color_compare_dont_care[2]? ~(host_ram2_q[5] ^ graph_color_compare_map[2]) : 1'b1) & (graph_color_compare_dont_care[3]? ~(host_ram3_q[5] ^ graph_color_compare_map[3]) : 1'b1),
681
    (graph_color_compare_dont_care[0]? ~(host_ram0_q[4] ^ graph_color_compare_map[0]) : 1'b1) & (graph_color_compare_dont_care[1]? ~(host_ram1_q[4] ^ graph_color_compare_map[1]) : 1'b1) &
682
    (graph_color_compare_dont_care[2]? ~(host_ram2_q[4] ^ graph_color_compare_map[2]) : 1'b1) & (graph_color_compare_dont_care[3]? ~(host_ram3_q[4] ^ graph_color_compare_map[3]) : 1'b1),
683
    (graph_color_compare_dont_care[0]? ~(host_ram0_q[3] ^ graph_color_compare_map[0]) : 1'b1) & (graph_color_compare_dont_care[1]? ~(host_ram1_q[3] ^ graph_color_compare_map[1]) : 1'b1) &
684
    (graph_color_compare_dont_care[2]? ~(host_ram2_q[3] ^ graph_color_compare_map[2]) : 1'b1) & (graph_color_compare_dont_care[3]? ~(host_ram3_q[3] ^ graph_color_compare_map[3]) : 1'b1),
685
    (graph_color_compare_dont_care[0]? ~(host_ram0_q[2] ^ graph_color_compare_map[0]) : 1'b1) & (graph_color_compare_dont_care[1]? ~(host_ram1_q[2] ^ graph_color_compare_map[1]) : 1'b1) &
686
    (graph_color_compare_dont_care[2]? ~(host_ram2_q[2] ^ graph_color_compare_map[2]) : 1'b1) & (graph_color_compare_dont_care[3]? ~(host_ram3_q[2] ^ graph_color_compare_map[3]) : 1'b1),
687
    (graph_color_compare_dont_care[0]? ~(host_ram0_q[1] ^ graph_color_compare_map[0]) : 1'b1) & (graph_color_compare_dont_care[1]? ~(host_ram1_q[1] ^ graph_color_compare_map[1]) : 1'b1) &
688
    (graph_color_compare_dont_care[2]? ~(host_ram2_q[1] ^ graph_color_compare_map[2]) : 1'b1) & (graph_color_compare_dont_care[3]? ~(host_ram3_q[1] ^ graph_color_compare_map[3]) : 1'b1),
689
    (graph_color_compare_dont_care[0]? ~(host_ram0_q[0] ^ graph_color_compare_map[0]) : 1'b1) & (graph_color_compare_dont_care[1]? ~(host_ram1_q[0] ^ graph_color_compare_map[1]) : 1'b1) &
690
    (graph_color_compare_dont_care[2]? ~(host_ram2_q[0] ^ graph_color_compare_map[2]) : 1'b1) & (graph_color_compare_dont_care[3]? ~(host_ram3_q[0] ^ graph_color_compare_map[3]) : 1'b1)
691
};
692
 
693
assign mem_readdata =
694
    (host_read_out_of_bounds)?                                                                              8'hFF :
695
    (seq_access_chain4 && host_address_reduced_last[1:0] == 2'b00)?                                         host_ram0_q :
696
    (seq_access_chain4 && host_address_reduced_last[1:0] == 2'b01)?                                         host_ram1_q :
697
    (seq_access_chain4 && host_address_reduced_last[1:0] == 2'b10)?                                         host_ram2_q :
698
    (seq_access_chain4 && host_address_reduced_last[1:0] == 2'b11)?                                         host_ram3_q :
699
    (graph_read_mode == 1'b0 && ~(seq_access_odd_even_disabled) && host_address_reduced_last[0] == 1'b0)?   host_ram0_q :
700
    (graph_read_mode == 1'b0 && ~(seq_access_odd_even_disabled) && host_address_reduced_last[0] == 1'b1)?   host_ram1_q :
701
    (graph_read_mode == 1'b0 && graph_read_map_select == 2'd0)?                                             host_ram0_q :
702
    (graph_read_mode == 1'b0 && graph_read_map_select == 2'd1)?                                             host_ram1_q :
703
    (graph_read_mode == 1'b0 && graph_read_map_select == 2'd2)?                                             host_ram2_q :
704
    (graph_read_mode == 1'b0 && graph_read_map_select == 2'd3)?                                             host_ram3_q :
705
                                                                                                            host_read_mode_1;
706
 
707
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) host_ram0_reg <= 8'd0; else if(host_read_last) host_ram0_reg <= host_ram0_q; end
708
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) host_ram1_reg <= 8'd0; else if(host_read_last) host_ram1_reg <= host_ram1_q; end
709
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) host_ram2_reg <= 8'd0; else if(host_read_last) host_ram2_reg <= host_ram2_q; end
710
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) host_ram3_reg <= 8'd0; else if(host_read_last) host_ram3_reg <= host_ram3_q; end
711
 
712
 
713
//------------------------------------------------------------------------------ mem write
714
 
715
wire host_write = mem_write && ~(host_memory_out_of_bounds);
716
 
717
wire [7:0] host_writedata_rotate =
718
    (graph_write_rotate == 3'd0)?     mem_writedata[7:0] :
719
    (graph_write_rotate == 3'd1)?   { mem_writedata[0],   mem_writedata[7:1] } :
720
    (graph_write_rotate == 3'd2)?   { mem_writedata[1:0], mem_writedata[7:2] } :
721
    (graph_write_rotate == 3'd3)?   { mem_writedata[2:0], mem_writedata[7:3] } :
722
    (graph_write_rotate == 3'd4)?   { mem_writedata[3:0], mem_writedata[7:4] } :
723
    (graph_write_rotate == 3'd5)?   { mem_writedata[4:0], mem_writedata[7:5] } :
724
    (graph_write_rotate == 3'd6)?   { mem_writedata[5:0], mem_writedata[7:6] } :
725
                                    { mem_writedata[6:0], mem_writedata[7] };
726
 
727
wire [7:0] host_write_set_0 = (graph_write_mode == 2'd2)? {8{mem_writedata[0]}} : graph_write_enable_map[0]?  {8{graph_write_set_map[0]}} : host_writedata_rotate;
728
wire [7:0] host_write_set_1 = (graph_write_mode == 2'd2)? {8{mem_writedata[1]}} : graph_write_enable_map[1]?  {8{graph_write_set_map[1]}} : host_writedata_rotate;
729
wire [7:0] host_write_set_2 = (graph_write_mode == 2'd2)? {8{mem_writedata[2]}} : graph_write_enable_map[2]?  {8{graph_write_set_map[2]}} : host_writedata_rotate;
730
wire [7:0] host_write_set_3 = (graph_write_mode == 2'd2)? {8{mem_writedata[3]}} : graph_write_enable_map[3]?  {8{graph_write_set_map[3]}} : host_writedata_rotate;
731
 
732
wire [31:0] host_write_function =
733
    (graph_write_function == 2'd1)? { host_write_set_3, host_write_set_2, host_write_set_1, host_write_set_0 } & { host_ram3_reg, host_ram2_reg, host_ram1_reg, host_ram0_reg } :
734
    (graph_write_function == 2'd2)? { host_write_set_3, host_write_set_2, host_write_set_1, host_write_set_0 } | { host_ram3_reg, host_ram2_reg, host_ram1_reg, host_ram0_reg } :
735
    (graph_write_function == 2'd3)? { host_write_set_3, host_write_set_2, host_write_set_1, host_write_set_0 } ^ { host_ram3_reg, host_ram2_reg, host_ram1_reg, host_ram0_reg } :
736
                                    { host_write_set_3, host_write_set_2, host_write_set_1, host_write_set_0 };
737
 
738
wire [7:0] host_write_mask_0 = (graph_write_mask & host_write_function[7:0])   | (~(graph_write_mask) & host_ram0_reg);
739
wire [7:0] host_write_mask_1 = (graph_write_mask & host_write_function[15:8])  | (~(graph_write_mask) & host_ram1_reg);
740
wire [7:0] host_write_mask_2 = (graph_write_mask & host_write_function[23:16]) | (~(graph_write_mask) & host_ram2_reg);
741
wire [7:0] host_write_mask_3 = (graph_write_mask & host_write_function[31:24]) | (~(graph_write_mask) & host_ram3_reg);
742
 
743
wire [7:0] host_write_mode_3_mask = host_writedata_rotate & graph_write_mask;
744
wire [7:0] host_write_mode_3_ram0 = (host_write_mode_3_mask & {8{graph_write_set_map[0]}})   | (~(host_write_mode_3_mask) & host_ram0_reg);
745
wire [7:0] host_write_mode_3_ram1 = (host_write_mode_3_mask & {8{graph_write_set_map[1]}})   | (~(host_write_mode_3_mask) & host_ram1_reg);
746
wire [7:0] host_write_mode_3_ram2 = (host_write_mode_3_mask & {8{graph_write_set_map[2]}})   | (~(host_write_mode_3_mask) & host_ram2_reg);
747
wire [7:0] host_write_mode_3_ram3 = (host_write_mode_3_mask & {8{graph_write_set_map[3]}})   | (~(host_write_mode_3_mask) & host_ram3_reg);
748
 
749
wire [31:0] host_writedata =
750
    (graph_write_mode == 2'd0 || graph_write_mode == 2'd2)?     { host_write_mask_3, host_write_mask_2, host_write_mask_1, host_write_mask_0 } :
751
    (graph_write_mode == 2'd1)?                                 { host_ram3_reg, host_ram2_reg, host_ram1_reg, host_ram0_reg } :
752
                                                                { host_write_mode_3_ram3, host_write_mode_3_ram2, host_write_mode_3_ram1, host_write_mode_3_ram0 };
753
 
754
wire [3:0] host_write_enable_for_chain4 =
755
    (host_address_reduced[1:0] == 2'd0)?    4'b0001 :
756
    (host_address_reduced[1:0] == 2'd1)?    4'b0010 :
757
    (host_address_reduced[1:0] == 2'd2)?    4'b0100 :
758
                                            4'b1000;
759
wire [3:0] host_write_enable_for_odd_even =
760
    (host_address_reduced[0] == 1'd0)?      4'b0101 :
761
                                            4'b1010;
762
 
763
wire [3:0] host_write_enable =
764
    {4{host_write}} & seq_map_write_enable & (
765
    (seq_access_chain4)?                host_write_enable_for_chain4 :
766
    (~(seq_access_odd_even_disabled))?  host_write_enable_for_odd_even :
767
                                        4'b1111);
768
 
769
//------------------------------------------------------------------------------
770
 
771
wire dot_memory_load;
772
wire dot_memory_load_first_in_frame;
773
wire dot_memory_load_first_in_line_matched;
774
wire dot_memory_load_first_in_line;
775
wire dot_memory_load_vertical_retrace_start;
776
 
777
wire memory_address_load = dot_memory_load_first_in_frame || dot_memory_load_first_in_line_matched || dot_memory_load_first_in_line;
778
 
779
reg [15:0] memory_start_line;
780
always @(posedge clk_26 or negedge rst_n) begin
781
    if(rst_n == 1'b0)               memory_start_line <= 16'd0;
782
    else if(memory_address_load)    memory_start_line <= memory_address;
783
end
784
 
785
reg [15:0] memory_address_reg;
786
always @(posedge clk_26 or negedge rst_n) begin
787
    if(rst_n == 1'b0)                               memory_address_reg <= 16'd0;
788
    else if(memory_address_load || dot_memory_load) memory_address_reg <= memory_address;
789
end
790
 
791
reg [4:0] memory_row_scan_reg;
792
always @(posedge clk_26 or negedge rst_n) begin
793
    if(rst_n == 1'b0)               memory_row_scan_reg <= 5'd0;
794
    else if(memory_address_load)    memory_row_scan_reg <= memory_row_scan;
795
end
796
 
797
reg memory_row_scan_double;
798
always @(posedge clk_26 or negedge rst_n) begin
799
    if(rst_n == 1'b0)                                                                                               memory_row_scan_double <= 1'b0;
800
    else if(crtc_vertical_doublescan && (dot_memory_load_first_in_frame || dot_memory_load_first_in_line_matched))  memory_row_scan_double <= 1'b1;
801
    else if(crtc_vertical_doublescan && dot_memory_load_first_in_line)                                              memory_row_scan_double <= ~memory_row_scan_double;
802
    else if(~(crtc_vertical_doublescan) || dot_memory_load_vertical_retrace_start)                                  memory_row_scan_double <= 1'b0;
803
end
804
 
805
//do not change charmap in the middle of a character row scan
806
reg [2:0] memory_char_map_a;
807
always @(posedge clk_26 or negedge rst_n) begin
808
    if(rst_n == 1'b0)                                                                                                                               memory_char_map_a <= 3'd0;
809
    else if(dot_memory_load_first_in_frame || dot_memory_load_first_in_line_matched || (dot_memory_load_first_in_line && memory_row_scan == 5'd0))  memory_char_map_a <= seq_char_map_a;
810
end
811
 
812
reg [2:0] memory_char_map_b;
813
always @(posedge clk_26 or negedge rst_n) begin
814
    if(rst_n == 1'b0)                                                                                                                               memory_char_map_b <= 3'd0;
815
    else if(dot_memory_load_first_in_frame || dot_memory_load_first_in_line_matched || (dot_memory_load_first_in_line && memory_row_scan == 5'd0))  memory_char_map_b <= seq_char_map_b;
816
end
817
 
818
 
819
reg [3:0] memory_panning_reg;
820
always @(posedge clk_26 or negedge rst_n) begin
821
    if(rst_n == 1'b0)                                                                       memory_panning_reg <= 4'd0;
822
    else if(dot_memory_load_first_in_line_matched && attrib_panning_after_compare_match)    memory_panning_reg <= 4'd0;
823
    else if(dot_memory_load_first_in_frame)                                                 memory_panning_reg <= attrib_panning_value;
824
end
825
 
826
reg memory_load_step_a;
827
always @(posedge clk_26 or negedge rst_n) begin
828
    if(rst_n == 1'b0)           memory_load_step_a <= 1'b0;
829
    else if(dot_memory_load)    memory_load_step_a <= 1'b1;
830
    else                        memory_load_step_a <= 1'b0;
831
end
832
 
833
reg memory_load_step_b;
834
always @(posedge clk_26 or negedge rst_n) begin
835
    if(rst_n == 1'b0)           memory_load_step_b <= 1'b0;
836
    else if(memory_load_step_a) memory_load_step_b <= 1'b1;
837
    else                        memory_load_step_b <= 1'b0;
838
end
839
 
840
wire [15:0] memory_address =
841
    (dot_memory_load_first_in_line_matched)?                                    16'd0 :
842
    (dot_memory_load_first_in_frame)?                                           crtc_address_start + { 14'd0, crtc_address_byte_panning } :
843
    (dot_memory_load_first_in_line && memory_row_scan_double)?                  memory_start_line :
844
    (dot_memory_load_first_in_line && memory_row_scan_reg < crtc_row_max)?      memory_start_line :
845
    (dot_memory_load_first_in_line)?                                            memory_start_line + { 7'd0, crtc_address_offset[7:0], 1'b0 } :
846
    (dot_memory_load)?                                                          memory_address_reg + 16'd1 :
847
                                                                                memory_address_reg;
848
 
849
wire [4:0] memory_row_scan =
850
    (dot_memory_load_first_in_line_matched)?                                5'd0 :
851
    (dot_memory_load_first_in_frame && crtc_row_preset <= crtc_row_max)?    crtc_row_preset :
852
    (dot_memory_load_first_in_frame)?                                       5'd0 :
853
    (dot_memory_load_first_in_line && memory_row_scan_double)?              memory_row_scan_reg :
854
    (dot_memory_load_first_in_line && memory_row_scan_reg == crtc_row_max)? 5'd0 :
855
    (dot_memory_load_first_in_line)?                                        memory_row_scan_reg + 5'd1 :
856
                                                                            memory_row_scan_reg;
857
 
858
wire [15:0] memory_address_step_1 =
859
    (crtc_address_doubleword)?  { memory_address[13:0], memory_address[15:14] } :
860
    (crtc_address_byte)?        memory_address :
861
    (crtc_address_bit0)?        { memory_address[14:0], memory_address[15] } :
862
                                { memory_address[14:0], memory_address[13] };
863
 
864
wire [15:0] memory_address_step_2 = {
865
    memory_address_step_1[15],
866
    (crtc_address_bit14)?           memory_address_step_1[14] : memory_row_scan[1],
867
    (crtc_address_bit13)?           memory_address_step_1[13] : memory_row_scan[0],
868
    memory_address_step_1[12:0]
869
};
870
 
871
reg [15:0] memory_address_reg_final;
872
always @(posedge clk_26 or negedge rst_n) begin
873
    if(rst_n == 1'b0)           memory_address_reg_final <= 16'd0;
874
    else if(dot_memory_load)    memory_address_reg_final <= memory_address;
875
end
876
 
877
wire [2:0] memory_txt_index = plane_ram1_q[3]? memory_char_map_a : memory_char_map_b;
878
 
879
wire [15:0] memory_txt_address_base =
880
    ((~(seq_access_256kb) && memory_txt_index[2] == 1'b0) || memory_txt_index == 3'b000)?   16'h0000 :
881
    ((~(seq_access_256kb) && memory_txt_index[2] == 1'b1) || memory_txt_index == 3'b100)?   16'h2000 :
882
    (memory_txt_index == 3'b001)?                                                           16'h4000 :
883
    (memory_txt_index == 3'b101)?                                                           16'h6000 :
884
    (memory_txt_index == 3'b010)?                                                           16'h8000 :
885
    (memory_txt_index == 3'b110)?                                                           16'hA000 :
886
    (memory_txt_index == 3'b011)?                                                           16'hC000 :
887
                                                                                            16'hE000;
888
 
889
wire [15:0] memory_txt_address = { memory_txt_address_base[15:13], plane_ram0_q[7:0], memory_row_scan_reg };
890
 
891
//------------------------------------------------------------------------------
892
 
893
wire [7:0] plane_ram0_q;
894
wire [7:0] plane_ram1_q;
895
wire [7:0] plane_ram2_q;
896
wire [7:0] plane_ram3_q;
897
 
898
 
899
simple_bidir_ram #(
900
    .widthad    (16),
901
    .width      (8)
902
)
903
plane_ram_inst0(
904
    .clk            (clk_26),
905
 
906
    .address_a      (host_address),
907
    .data_a         (host_writedata[7:0]),
908
    .wren_a         (general_enable_ram && host_write_enable[0]),
909
    .q_a            (host_ram0_q),
910
 
911
    .address_b      (memory_address_step_2),
912
    .q_b            (plane_ram0_q)
913
);
914
 
915
simple_bidir_ram #(
916
    .widthad    (16),
917
    .width      (8)
918
)
919
plane_ram_inst1(
920
    .clk            (clk_26),
921
 
922
    .address_a      (host_address),
923
    .data_a         (host_writedata[15:8]),
924
    .wren_a         (general_enable_ram && host_write_enable[1]),
925
    .q_a            (host_ram1_q),
926
 
927
    .address_b      (memory_address_step_2),
928
    .q_b            (plane_ram1_q)
929
);
930
 
931
simple_bidir_ram #(
932
    .widthad    (16),
933
    .width      (8)
934
)
935
plane_ram_inst2(
936
    .clk            (clk_26),
937
 
938
    .address_a      (host_address),
939
    .data_a         (host_writedata[23:16]),
940
    .wren_a         (general_enable_ram && host_write_enable[2]),
941
    .q_a            (host_ram2_q),
942
 
943
    .address_b      (memory_load_step_a? memory_txt_address : memory_address_step_2),
944
    .q_b            (plane_ram2_q)
945
);
946
 
947
simple_bidir_ram #(
948
    .widthad    (16),
949
    .width      (8)
950
)
951
plane_ram_inst3(
952
    .clk            (clk_26),
953
 
954
    .address_a      (host_address),
955
    .data_a         (host_writedata[31:24]),
956
    .wren_a         (general_enable_ram && host_write_enable[3]),
957
    .q_a            (host_ram3_q),
958
 
959
    .address_b      (memory_address_step_2),
960
    .q_b            (plane_ram3_q)
961
);
962
 
963
//------------------------------------------------------------------------------
964
 
965
reg [7:0] plane_ram0;
966
reg [7:0] plane_ram1;
967
reg [7:0] plane_ram2;
968
reg [7:0] plane_ram3;
969
 
970
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) plane_ram0 <= 8'd0; else if(memory_load_step_a) plane_ram0 <= plane_ram0_q; end
971
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) plane_ram1 <= 8'd0; else if(memory_load_step_a) plane_ram1 <= plane_ram1_q; end
972
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) plane_ram2 <= 8'd0; else if(memory_load_step_a) plane_ram2 <= plane_ram2_q; end
973
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) plane_ram3 <= 8'd0; else if(memory_load_step_a) plane_ram3 <= plane_ram3_q; end
974
 
975
//------------------------------------------------------------------------------
976
 
977
reg [5:0] plane_shift_cnt;
978
always @(posedge clk_26 or negedge rst_n) begin
979
    if(rst_n == 1'b0)                   plane_shift_cnt <= 6'd0;
980
    else if(memory_load_step_b)         plane_shift_cnt <= 6'd1;
981
    else if(plane_shift_cnt == 6'd34)   plane_shift_cnt <= 6'd0;
982
    else if(plane_shift_cnt != 6'd0)    plane_shift_cnt <= plane_shift_cnt + 6'd1;
983
end
984
 
985
wire plane_shift_enable =
986
    (~(seq_dotclock_divided) && plane_shift_cnt >= 6'd1) ||
987
    (  seq_dotclock_divided  && plane_shift_cnt >= 6'd1 && plane_shift_cnt[0]);
988
 
989
wire plane_shift_9dot =
990
    ~(seq_8dot_char) && plane_shift_enable &&
991
    (~(seq_dotclock_divided) && plane_shift_cnt == 6'd9) ||
992
    (  seq_dotclock_divided  && plane_shift_cnt == 6'd17);
993
 
994
//------------------------------------------------------------------------------
995
 
996
reg [7:0] plane_shift0;
997
reg [7:0] plane_shift1;
998
reg [7:0] plane_shift2;
999
reg [7:0] plane_shift3;
1000
 
1001
wire [7:0] plane_shift_value0 =
1002
    (graph_shift_mode == 2'b00)?    plane_ram0 :
1003
    (graph_shift_mode == 2'b01)?    { plane_ram0[6],plane_ram0[4],plane_ram0[2],plane_ram0[0], plane_ram1[6],plane_ram1[4],plane_ram1[2],plane_ram1[0] } :
1004
                                    { plane_ram0[4],plane_ram0[0],plane_ram1[4],plane_ram1[0], plane_ram2[4],plane_ram2[0],plane_ram3[4],plane_ram3[0] };
1005
 
1006
wire [7:0] plane_shift_value1 =
1007
    (graph_shift_mode == 2'b00)?    plane_ram1 :
1008
    (graph_shift_mode == 2'b01)?    { plane_ram0[7],plane_ram0[5],plane_ram0[3],plane_ram0[1], plane_ram1[7],plane_ram1[5],plane_ram1[3],plane_ram1[1] } :
1009
                                    { plane_ram0[5],plane_ram0[1],plane_ram1[5],plane_ram1[1], plane_ram2[5],plane_ram2[1],plane_ram3[5],plane_ram3[1] };
1010
 
1011
wire [7:0] plane_shift_value2 =
1012
    (graph_shift_mode == 2'b00)?    plane_ram2 :
1013
    (graph_shift_mode == 2'b01)?    { plane_ram2[6],plane_ram2[4],plane_ram2[2],plane_ram2[0], plane_ram3[6],plane_ram3[4],plane_ram3[2],plane_ram3[0] } :
1014
                                    { plane_ram0[6],plane_ram0[2],plane_ram1[6],plane_ram1[2], plane_ram2[6],plane_ram2[2],plane_ram3[6],plane_ram3[2] };
1015
 
1016
wire [7:0] plane_shift_value3 =
1017
    (graph_shift_mode == 2'b00)?    plane_ram3 :
1018
    (graph_shift_mode == 2'b01)?    { plane_ram2[7],plane_ram2[5],plane_ram2[3],plane_ram2[1], plane_ram3[7],plane_ram3[5],plane_ram3[3],plane_ram3[1] } :
1019
                                    { plane_ram0[7],plane_ram0[3],plane_ram1[7],plane_ram1[3], plane_ram2[7],plane_ram2[3],plane_ram3[7],plane_ram3[3] };
1020
 
1021
always @(posedge clk_26 or negedge rst_n) begin
1022
    if(rst_n == 1'b0)           plane_shift0 <= 8'd0;
1023
    else if(memory_load_step_b) plane_shift0 <= plane_shift_value0;
1024
    else if(plane_shift_enable) plane_shift0 <= { plane_shift0[6:0], 1'b0 };
1025
end
1026
 
1027
always @(posedge clk_26 or negedge rst_n) begin
1028
    if(rst_n == 1'b0)           plane_shift1 <= 8'd0;
1029
    else if(memory_load_step_b) plane_shift1 <= plane_shift_value1;
1030
    else if(plane_shift_enable) plane_shift1 <= { plane_shift1[6:0], 1'b0 };
1031
end
1032
 
1033
always @(posedge clk_26 or negedge rst_n) begin
1034
    if(rst_n == 1'b0)           plane_shift2 <= 8'd0;
1035
    else if(memory_load_step_b) plane_shift2 <= plane_shift_value2;
1036
    else if(plane_shift_enable) plane_shift2 <= { plane_shift2[6:0], 1'b0 };
1037
end
1038
 
1039
always @(posedge clk_26 or negedge rst_n) begin
1040
    if(rst_n == 1'b0)           plane_shift3 <= 8'd0;
1041
    else if(memory_load_step_b) plane_shift3 <= plane_shift_value3;
1042
    else if(plane_shift_enable) plane_shift3 <= { plane_shift3[6:0], 1'b0 };
1043
end
1044
 
1045
//------------------------------------------------------------------------------
1046
 
1047
reg [7:0] plane_txt_shift;
1048
 
1049
wire blink_txt_value;
1050
wire blink_cursor_value;
1051
 
1052
wire txt_blink_enabled = attrib_blinking && plane_ram1[7] && blink_txt_value;
1053
 
1054
wire txt_underline_enable = plane_ram1[2:0] == 3'b001 && plane_ram1[6:4] == 3'b000 && crtc_row_underline > 5'd0 && crtc_row_underline - 5'd1 == memory_row_scan_reg;
1055
 
1056
wire txt_cursor_enable =
1057
    ~(crtc_cursor_off) &&
1058
    blink_cursor_value &&
1059
    memory_address_reg_final == crtc_address_cursor + { 14'd0, crtc_cursor_skew } &&
1060
    memory_row_scan_reg >= crtc_cursor_row_start &&
1061
    memory_row_scan_reg <= crtc_cursor_row_end &&
1062
    crtc_cursor_row_start <= crtc_cursor_row_end;
1063
 
1064
wire [7:0] plane_txt_shift_value =
1065
    (txt_blink_enabled)?        8'd0 :
1066
    (txt_underline_enable)?     8'hFF :
1067
    (txt_cursor_enable)?        8'hFF :
1068
                                plane_ram2_q;
1069
 
1070
always @(posedge clk_26 or negedge rst_n) begin
1071
    if(rst_n == 1'b0)           plane_txt_shift <= 8'd0;
1072
    else if(memory_load_step_b) plane_txt_shift <= plane_txt_shift_value;
1073
    else if(plane_shift_enable) plane_txt_shift <= { plane_txt_shift[6:0], 1'b0 };
1074
end
1075
 
1076
reg [3:0] txt_foreground;
1077
reg [3:0] txt_background;
1078
always @(posedge clk_26 or negedge rst_n) begin
1079
    if(rst_n == 1'b0)           txt_foreground <= 4'd0;
1080
    else if(memory_load_step_b) txt_foreground <= plane_ram1[3:0];
1081
end
1082
 
1083
always @(posedge clk_26 or negedge rst_n) begin
1084
    if(rst_n == 1'b0)           txt_background <= 4'd0;
1085
    else if(memory_load_step_b) txt_background <= (attrib_blinking)? { 1'b0, plane_ram1[6:4] } : plane_ram1[7:4];
1086
end
1087
 
1088
wire txt_line_graphic_char = plane_ram0 >= 8'hB0 && plane_ram0 <= 8'hDF;
1089
 
1090
//------------------------------------------------------------------------------
1091
 
1092
wire [3:0] pel_input =
1093
    (plane_shift_9dot && attrib_9bit_same_as_8bit && pel_line_graphic_char)?   pel_input_last :
1094
    (plane_shift_9dot)?                                                        pel_background :
1095
 
1096
    (attrib_graphic_mode)?  { plane_shift3[7], plane_shift2[7], plane_shift1[7], plane_shift0[7] } :
1097
    (plane_txt_shift[7])?   txt_foreground :
1098
                            txt_background;
1099
 
1100
reg [3:0] pel_input_last;
1101
always @(posedge clk_26 or negedge rst_n) begin
1102
    if(rst_n == 1'b0)           pel_input_last <= 4'd0;
1103
    else if(plane_shift_enable) pel_input_last <= pel_input;
1104
end
1105
 
1106
reg pel_line_graphic_char;
1107
always @(posedge clk_26 or negedge rst_n) begin
1108
    if(rst_n == 1'b0)           pel_line_graphic_char <= 1'b0;
1109
    else if(plane_shift_enable) pel_line_graphic_char <= txt_line_graphic_char;
1110
end
1111
 
1112
reg [3:0] pel_background;
1113
always @(posedge clk_26 or negedge rst_n) begin
1114
    if(rst_n == 1'b0)           pel_background <= 4'd0;
1115
    else if(plane_shift_enable) pel_background <= txt_background;
1116
end
1117
 
1118
//------------------------------------------------------------------------------
1119
 
1120
wire [3:0] pel_after_enable = attrib_mask & pel_input;
1121
 
1122
//APA blinking logic (undocumented)
1123
wire [3:0] pel_after_blink =
1124
    (attrib_graphic_mode && attrib_blinking && blink_txt_value)?    { 1'b1, pel_after_enable[2:0] } :
1125
    (attrib_graphic_mode && attrib_blinking)?                       pel_after_enable ^ 4'b1000 :
1126
                                                                    pel_after_enable;
1127
 
1128
reg [35:0] pel_shift_reg;
1129
always @(posedge clk_26 or negedge rst_n) begin
1130
    if(rst_n == 1'b0)           pel_shift_reg <= 36'd0;
1131
    else if(plane_shift_enable) pel_shift_reg <= { pel_after_blink, pel_shift_reg[35:4] };
1132
end
1133
 
1134
wire [7:0] pel_after_panning =
1135
    (memory_panning_reg == 4'd0)?     pel_shift_reg[11:4] :
1136
    (memory_panning_reg == 4'd1)?     pel_shift_reg[15:8] :
1137
    (memory_panning_reg == 4'd2)?     pel_shift_reg[19:12] :
1138
    (memory_panning_reg == 4'd3)?     pel_shift_reg[23:16] :
1139
    (memory_panning_reg == 4'd4)?     pel_shift_reg[27:20] :
1140
    (memory_panning_reg == 4'd5)?     pel_shift_reg[31:24] :
1141
    (memory_panning_reg == 4'd6)?     pel_shift_reg[35:28] :
1142
    (memory_panning_reg == 4'd7)?     { 4'd0, pel_shift_reg[35:32] } :
1143
                                      pel_shift_reg[7:0];
1144
 
1145
reg plane_shift_enable_last;
1146
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) plane_shift_enable_last <= 1'b0; else plane_shift_enable_last <= plane_shift_enable; end
1147
 
1148
reg pel_color_8bit_cnt;
1149
always @(posedge clk_26 or negedge rst_n) begin
1150
    if(rst_n == 1'b0)                                               pel_color_8bit_cnt <= 1'b0;
1151
    else if(plane_shift_enable && plane_shift_enable_last == 1'b0)  pel_color_8bit_cnt <= 1'b1;
1152
    else                                                            pel_color_8bit_cnt <= ~pel_color_8bit_cnt;
1153
end
1154
 
1155
reg [7:0] pel_color_8bit_buffer;
1156
always @(posedge clk_26 or negedge rst_n) begin
1157
    if(rst_n == 1'b0)                   pel_color_8bit_buffer <= 8'd0;
1158
    else if(pel_color_8bit_cnt == 1'b0) pel_color_8bit_buffer <= pel_after_panning;
1159
end
1160
//------------------------------------------------------------------------------
1161
 
1162
wire [5:0] pel_palette;
1163
 
1164
simple_bidir_ram #(
1165
    .widthad    (4),
1166
    .width      (6)
1167
)
1168
internal_palette_ram_inst(
1169
    .clk            (clk_26),
1170
 
1171
    .address_a      (attrib_io_index[3:0]),
1172
    .data_a         (io_c_writedata[5:0]),
1173
    .wren_a         (attrib_io_write && attrib_io_index < 5'h10),
1174
    .q_a            (host_palette_q),
1175
 
1176
    .address_b      (pel_after_panning[3:0]),
1177
    .q_b            (pel_palette)
1178
);
1179
 
1180
wire [7:0] pel_palette_index = {
1181
    attrib_color_bit7_6_value,
1182
    (attrib_color_bit5_4_enable)? attrib_color_bit5_4_value : pel_palette[5:4],
1183
    pel_palette[3:0]
1184
};
1185
 
1186
wire vgaprep_overscan;
1187
 
1188
wire [7:0] pel_index =
1189
    (vgaprep_overscan)?             attrib_color_overscan :
1190
    (~(attrib_video_enable))?       8'h00 :
1191
    (attrib_color_8bit_enable)?     { pel_color_8bit_buffer[3:0], pel_color_8bit_buffer[7:4] } :
1192
                                    pel_palette_index;
1193
 
1194
//------------------------------------------------------------------------------
1195
 
1196
wire [17:0] dac_color;
1197
 
1198
simple_bidir_ram #(
1199
    .widthad    (8),
1200
    .width      (18)
1201
)
1202
dac_ram_inst(
1203
    .clk            (clk_26),
1204
 
1205
    .address_a      (dac_is_read? dac_read_index : dac_write_index),
1206
    .data_a         ({ dac_write_buffer, io_c_writedata[5:0] }),
1207
    .wren_a         (io_c_write && io_c_address == 4'h9 && dac_cnt == 2'd2),
1208
    .q_a            (dac_read_q),
1209
 
1210
    .address_b      (pel_index),
1211
    .q_b            (dac_color)
1212
);
1213
 
1214
//------------------------------------------------------------------------------
1215
 
1216
wire character_last_dot = dot_cnt_enable && ((dot_cnt == 4'd8 && ~(seq_8dot_char)) || (dot_cnt == 4'd7 && seq_8dot_char));
1217
wire line_last_dot      = horiz_cnt == crtc_horizontal_total + 8'd4 && character_last_dot;
1218
wire screen_last_dot    = vert_cnt == crtc_vertical_total - 10'd1   && line_last_dot;
1219
 
1220
reg [3:0] dot_cnt;
1221
reg [7:0] horiz_cnt;
1222
reg [9:0] vert_cnt;
1223
 
1224
reg dot_cnt_div;
1225
always @(posedge clk_26 or negedge rst_n) begin
1226
    if(rst_n == 1'b0)   dot_cnt_div <= 1'b0;
1227
    else                dot_cnt_div <= ~(dot_cnt_div);
1228
end
1229
 
1230
wire dot_cnt_enable = ~(seq_dotclock_divided) || dot_cnt_div;
1231
 
1232
always @(posedge clk_26 or negedge rst_n) begin
1233
    if(rst_n == 1'b0)                               dot_cnt <= 4'd0;
1234
    else if(dot_cnt_enable && character_last_dot)   dot_cnt <= 4'd0;
1235
    else if(dot_cnt_enable)                         dot_cnt <= dot_cnt + 4'd1;
1236
end
1237
 
1238
always @(posedge clk_26 or negedge rst_n) begin
1239
    if(rst_n == 1'b0)           horiz_cnt <= 8'd0;
1240
    else if(line_last_dot)      horiz_cnt <= 8'd0;
1241
    else if(character_last_dot) horiz_cnt <= horiz_cnt + 8'd1;
1242
end
1243
 
1244
always @(posedge clk_26 or negedge rst_n) begin
1245
    if(rst_n == 1'b0)           vert_cnt <= 10'd0;
1246
    else if(screen_last_dot)    vert_cnt <= 10'd0;
1247
    else if(line_last_dot)      vert_cnt <= vert_cnt + 10'd1;
1248
end
1249
 
1250
assign dot_memory_load =
1251
    (   (seq_8dot_char    && ~(seq_dotclock_divided) && dot_cnt_enable    && dot_cnt == 4'd3) ||
1252
        (seq_8dot_char    && seq_dotclock_divided    && ~(dot_cnt_enable) && dot_cnt == 4'd6) ||
1253
        (~(seq_8dot_char) && ~(seq_dotclock_divided) && dot_cnt_enable    && dot_cnt == 4'd4) ||
1254
        (~(seq_8dot_char) && seq_dotclock_divided    && ~(dot_cnt_enable) && dot_cnt == 4'd7)
1255
    ) &&
1256
    (   (vert_cnt == crtc_vertical_total - 10'd1 && horiz_cnt >= crtc_horizontal_total + 8'd3) ||
1257
        (vert_cnt < crtc_vertical_display_size && (horiz_cnt <= crtc_horizontal_display_size - 8'd2 || horiz_cnt >= crtc_horizontal_total + 8'd3)) ||
1258
        (vert_cnt == crtc_vertical_display_size && horiz_cnt <= crtc_horizontal_display_size - 8'd2)
1259
    );
1260
 
1261
assign dot_memory_load_first_in_frame = dot_memory_load && vert_cnt == crtc_vertical_total - 10'd1 && horiz_cnt == crtc_horizontal_total + 8'd3;
1262
assign dot_memory_load_first_in_line  = dot_memory_load && horiz_cnt == crtc_horizontal_total + 8'd3;
1263
assign dot_memory_load_first_in_line_matched =
1264
    dot_memory_load_first_in_line && (
1265
    (crtc_line_compare > 10'd0 && vert_cnt == crtc_line_compare - 10'd1) ||
1266
    (crtc_line_compare == 10'd0 && vert_cnt == crtc_vertical_total - 10'd1));
1267
 
1268
assign dot_memory_load_vertical_retrace_start = vert_cnt == crtc_vertical_retrace_start;
1269
 
1270
//------------------------------------------------------------------------------
1271
 
1272
reg host_io_vertical_retrace_last;
1273
always @(posedge clk_26 or negedge rst_n) begin
1274
    if(rst_n == 1'b0)   host_io_vertical_retrace_last <= 1'b0;
1275
    else                host_io_vertical_retrace_last <= host_io_vertical_retrace;
1276
end
1277
 
1278
reg [5:0] blink_cnt;
1279
always @(posedge clk_26 or negedge rst_n) begin
1280
    if(rst_n == 1'b0)           blink_cnt <= 6'd0;
1281
    else if(host_io_vertical_retrace_last == 1'b1 && host_io_vertical_retrace == 1'b0) blink_cnt <= blink_cnt + 6'd1;
1282
end
1283
 
1284
assign blink_txt_value    = blink_cnt[5];
1285
assign blink_cursor_value = blink_cnt[4];
1286
 
1287
//------------------------------------------------------------------------------
1288
 
1289
reg vgaprep_horiz_blank;
1290
always @(posedge clk_26 or negedge rst_n) begin
1291
    if(rst_n == 1'b0)                                                                                       vgaprep_horiz_blank <= 1'b0;
1292
    else if(horiz_cnt == crtc_horizontal_blanking_start)                                                    vgaprep_horiz_blank <= 1'b1;
1293
    else if(horiz_cnt > crtc_horizontal_blanking_start && horiz_cnt[5:0] == crtc_horizontal_blanking_end)   vgaprep_horiz_blank <= 1'b0;
1294
end
1295
 
1296
reg vgaprep_vert_blank;
1297
always @(posedge clk_26 or negedge rst_n) begin
1298
    if(rst_n == 1'b0)                                                                               vgaprep_vert_blank <= 1'b0;
1299
    else if(vert_cnt == crtc_vertical_blanking_start)                                               vgaprep_vert_blank <= 1'b1;
1300
    else if(vert_cnt > crtc_vertical_blanking_start && vert_cnt[7:0] == crtc_vertical_blanking_end) vgaprep_vert_blank <= 1'b0;
1301
end
1302
 
1303
wire vgaprep_blank =
1304
    seq_screen_disable || ~(seq_sync_reset_n) || ~(seq_async_reset_n) ||
1305
    //horizontal
1306
    horiz_cnt == crtc_horizontal_blanking_start || (horiz_cnt > crtc_horizontal_blanking_start && vgaprep_horiz_blank && horiz_cnt[5:0] != crtc_horizontal_blanking_end) ||
1307
    //line before vertical blank
1308
    (horiz_cnt >= crtc_horizontal_blanking_start && vert_cnt + 10'd1 == crtc_vertical_blanking_start) ||
1309
    //last line of vertical blank
1310
    ((~(vgaprep_vert_blank) || (vert_cnt[7:0] + 8'd1 != crtc_vertical_blanking_end) || horiz_cnt < crtc_horizontal_blanking_start) &&
1311
        //vertical
1312
        (vert_cnt == crtc_vertical_blanking_start    || (vert_cnt > crtc_vertical_blanking_start && vgaprep_vert_blank && vert_cnt[7:0] != crtc_vertical_blanking_end)));
1313
 
1314
wire vgaprep_horiz_sync =
1315
    horiz_cnt == (crtc_horizontal_retrace_start + { 6'd0, crtc_horizontal_retrace_skew }) ||
1316
    (horiz_cnt > (crtc_horizontal_retrace_start + { 6'd0, crtc_horizontal_retrace_skew }) && vgareg0_horiz_sync == ~(general_hsync) && horiz_cnt[4:0] != crtc_horizontal_retrace_end);
1317
 
1318
wire vgaprep_vert_sync =
1319
    vert_cnt == crtc_vertical_retrace_start ||
1320
    (vert_cnt > crtc_vertical_retrace_start && vgareg0_vert_sync == ~(general_vsync) && vert_cnt[3:0] != crtc_vertical_retrace_end);
1321
 
1322
//one cycle before input to vgareg_*
1323
assign vgaprep_overscan =
1324
    (horiz_cnt > crtc_horizontal_display_size  && ~(line_last_dot)) ||
1325
    (horiz_cnt == crtc_horizontal_display_size && character_last_dot) ||
1326
    (vert_cnt > crtc_vertical_display_size     && ~(screen_last_dot)) ||
1327
    (vert_cnt == crtc_vertical_display_size    && line_last_dot);
1328
 
1329
//------------------------------------------------------------------------------
1330
 
1331
wire [8:0] sys_readdata_from_ram;
1332
 
1333
assign sys_readdata = { 23'd0, sys_readdata_from_ram };
1334
 
1335
reg sys_enabled;
1336
always @(posedge clk_26 or negedge rst_n) begin
1337
    if(rst_n == 1'b0)                               sys_enabled <= 1'b0;
1338
    else if(sys_write && sys_writedata[15] == 1'b1) sys_enabled <= sys_writedata[14];
1339
end
1340
 
1341
wire [8:0] sys_character;
1342
wire [7:0] sys_line;
1343
 
1344
reg [6:0] sys_horiz_cnt;
1345
always @(posedge clk_26 or negedge rst_n) begin
1346
    if(rst_n == 1'b0)                                   sys_horiz_cnt <= 7'd0;
1347
    else if(sys_horiz_cnt == 7'd0 && horiz_cnt == 8'd1) sys_horiz_cnt <= 7'd1;
1348
    else if(sys_horiz_cnt > 7'd0)                       sys_horiz_cnt <= sys_horiz_cnt + 7'd1;
1349
end
1350
 
1351
wire [6:0] sys_horiz_cnt_plus_4 = sys_horiz_cnt + 7'd2;
1352
 
1353
 
1354
simple_bidir_ram #(
1355
    .widthad    (8),
1356
    .width      (9)
1357
)
1358
vga_system_ram (
1359
    .clk        (clk_26),
1360
 
1361
    .address_a  (sys_address),
1362
    .wren_a     (sys_write && sys_writedata[15:9] == 7'd0),
1363
    .data_a     (sys_writedata[8:0]),
1364
    .q_a        (sys_readdata_from_ram),
1365
 
1366
    .address_b  ({ ((vert_cnt >= 10'd256)? 4'd0 : vert_cnt[7:4]), sys_horiz_cnt_plus_4[6:3] }),
1367
    .q_b        (sys_character)
1368
);
1369
 
1370
reg sys_inverted;
1371
always @(posedge clk_26 or negedge rst_n) begin
1372
    if(rst_n == 1'b0)   sys_inverted <= 1'b0;
1373
    else                sys_inverted <= sys_character[8];
1374
end
1375
 
1376
simple_single_rom #(
1377
    .widthad    (11),
1378
    .width      (8),
1379
    .datafile   ("./../soc/vga/vga_font.bin")
1380
)
1381
vga_font_rom_inst (
1382
    .clk        (clk_26),
1383
    .addr       ({ sys_character[6:0], vert_cnt[3:0] }),
1384
    .q          (sys_line)
1385
);
1386
 
1387
wire sys_pixel =
1388
    (sys_horiz_cnt[2:0] == 3'd0)? sys_line[0] :
1389
    (sys_horiz_cnt[2:0] == 3'd1)? sys_line[1] :
1390
    (sys_horiz_cnt[2:0] == 3'd2)? sys_line[2] :
1391
    (sys_horiz_cnt[2:0] == 3'd3)? sys_line[3] :
1392
    (sys_horiz_cnt[2:0] == 3'd4)? sys_line[4] :
1393
    (sys_horiz_cnt[2:0] == 3'd5)? sys_line[5] :
1394
    (sys_horiz_cnt[2:0] == 3'd6)? sys_line[6] :
1395
                                  sys_line[7];
1396
 
1397
wire [7:0] sys_pixel_color = (sys_pixel ^ sys_inverted)? 8'd255 : 8'd30;
1398
 
1399
//------------------------------------------------------------------------------
1400
 
1401
assign host_io_vertical_retrace = vgaprep_vert_sync;
1402
assign host_io_not_displaying   = vgaprep_blank;
1403
 
1404
reg vgareg_blank_n;
1405
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) vgareg_blank_n <= 1'b0; else vgareg_blank_n <= ~(vgaprep_blank); end
1406
 
1407
reg vgareg0_horiz_sync;
1408
reg vgareg1_horiz_sync;
1409
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) vgareg0_horiz_sync <= 1'b0; else vgareg0_horiz_sync <= (vgaprep_horiz_sync && crtc_enable_sync)? ~(general_hsync) : general_hsync; end
1410
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) vgareg1_horiz_sync <= 1'b0; else vgareg1_horiz_sync <= vgareg0_horiz_sync; end
1411
 
1412
reg vgareg0_vert_sync;
1413
reg vgareg1_vert_sync;
1414
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) vgareg0_vert_sync <= 1'b0; else vgareg0_vert_sync <= (vgaprep_vert_sync && crtc_enable_sync)? ~(general_vsync) : general_vsync; end
1415
always @(posedge clk_26 or negedge rst_n) begin if(rst_n == 1'b0) vgareg1_vert_sync <= 1'b0; else vgareg1_vert_sync <= vgareg0_vert_sync; end
1416
 
1417
reg [7:0] vgareg_r;
1418
reg [7:0] vgareg_g;
1419
reg [7:0] vgareg_b;
1420
always @(posedge clk_26 or negedge rst_n) begin
1421
    if(rst_n == 1'b0)                                                                           vgareg_r <= 8'b0;
1422
    else if(sys_enabled && (horiz_cnt == 8'd1 || sys_horiz_cnt > 7'd0) && vert_cnt < 10'd256)   vgareg_r <= sys_pixel_color;
1423
    else                                                                                        vgareg_r <= { dac_color[17:12], 2'b0 };
1424
end
1425
always @(posedge clk_26 or negedge rst_n) begin
1426
    if(rst_n == 1'b0)                                                                           vgareg_g <= 8'b0;
1427
    else if(sys_enabled && (horiz_cnt == 8'd1 || sys_horiz_cnt > 7'd0) && vert_cnt < 10'd256)   vgareg_g <= sys_pixel_color;
1428
    else                                                                                        vgareg_g <= { dac_color[11:6], 2'b0 };
1429
end
1430
always @(posedge clk_26 or negedge rst_n) begin
1431
    if(rst_n == 1'b0)                                                                           vgareg_b <= 8'b0;
1432
    else if(sys_enabled && (horiz_cnt == 8'd1 || sys_horiz_cnt > 7'd0) && vert_cnt < 10'd256)   vgareg_b <= sys_pixel_color;
1433
    else                                                                                        vgareg_b <= { dac_color[5:0], 2'b0 };
1434
end
1435
 
1436
assign vga_clock  = clk_26;
1437
assign vga_sync_n = 1'b0;
1438
 
1439
assign vga_blank_n    = vgareg_blank_n;
1440
assign vga_horiz_sync = vgareg1_horiz_sync;
1441
assign vga_vert_sync  = vgareg1_vert_sync;
1442
 
1443
assign vga_r = vgareg_r;
1444
assign vga_g = vgareg_g;
1445
assign vga_b = vgareg_b;
1446
 
1447
//------------------------------------------------------------------------------
1448
 
1449
// synthesis translate_off
1450
wire _unused_ok = &{ 1'b0, sys_read, sys_writedata[31:16], host_address_reduced_last[16:2], memory_txt_address_base[12:0], sys_character[7], sys_horiz_cnt_plus_4[2:0], 1'b0 };
1451
// synthesis translate_on
1452
 
1453
//------------------------------------------------------------------------------
1454
 
1455
endmodule

powered by: WebSVN 2.1.0

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