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

Subversion Repositories zx_ula

[/] [zx_ula/] [branches/] [xilinx/] [spectrum_48k_spartan3_starter_kit_timex_hicolor/] [ula.v] - Blame information for rev 14

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 14 mcleod_ide
`timescale 1ns / 1ps
2
//////////////////////////////////////////////////////////////////////////////////
3
// Company:        Dept. Architecture and Computing Technology. University of Seville
4
// Engineer:       Miguel Angel Rodriguez Jodar. rodriguj@atc.us.es
5
// 
6
// Create Date:    19:13:39 4-Apr-2012 
7
// Design Name:    ZX Spectrum
8
// Module Name:    ula 
9
// Project Name: 
10
// Target Devices: 
11
// Tool versions: 
12
// Description: 
13
//
14
// Dependencies: 
15
//
16
// Revision: 
17
// Revision 1.00 - File Created
18
// Additional Comments: GPL License policies apply to the contents of this file.
19
//
20
//////////////////////////////////////////////////////////////////////////////////
21
 
22
`define cyclestart(a,b) ((a)==(b))
23
`define cycleend(a,b) ((a)==(b+1))
24
 
25
module ula(
26
    input clk14,                        // 14MHz master clock
27
         input reset,                   // to reset the ULA to normal color mode.
28
         // CPU interfacing
29
    input [15:0] a,              // Address bus from CPU (not all lines are used)
30
    input [7:0] din,             // Input data bus from CPU
31
         output [7:0] dout,      // Output data bus to CPU
32
    input mreq_n,                       // MREQ from CPU
33
    input iorq_n,                       // IORQ from CPU
34
    input rd_n,                 // RD from CPU
35
    input wr_n,                 // WR from CPU
36
         input rfsh_n,                  // RFSH from CPU
37
         output clkcpu,         // CLK to CPU
38
         output msk_int_n,      // Vertical retrace interrupt, to CPU
39
         // VRAM interfacing
40
    output [13:0] va,     // Address bus to VRAM (16K)
41
         input [7:0] vramdout,// Data from VRAM to ULA/CPU
42
         output [7:0] vramdin,// Data from CPU to VRAM
43
    output vramoe,               // 
44
    output vramcs,               // Control signals for VRAM
45
    output vramwe,               //
46
         // ULA I/O
47
    input ear,                             //
48
    output mic,                    // I/O ports
49
    output spk,            //
50
         output [7:0] kbrows,   // Keyboard rows
51
    input [4:0] kbcolumns,       //  Keyboard columns
52
         // Video output
53
    output r,                           //
54
    output g,                           // RGB TTL signal
55
    output b,                           // with separate bright
56
    output i,                           // and composite sync
57
    output csync                        //               
58
    );
59
 
60
        reg [2:0] BorderColor = 3'b100;
61
        reg TimexHiColorMode = 0;
62
 
63
        // Pixel clock
64
        reg clk7 = 0;
65
        always @(posedge clk14)
66
                clk7 <= !clk7;
67
 
68
        // Horizontal counter
69
        reg [8:0] hc = 0;
70
        always @(posedge clk7) begin
71
                if (hc==447)
72
                        hc <= 0;
73
                else
74
                        hc <= hc + 1;
75
        end
76
 
77
        // Vertical counter
78
        reg [8:0] vc = 0;
79
        always @(posedge clk7) begin
80
                if (hc==447) begin
81
                        if (vc == 311)
82
                                vc <= 0;
83
                        else
84
                                vc <= vc + 1;
85
                end
86
        end
87
 
88
        // HBlank generation
89
        reg HBlank_n = 1;
90
        always @(negedge clk7) begin
91
                if (`cyclestart(hc,320))
92
                        HBlank_n <= 0;
93
                else if (`cycleend(hc,415))
94
                        HBlank_n <= 1;
95
        end
96
 
97
        // HSync generation (6C ULA version)
98
        reg HSync_n = 1;
99
        always @(negedge clk7) begin
100
                if (`cyclestart(hc,344))
101
                        HSync_n <= 0;
102
                else if (`cycleend(hc,375))
103
                        HSync_n <= 1;
104
        end
105
 
106
        // VBlank generation
107
        reg VBlank_n = 1;
108
        always @(negedge clk7) begin
109
                if (`cyclestart(vc,248))
110
                        VBlank_n <= 0;
111
                else if (`cycleend(vc,255))
112
                        VBlank_n <= 1;
113
        end
114
 
115
        // VSync generation (PAL)
116
        reg VSync_n = 1;
117
        always @(negedge clk7) begin
118
                if (`cyclestart(vc,248))
119
                        VSync_n <= 0;
