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

Subversion Repositories aoocs

[/] [aoocs/] [trunk/] [rtl/] [ocs_control.v] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 alfik
/*
2
 * Copyright 2010, Aleksander Osman, alfik@poczta.fm. All rights reserved.
3
 *
4
 * Redistribution and use in source and binary forms, with or without modification, are
5
 * permitted provided that the following conditions are met:
6
 *
7
 *  1. Redistributions of source code must retain the above copyright notice, this list of
8
 *     conditions and the following disclaimer.
9
 *
10
 *  2. Redistributions in binary form must reproduce the above copyright notice, this list
11
 *     of conditions and the following disclaimer in the documentation and/or other materials
12
 *     provided with the distribution.
13
 *
14
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
15
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
16
 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR
17
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
19
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
21
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
22
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23
 */
24
 
25
/*! \file
26
 * \brief OCS system control implementation with WISHBONE slave interface.
27
 */
28
 
29
/*! \brief \copybrief ocs_control.v
30
 
31
List of system control registers:
32
\verbatim
33
Implemented:
34
     [DDFSTOP      094  W   A     Display bitplane data fetch stop
35
                                  (horiz. position)                             write not implemented here]
36
    DMACON       096  W   ADP     DMA control write (clear or set)              write not implemented here
37
 
38
    DMACONR     *002  R   AP      DMA control (and blitter status) read
39
    VPOSR       *004  R   A( E )  Read vert most signif. bit (and frame flop)
40
    VHPOSR      *006  R   A       Read vert and horiz. position of beam
41
 
42
    ADKCON       09E  W   P       Audio, disk, UART control
43
 
44
    ADKCONR     *010  R   P       Audio, disk control register read
45
     [POT0DAT   *012  R   P( E )  Pot counter pair 0 data (vert,horiz)          read implemented here]
46
 
47
    INTENAR     *01C  R   P       Interrupt enable bits read
48
    INTREQR     *01E  R   P       Interrupt request bits read
49
 
50
     [CLXCON     098  W   D       Collision control                             write not implemented here]
51
    INTENA       09A  W   P       Interrupt enable bits (clear or set bits)     write not implemented here
52
    INTREQ       09C  W   P       Interrupt request bits (clear or set bits)
53
 
54
Not implemented:
55
    REFPTR    & *028  W   A       Refresh pointer
56
    VPOSW       *02A  W   A       Write vert most signif. bit (and frame flop)
57
    VHPOSW      *02C  W   A       Write vert and horiz position of beam
58
 
59
    STREQU    & *038  S   D       Strobe for horiz sync with VB and EQU
60
    STRVBL    & *03A  S   D       Strobe for horiz sync with VB (vert. blank)
61
    STRHOR    & *03C  S   DP      Strobe for horiz sync
62
    STRLONG   & *03E  S   D( E )  Strobe for identification of long horiz. line.
63
 
64
    RESERVED     1110X
65
    RESERVED     1111X
66
    NO-OP(NULL)  1FE
67
\endverbatim
68
*/
69
module ocs_control(
70
    //% \name Clock and reset
71
    //% @{
72
    input               clk_30,
73
    input               reset_n,
74
    //% @}
75
 
76
    //% \name WISHBONE slave
77
    //% @{
78
    input               CYC_I,
79
    input               STB_I,
80
    input               WE_I,
81
    input [8:2]         ADR_I,
82
    input [3:0]         SEL_I,
83
    input [31:0]        slave_DAT_I,
84
    output reg [31:0]   slave_DAT_O,
85
    output reg          ACK_O,
86
    //% @}
87
 
88
    //% \name Not aligned register access on a 32-bit WISHBONE bus
89
    //% @{
90
        // INTENA write not implemented here
91
    input               na_int_ena_write,
92
    input [15:0]        na_int_ena,
93
    input [1:0]         na_int_ena_sel,
94
        // DMACON write not implemented here
95
    input               na_dma_con_write,
96
    input [15:0]        na_dma_con,
97
    input [1:0]         na_dma_con_sel,
98
        // POT0DAT read implemented here
99
    output              na_pot0dat_read,
100
    input [15:0]        na_pot0dat,
101
    //% @}
102
 
103
    //% \name Internal OCS ports: beam counters
104
    //% @{
105
    output reg          line_start,
106
    output reg          line_pre_start,
107
    output reg [8:0]    line_number,
108
    output reg [8:0]    column_number,
109
    //% @}
110
 
111
    //% \name Internal OCS ports: clock pulses for CIA and audio
112
    //% @{
113
    output reg          pulse_709379_hz,
114
    output              pulse_color,
115
    //% @}
116
 
117
    //% \name Internal OCS ports: global registers and blitter signals
118
    //% @{
119
    output reg [10:0]   dma_con,
120
    output reg [14:0]   adk_con,
121
 
122
    input               blitter_busy,
123
    input               blitter_zero,
124
    //% @}
125
 
126
    //% \name Internal OCS ports: interrupts
127
    //% @{
128
    input               blitter_irq,
129
    input               cia_a_irq,
130
    input               cia_b_irq,
131
    input               floppy_syn_irq,
132
    input               floppy_blk_irq,
133
    input               serial_rbf_irq,
134
    input               serial_tbe_irq,
135
    input [3:0]         audio_irq,
136
 
137
    output [2:0]        interrupt
138
    //% @}
139
);
140
 
