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

Subversion Repositories aoocs

[/] [aoocs/] [trunk/] [rtl/] [ocs_copper.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 copper implementation with WISHBONE master and slave interface.
27
 */
28
 
29
/*! \brief \copybrief ocs_copper.v
30
 
31
List of copper registers:
32
\verbatim
33
Implemented:
34
    COPCON      *02E  W   A( E )  Coprocessor control register (CDANG)
35
    COP1LCH   +  080  W   A( E )  Coprocessor first location register (high 3 bits, high 5 bits if ECS)
36
    COP1LCL   +  082  W   A       Coprocessor first location register (low 15 bits)
37
    COP2LCH   +  084  W   A( E )  Coprocessor second location register (high 3 bits, high 5 bits if ECS)
38
    COP2LCL   +  086  W   A       Coprocessor second location register (low 15 bits)
39
    COPJMP1      088  S   A       Coprocessor restart at first location
40
    COPJMP2      08A  S   A       Coprocessor restart at second location
41
Not implemented:
42
    COPINS       08C  W   A       Coprocessor instruction fetch identify
43
\endverbatim
44
 
45
\note
46
    \li \c COPINS is not implemented.
47
*/
48
module ocs_copper(
49
    //% \name Clock and reset
50
    //% @{
51
    input               CLK_I,
52
    input               reset_n,
53
    //% @}
54
 
55
    //% \name WISHBONE master
56
    //% @{
57
    output reg          CYC_O,
58
    output reg          STB_O,
59
    output reg          WE_O,
60
    output reg [31:2]   ADR_O,
61
    output reg [3:0]    SEL_O,
62
    output reg [31:0]   master_DAT_O,
63
    input [31:0]        master_DAT_I,
64
    input               ACK_I,
65
    //% @}
66
 
67
    //% \name WISHBONE slave
68
    //% @{
69
    input               CYC_I,
70
    input               STB_I,
71
    input               WE_I,
72
    input [8:2]         ADR_I,
73
    input [3:0]         SEL_I,
74
    input [31:0]        slave_DAT_I,
75
    output reg          ACK_O,
76
    //% @}
77
 
78
    //% \name Internal OCS ports
79
    //% @{
80
    input               line_start,
81
    input [8:0]         line_number,
82
    input [8:0]         column_number,
83
 
84
    input [10:0]        dma_con,
85
    input               blitter_busy
86
    //% @}
87
);
88
 
89
reg [15:0] cop_con;
90
reg [31:0] cop1_loc;
91
reg [31:0] cop2_loc;
92
 
93
reg [1:0] jump_strobe;
94
reg [1:0] state;
95
reg [31:0] pc;
96
reg [47:0] ir;
97
reg [1:0] avail;
98
 
99
parameter [1:0]
100
    S_IDLE          = 2'd0,
101
    S_LOAD          = 2'd1,
102
    S_SAVE          = 2'd2;
103
 
104
// MOVE: >= 0x20($80-$FF) always, >= 0x10 && < 0x20 CDANG, < 0x10($00-$3E) never
105
// WAIT: pos >= params;  PAL max(226,312)
106
//       horiz [7:1] bits, DDF,  0x0-0xE2, resolution 4 lowres, 8 hires, horiz blanking 0x0F-0x35, lowres 0x04-0x47 not used
107
//       vert [7:0] bits, 
108
// SKIP: pos >= params then skip next instruction
109
//
110
// enable bits: if 0 -> always true, vert[7] not masked, always checked
111
 
112
wire [31:0] move_address;
113
assign move_address = { 8'd0, 12'hDFF, 3'b0, ir[40:32] };
114
 
115
wire beam_compare;
116
assign beam_compare =
117
    (line_number[7:0] & { 1'b1, ir[30:24] }) > (ir[47:40] & { 1'b1, ir[30:24] }) ||
118
    (   (line_number[7:0] & { 1'b1, ir[30:24] }) == (ir[47:40] & { 1'b1, ir[30:24] }) &&
119
        (column_number[8:0] & { ir[23:17], 2'b0 }) >= ({ ir[39:33], 2'b0 } & { ir[23:17], 2'b0 })
120
    );
121
 
122
 
123
always @(posedge CLK_I or negedge reset_n) begin
124
    if(reset_n == 1'b0) begin
125
        CYC_O <= 1'b0;
126
        STB_O <= 1'b0;
127
        WE_O <= 1'b0;
128
        ADR_O <= 30'd0;
129
        SEL_O <= 4'b0000;
130
        master_DAT_O <= 32'd0;
131
        ACK_O <= 1'b0;
132
 
133
        cop_con <= 16'd0;
134
        cop1_loc <= 32'd0;
135
        cop2_loc <= 32'd0;
136
 
137
        jump_strobe <= 2'b11;
138
        state <= S_IDLE;
139
        pc <= 32'd0;
140
        ir <= 48'd0;
141
        avail <= 2'd0;
142
    end
143
    else begin
144
        if(CYC_I == 1'b1 && STB_I == 1'b1 /*&& WE_I == 1'b1*/ && ACK_O == 1'b0) ACK_O <= 1'b1;
145
        else ACK_O <= 1'b0;
146
 
147
        // JMP1
148
        if( (CYC_I == 1'b1 && STB_I == 1'b1 /*&& WE_I == 1'b1*/ && { ADR_I, 2'b0 } == 9'h088 && SEL_O[3:2] != 2'b00 && ACK_O == 1'b0) ||
149
            (line_start == 1'b1 && line_number == 9'd0) ) //PAL:25, NTSC: 20
150
        begin
151
            jump_strobe <= 2'b01;
152
        end
153
        // JMP2
154
        else if(CYC_I == 1'b1 && STB_I == 1'b1 /*&& WE_I == 1'b1*/ && { ADR_I, 2'b0 } == 9'h088 && SEL_O[1:0] != 2'b00 && ACK_O == 1'b0) begin
155
            jump_strobe <= 2'b10;
156
        end
157
        else if(state == S_SAVE &&
158
            ((cop_con[1] == 1'b1 && move_address[8:0] <= 9'h03E) || (cop_con[1] == 1'b0 && move_address[8:0] <= 9'h07E)))
159
        begin
160
            jump_strobe <= 2'b11;
161
        end
162
 
163
        // 02C:     VHPOSW(not used),   COPCON,
164
        // 080:     COP1LCH,            COP1LCL,
165
        // 084:     COP2LCH,            COP2LCL,
166
        // 088:     COPJMP1,            COPJMP2,
167
        if(CYC_I == 1'b1 && STB_I == 1'b1 && WE_I == 1'b1 && ACK_O == 1'b0) begin
168
            if({ ADR_I, 2'b0 } == 9'h02C && SEL_I[0] == 1'b1)  cop_con[7:0]   <= slave_DAT_I[7:0];
169
            if({ ADR_I, 2'b0 } == 9'h02C && SEL_I[1] == 1'b1)  cop_con[15:8]  <= slave_DAT_I[15:8];
170
            if({ ADR_I, 2'b0 } == 9'h02C && SEL_I[2] == 1'b1)  ;
171
            if({ ADR_I, 2'b0 } == 9'h02C && SEL_I[3] == 1'b1)  ;
172
            if({ ADR_I, 2'b0 } == 9'h080 && SEL_I[0] == 1'b1)  cop1_loc[7:0]   <= slave_DAT_I[7:0];
173
            if({ ADR_I, 2'b0 } == 9'h080 && SEL_I[1] == 1'b1)  cop1_loc[15:8]  <= slave_DAT_I[15:8];
174
            if({ ADR_I, 2'b0 } == 9'h080 && SEL_I[2] == 1'b1)  cop1_loc[23:16] <= slave_DAT_I[23:16];
175
            if({ ADR_I, 2'b0 } == 9'h080 && SEL_I[3] == 1'b1)  cop1_loc[31:24] <= slave_DAT_I[31:24];
176
            if({ ADR_I, 2'b0 } == 9'h084 && SEL_I[0] == 1'b1)  cop2_loc[7:0]   <= slave_DAT_I[7:0];
177
            if({ ADR_I, 2'b0 } == 9'h084 && SEL_I[1] == 1'b1)  cop2_loc[15:8]  <= slave_DAT_I[15:8];
178
            if({ ADR_I, 2'b0 } == 9'h084 && SEL_I[2] == 1'b1)  cop2_loc[23:16] <= slave_DAT_I[23:16];
179
            if({ ADR_I, 2'b0 } == 9'h084 && SEL_I[3] == 1'b1)  cop2_loc[31:24] <= slave_DAT_I[31:24];
180
        end
181
        else if(state == S_IDLE) begin
182
            // DMAEN, COPEN
183
            if(dma_con[9] == 1'b0 || dma_con[7] == 1'b0 ) begin
184
                jump_strobe <= 2'b11;
185
            end
186
            else if(jump_strobe == 2'b11) begin
187
                // no operation
188
            end
189
            else if(jump_strobe == 2'b01) begin
190
                jump_strobe <= 2'b00;
191
                pc <= cop1_loc;
192
                avail <= 2'd0;
193
                state <= S_LOAD;
194
            end
195
            else if(jump_strobe == 2'b10) begin
196
                jump_strobe <= 2'b00;
197
                pc <= cop2_loc;
198
                avail <= 2'd0;
199
                state <= S_LOAD;
200
            end
201
            else if(avail < 2'd2) begin
202
                state <= S_LOAD;
203
            end
204
            // MOVE
205
            else if(ir[32] == 1'b0) begin
206
                state <= S_SAVE;
207
            end
208
            // WAIT
209
            else if(ir[32] == 1'b1 && ir[16] == 1'b0 && (ir[31] == 1'b1 || blitter_busy == 1'b0) && beam_compare == 1'b1) begin
210
                avail <= avail - 2'd2;
211
                ir <= { ir[15:0], 32'd0 };
212
                state <= S_LOAD;
213
            end
214
            // SKIP
215
            else if(ir[32] == 1'b1 && ir[16] == 1'b1 && (ir[31] == 1'b1 || blitter_busy == 1'b0) && beam_compare == 1'b1) begin
216
                if(avail == 2'd2)   pc <= pc + 32'd4;
217
                else                pc <= pc + 32'd2;
218
 
219
                avail <= 2'd0;
220
                ir <= { ir[15:0], 32'd0 };
221
                state <= S_LOAD;
222
            end
223
 
224
        end
225
        else if(state == S_LOAD) begin
226
            if(ACK_I == 1'b1) begin
227
                CYC_O <= 1'b0;
228
                STB_O <= 1'b0;
229
 
230
                if(pc[1] == 1'b0 && avail == 2'd0) begin
231
                    pc <= pc + 32'd4;
232
                    avail <= avail + 2'd2;
233
                    ir[47:16] <= master_DAT_I[31:0];
234
                end
235
                else if(pc[1] == 1'b0 && avail == 2'd1) begin
236
                    pc <= pc + 32'd4;
237
                    avail <= avail + 2'd2;
238
                    ir[31:0] <= master_DAT_I[31:0];
239
                end
240
                else if(pc[1] == 1'b1 && avail == 2'd0) begin
241
                    pc <= pc + 32'd2;
242
                    avail <= avail + 2'd1;
243
                    ir[47:32] <= master_DAT_I[15:0];
244
                end
245
                else if(pc[1] == 1'b1 && avail == 2'd1) begin
246
                    pc <= pc + 32'd2;
247
                    avail <= avail + 2'd1;
248
                    ir[31:16] <= master_DAT_I[15:0];
249
                end
250
 
251
                state <= S_IDLE;
252
            end
253
            else begin
254
                CYC_O <= 1'b1;
255
                STB_O <= 1'b1;
256
                WE_O <= 1'b0;
257
                ADR_O <= pc[31:2];
258
                SEL_O <= 4'b1111;
259
            end
260
        end
261
        else if(state == S_SAVE) begin
262
            if(ACK_I == 1'b1 || (cop_con[1] == 1'b1 && move_address[8:0] <= 9'h03E) || (cop_con[1] == 1'b0 && move_address[8:0] <= 9'h07E))
263
            begin
264
                CYC_O <= 1'b0;
265
                STB_O <= 1'b0;
266
 
267
                avail <= avail - 2'd2;
268
                ir <= { ir[15:0], 32'd0 };
269
 
270
                state <= S_IDLE;
271
            end
272
            else begin
273
                CYC_O <= 1'b1;
274
                STB_O <= 1'b1;
275
                WE_O <= 1'b1;
276
                ADR_O <= move_address[31:2];
277
                if(move_address[1] == 1'b0) begin
278
                    SEL_O <= 4'b1100;
279
                    master_DAT_O <= { ir[31:16], 16'd0 };
280
                end
281
                else begin
282
                    SEL_O <= 4'b0011;
283
                    master_DAT_O <= { 16'd0, ir[31:16] };
284
                end
285
            end
286
        end
287
    end
288
end
289
 
290
endmodule
291
 

powered by: WebSVN 2.1.0

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