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

Subversion Repositories zx_ula

[/] [zx_ula/] [trunk/] [fpga_version/] [ula_test_for_ise_and_isim/] [ula.v] - Blame information for rev 5

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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