120
                else if (`cycleend(vc,251))
121
                        VSync_n <= 1;
122
        end
123
 
124
        // INT generation
125
        reg INT_n = 1;
126
        assign msk_int_n = INT_n;
127
        always @(negedge clk7) begin
128
                if (`cyclestart(vc,248) && `cyclestart(hc,0))
129
                        INT_n <= 0;
130
                else if (`cyclestart(vc,248) && `cycleend(hc,31))
131
                        INT_n <= 1;
132
        end
133
 
134
        // Border control signal (=0 when we're not displaying paper/ink pixels)
135
        reg Border_n = 1;
136
        always @(negedge clk7) begin
137
                if ( (vc[7] & vc[6]) | vc[8] | hc[8])
138
                        Border_n <= 0;
139
                else
140
                        Border_n <= 1;
141
        end
142
 
143
        // VidEN generation (delaying Border 8 clocks)
144
        reg VidEN_n = 1;
145
        always @(negedge clk7) begin
146
                if (hc[3])
147
                        VidEN_n <= !Border_n;
148
        end
149
 
150
        // DataLatch generation (posedge to capture data from memory)
151
        reg DataLatch_n = 1;
152
        always @(negedge clk7) begin
153
                if (hc[0] & !hc[1] & Border_n & hc[3])
154
                        DataLatch_n <= 0;
155
                else
156
                        DataLatch_n <= 1;
157
        end
158
 
159
        // AttrLatch generation (posedge to capture data from memory)
160
        reg AttrLatch_n = 1;
161
        always @(negedge clk7) begin
162
                if (hc[0] & hc[1] & Border_n & hc[3])
163
                        AttrLatch_n <= 0;
164
                else
165
                        AttrLatch_n <= 1;
166
        end
167
 
168
        // SLoad generation (negedge to load shift register)
169
        reg SLoad = 0;
170
        always @(negedge clk7) begin
171
                if (!hc[0] & !hc[1] & hc[2] & !VidEN_n)
172
                        SLoad <= 1;
173
                else
174
                        SLoad <= 0;
175
        end
176
 
177
        // AOLatch generation (negedge to update attr output latch)
178
        reg AOLatch_n = 1;
179
        always @(negedge clk7) begin
180
                if (hc[0] & !hc[1] & hc[2])
181
                        AOLatch_n <= 0;
182
                else
183
                        AOLatch_n <= 1;
184
        end
185
 
186
        // First buffer for bitmap
187
        reg [7:0] BitmapReg = 0;
188
        always @(negedge DataLatch_n) begin
189
                BitmapReg <= vramdout;
190
        end
191
 
192
        // Shift register (second bitmap register)
193
        reg [7:0] SRegister = 0;
194
        always @(negedge clk7) begin
195
                if (SLoad)
196
                        SRegister <= BitmapReg;
197
                else
198
                        SRegister <= {SRegister[6:0],1'b0};
199
        end
200
 
201
        // First buffer for attribute
202
        reg [7:0] AttrReg = 0;
203
        always @(negedge AttrLatch_n) begin
204
                AttrReg <= vramdout;
205
        end
206
 
207
        // Second buffer for attribute
208
        reg [7:0] AttrOut = 0;
209
        always @(negedge AOLatch_n) begin
210
                if (!VidEN_n)
211
                        AttrOut <= AttrReg;
212
                else
213
                        AttrOut <= {2'b00,BorderColor,BorderColor};
214
        end
215
 
216
        // Flash counter and pixel generation
217
        reg [4:0] FlashCnt = 0;
218
        always @(negedge VSync_n) begin
219
                FlashCnt <= FlashCnt + 1;
220
        end
221
        wire Pixel = SRegister[7] ^ (AttrOut[7] & FlashCnt[4]);
222
 
223
        // RGB generation
224
        reg rI,rG,rR,rB;
225
        assign r = rR;
226
        assign g = rG;
227
        assign b = rB;
228
        assign i = rI;
229
        always @(*) begin
230
                if (HBlank_n && VBlank_n)
231
                        {rI,rG,rR,rB} = (Pixel)? {AttrOut[6],AttrOut[2:0]} : {AttrOut[6],AttrOut[5:3]};
232
                else
233
                        {rI,rG,rR,rB} = 4'b0000;
234
        end
235
 
236
        //CSync generation
237
        assign csync = HSync_n & VSync_n;
238
 
239
        // VRAM address and control line generation
240
        reg [13:0] rVA = 0;
241
        reg rVCS = 0;
242
        reg rVOE = 0;
243
        reg rVWE = 0;
244
        assign va = rVA;
245
        assign vramcs = rVCS;
246
        assign vramoe = rVOE;
247
        assign vramwe = rVWE;
248
        // Latches to hold delayed versions of V and H counters
249
        reg [8:0] v = 0;
250
        reg [8:0] c = 0;
251
        // Address and control line multiplexor ULA/CPU
252
        always @(negedge clk7) begin
253
                if (Border_n && (hc[3:0]==4'b0111 || hc[3:0]==4'b1011)) begin     // cycles 7 and 11: load V and C from VC and HC
254
                        c <= hc;
255
                        v <= vc;
256
                end
257
        end
258
        // Address and control line multiplexor ULA/CPU
259
        always @(*) begin
260
                if (Border_n && (hc[3:0]==4'b1000 || hc[3:0]==4'b1001 || hc[3:0]==4'b1100 || hc[3:0]==4'b1101)) begin       // cycles 8 and 12: present display address to VRAM 
261
                        rVA = {1'b0,v[7:6],v[2:0],v[5:3],c[7:3]};                                                // (cycles 9 and 13 load display byte)
262
                        rVCS = 1;
263
                        rVOE = !hc[0];
264
                        rVWE = 0;
265
                end
266
                else if (Border_n && (hc[3:0]==4'b1010 || hc[3:0]==4'b1011 || hc[3:0]==4'b1110 || hc[3:0]==4'b1111)) begin  // cycles 10 and 14: present attribute address to VRAM
267
                        rVA = (TimexHiColorMode)?       {1'b1,v[7:6],v[2:0],v[5:3],c[7:3]} :                                                                                                             // (cycles 11 and 15 load attr byte). 
268
                                                                                                {4'b0110,v[7:3],c[7:3]};                                                                                                                                                // Attribute address depends upon the mode selected
269
                        rVCS = 1;
270
                        rVOE = !hc[0];
271
                        rVWE = 0;
272
                end
273
                else if (Border_n && hc[3:0]==4'b0000) begin
274
                        rVA = a[13:0];
275
                        rVCS = 0;
276
                        rVOE = 0;
277
                        rVWE = 0;
278
                end
279
                else begin      // when VRAM is not in use by ULA, give it to CPU
280
                        rVA = a[13:0];
281
                        rVCS = !a[15] & a[14] & !mreq_n;
282
                        rVOE = !rd_n;
283
                        rVWE = !wr_n;
284
                end
285
        end
286
 
287
        // CPU contention
288
        reg CPUClk = 0;
289
        assign clkcpu = CPUClk;
290
        reg ioreqtw3 = 0;
291
        reg mreqt23 = 0;
292
        wire ioreq_n = a[0] | iorq_n;
293
        wire Nor1 = (~(a[14] | ~ioreq_n)) |
294
                    (~(~a[15] | ~ioreq_n)) |
295
                                        (~(hc[2] | hc[3])) |
296
                                        (~Border_n | ~ioreqtw3 | ~CPUClk | ~mreqt23);
297
        wire Nor2 = (~(hc[2] | hc[3])) |
298
                    ~Border_n |
299
                                        ~CPUClk |
300
                                        ioreq_n |
301
                                        ~ioreqtw3;
302
        wire CLKContention = ~Nor1 | ~Nor2;
303
 
304
        always @(posedge clk7) begin    // change clk7 by clk14 for 7MHz CPU clock operation
305
                if (CPUClk && !CLKContention)   // if there's no contention, the clock can go low
306
                        CPUClk <= 0;
307
                else
308
                        CPUClk <= 1;
309
        end
310
        always @(posedge CPUClk) begin
311
                ioreqtw3 <= ioreq_n;
312
                mreqt23 <= mreq_n;
313
        end
314
 
315
        // ULA-CPU interface
316
        assign dout = (!a[15] & a[14] & !mreq_n)? vramdout : // CPU reads VRAM through ULA as in the +3, not directly
317
                      (!iorq_n & !a[0])?          {1'b1,ear,1'b1,kbcolumns} :    // CPU reads keyboard and EAR state
318
                                          (!iorq_n && a[7:0]==8'hFF && !rd_n)? {6'b000000,TimexHiColorMode,1'b0} : // Timex hicolor config port. Only bit 1 is reported.
319
                                          (Border_n)?                  AttrReg :  // to emulate
320
                                                                      8'hFF;     // port FF (well, cannot be actually FF anymore)
321
        assign vramdin = din;           // The CPU doesn't need to share the memory input data bus with the ULA
322
        assign kbrows = {a[11]? 1'bz : 1'b0,    // high impedance or 0, as if diodes were been placed in between
323
                                                  a[10]? 1'bz : 1'b0,   // if the keyboard matrix is to be implemented within the FPGA, then
324
                                                  a[9]?  1'bz : 1'b0,   // there's no need to do this.
325
                                                  a[12]? 1'bz : 1'b0,
326
                                                  a[13]? 1'bz : 1'b0,
327
                                                  a[8]?  1'bz : 1'b0,
328
                                                  a[14]? 1'bz : 1'b0,
329
                                                  a[15]? 1'bz : 1'b0 };
330
        reg rMic = 0;
331
        reg rSpk = 0;
332
        assign mic = rMic;
333
        assign spk = rSpk;
334
        always @(negedge clk7 or posedge reset) begin
335
                if (reset)
336
                        TimexHiColorMode <= 0;
337
                else if (!iorq_n && a[7:0]==8'hFF && !wr_n)
338
                        TimexHiColorMode <= din[1];
339
                else if (!iorq_n & !a[0] & !wr_n)
340
                        {rSpk,rMic,BorderColor} <= din[5:0];
341
        end
342
endmodule

powered by: WebSVN 2.1.0

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