141
assign interrupt =
142
    (int_ena[14] == 1'b0)? 3'd0 :
143
    (int_ena[13] == 1'b1 && int_req[13] == 1'b1) ? 3'd6 :
144
    (int_ena[12] == 1'b1 && int_req[12] == 1'b1) ? 3'd5 :
145
    (int_ena[11] == 1'b1 && int_req[11] == 1'b1) ? 3'd5 :
146
    (int_ena[10] == 1'b1 && int_req[10] == 1'b1) ? 3'd4 :
147
    (int_ena[9] == 1'b1 && int_req[9] == 1'b1) ? 3'd4 :
148
    (int_ena[8] == 1'b1 && int_req[8] == 1'b1) ? 3'd4 :
149
    (int_ena[7] == 1'b1 && int_req[7] == 1'b1) ? 3'd4 :
150
    (int_ena[6] == 1'b1 && int_req[6] == 1'b1) ? 3'd3 :
151
    (int_ena[5] == 1'b1 && int_req[5] == 1'b1) ? 3'd3 :
152
    (int_ena[4] == 1'b1 && int_req[4] == 1'b1) ? 3'd3 :
153
    (int_ena[3] == 1'b1 && int_req[3] == 1'b1) ? 3'd2 :
154
    (int_ena[2] == 1'b1 && int_req[2] == 1'b1) ? 3'd1 :
155
    (int_ena[1] == 1'b1 && int_req[1] == 1'b1) ? 3'd1 :
156
    (int_ena[0] == 1'b1 && int_req[0] == 1'b1) ? 3'd1 :
157
    3'd0;
158
 
159
wire [14:0] new_int_req;
160
assign new_int_req = {
161
    1'b0,
162
    cia_b_irq,
163
    floppy_syn_irq,
164
    serial_rbf_irq,
165
    audio_irq[3:0],
166
    blitter_irq,
167
    (line_start == 1'b1 && line_number == 9'd0),
168
    1'b0,
169
    cia_a_irq,
170
    1'b0,
171
    floppy_blk_irq,
172
    serial_tbe_irq
173
};
174
 
175
reg [14:0] int_ena;
176
reg [14:0] int_req;
177
reg [10:0] column_counter;
178
reg long_frame;
179
 
180
assign na_pot0dat_read = (CYC_I == 1'b1 && STB_I == 1'b1 && ACK_O == 1'b0 && WE_I == 1'b0 && { ADR_I, 2'b0 } == 9'h010 && SEL_I[1:0] != 2'b00);
181
 
182
always @(posedge clk_30 or negedge reset_n) begin
183
    if(reset_n == 1'b0) begin
184
        slave_DAT_O <= 32'd0;
185
        ACK_O <= 1'b0;
186
 
187
        line_start <= 1'b0;
188
        line_pre_start <= 1'b0;
189
        line_number <= 9'd0;
190
        column_number <= 9'd0;
191
 
192
        dma_con <= 11'd0;
193
        int_req <= 15'd0;
194
        int_ena <= 15'd0;
195
        adk_con <= 15'd0;
196
        column_counter <= 11'd0;
197
        long_frame <= 1'b0;
198
    end
199
    else begin
200
        if(na_dma_con_write == 1'b1 && na_dma_con_sel[1:0] == 2'b11) begin
201
            if(na_dma_con[15] == 1'b1)  dma_con <= dma_con | na_dma_con[10:0];
202
            else                        dma_con <= dma_con & (~na_dma_con[10:0]);
203
        end
204
 
205
        if(na_int_ena_write == 1'b1 && na_int_ena_sel[1:0] == 2'b11) begin
206
            if(na_int_ena[15] == 1'b1)  int_ena <= int_ena | na_int_ena[14:0];
207
            else                        int_ena <= int_ena & (~na_int_ena[14:0]);
208
        end
209
 
210
        if(column_counter == 11'd1919)  column_counter <= 11'd0;
211
        else                            column_counter <= column_counter + 11'd1;
212
 
213
        if(column_counter == 11'd1918)  line_pre_start <= 1'b1;
214
        else                            line_pre_start <= 1'b0;
215
 
216
        if(column_counter == 11'd1919)  line_start <= 1'b1;
217
        else                            line_start <= 1'b0;
218
 
219
        if(column_counter == 11'd1919) begin
220
            column_number <= 9'd0;
221
 
222
            if(line_number == 9'd311 && long_frame == 1'b0) begin
223
                line_number <= 9'd0;
224
                long_frame <= 1'b1;
225
            end
226
            else if(line_number == 9'd312 && long_frame == 1'b1) begin
227
                line_number <= 9'd0;
228
                long_frame <= 1'b0;
229
            end
230
            else line_number <= line_number + 9'd1;
231
        end
232
        else if(column_counter > 11'd600 /*time for 6 bitplain*/) begin
233
            if(column_counter[0] == 1'b1 && column_number < 9'd452 /*226*2*/)  column_number <= column_number + 9'd1;
234
        end
235
 
236
        if(ACK_O == 1'b1) ACK_O <= 1'b0;
237
 
238
        if(CYC_I == 1'b1 && STB_I == 1'b1 && ACK_O == 1'b0) begin
239
            ACK_O <= 1'b1;
240
 
241
            // BLTDDAT not used, DMACONR
242
            if(WE_I == 1'b0 && { ADR_I, 2'b0 } == 9'h000)       slave_DAT_O <= { 16'd0, 1'b0, blitter_busy, blitter_zero, 2'b00, dma_con[10:0] };
243
            // VPOSR, VHPOSR
244
            else if(WE_I == 1'b0 && { ADR_I, 2'b0 } == 9'h004)  slave_DAT_O <= { long_frame, 14'd0, line_number[8:0], column_number[8:1] };
245
            // INTENAR, INTREQR
246
            else if(WE_I == 1'b0 && { ADR_I, 2'b0 } == 9'h01C)  slave_DAT_O <= { 1'b0, int_ena[14:0], 1'b0, int_req[14:0] };
247
            // ADKCONR, POT0DAT read implemented here
248
            else if(WE_I == 1'b0 && { ADR_I, 2'b0 } == 9'h010)  slave_DAT_O <= { 1'b0, adk_con[14:0], na_pot0dat };
249
            // INTREQ, ADKCON
250
            else if(WE_I == 1'b1 && { ADR_I, 2'b0 } == 9'h09C) begin
251
                if(SEL_I[1:0] == 2'b11) begin
252
                    if(slave_DAT_I[15] == 1'b1) adk_con <= adk_con | slave_DAT_I[14:0];
253
                    else                        adk_con <= adk_con & (~slave_DAT_I[14:0]);
254
                end
255
            end
256
        end
257
 
258
        if(CYC_I == 1'b1 && STB_I == 1'b1 && ACK_O == 1'b0 && WE_I == 1'b1 && { ADR_I, 2'b0 } == 9'h09C && SEL_I[3:2] == 2'b11) begin
259
            if(slave_DAT_I[31] == 1'b1) int_req <= (int_req | (new_int_req /*& int_ena*/)) | slave_DAT_I[30:16];
260
            else                        int_req <= (int_req | (new_int_req /*& int_ena*/)) & (~slave_DAT_I[30:16]);
261
        end
262
        else                            int_req <= (int_req | (new_int_req /*& int_ena*/));
263
 
264
    end
265
end
266
 
267
 
268
 
269
 
270
// 1/10 fCPU == 1/20 color clock
271
reg [2:0] counter_709379_hz;
272
always @(posedge clk_30 or negedge reset_n) begin
273
    if(reset_n == 1'b0) begin
274
        counter_709379_hz <= 3'd0;
275
        pulse_709379_hz <= 1'b0;
276
    end
277
    else if(pulse_color == 1'b1) begin
278
        if(counter_709379_hz == 3'd4) begin
279
            pulse_709379_hz <= 1'b1;
280
            counter_709379_hz <= 3'd0;
281
        end
282
        else begin
283
            pulse_709379_hz <= 1'b0;
284
            counter_709379_hz <= counter_709379_hz + 3'd1;
285
        end
286
    end
287
    else begin
288
        pulse_709379_hz <= 1'b0;
289
    end
290
end
291
 
292
// 1/2 fCPU = 1 color clock
293
// 3.546875MHz
294
assign pulse_color = (pulse_cpu == 1'b1) && (pulse_counter == 1'b1);
295
 
296
reg pulse_counter;
297
always @(posedge clk_30 or negedge reset_n) begin
298
    if(reset_n == 1'b0)         pulse_counter <= 1'b0;
299
    else if(pulse_cpu == 1'b1)  pulse_counter <= ~pulse_counter;
300
end
301
 
302
// fCPU
303
// in: 30MHz, out: 7.09375MHz -> 960 - 227
304
reg [10:0] counter_cpu;
305
reg pulse_cpu;
306
always @(posedge clk_30 or negedge reset_n) begin
307
    if(reset_n == 1'b0) begin
308
        counter_cpu <= 11'd960;
309
        pulse_cpu <= 1'b0;
310
    end
311
    else if(counter_cpu <= 11'd114) begin
312
        counter_cpu <= counter_cpu - 11'd227 + 11'd960;
313
        pulse_cpu <= 1'b1;
314
    end
315
    else if(counter_cpu < 11'd227) begin
316
        counter_cpu <= counter_cpu + 11'd960;
317
        pulse_cpu <= 1'b0;
318
    end
319
    else if(counter_cpu > 11'd960) begin
320
        counter_cpu <= counter_cpu - 11'd227 - 11'd227;
321
        pulse_cpu <= 1'b1;
322
    end
323
    else begin
324
        counter_cpu <= counter_cpu - 11'd227;
325
        pulse_cpu <= 1'b0;
326
    end
327
end
328
 
329
endmodule
330
 

powered by: WebSVN 2.1.0

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