URL
https://opencores.org/ocsvn/aoocs/aoocs/trunk
ocs_copper.v
Go to the documentation of this file.
00001 /* 00002 Copyright 2010, Aleksander Osman, alfik@poczta.fm. All rights reserved. 00003 00004 Redistribution and use in source and binary forms, with or without modification, are 00005 permitted provided that the following conditions are met: 00006 00007 1. Redistributions of source code must retain the above copyright notice, this list of 00008 conditions and the following disclaimer. 00009 00010 2. Redistributions in binary form must reproduce the above copyright notice, this list 00011 of conditions and the following disclaimer in the documentation and/or other materials 00012 provided with the distribution. 00013 00014 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 00015 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 00016 FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR 00017 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00018 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 00019 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 00020 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00021 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 00022 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00023 */ 00024 00025 /*! \file 00026 \brief OCS copper implementation with WISHBONE master and slave interface. 00027 */ 00028 00029 /*! \brief \copybrief ocs_copper.v 00030 00031 List of copper registers: 00032 \verbatim 00033 Implemented: 00034 COPCON *02E W A( E ) Coprocessor control register (CDANG) 00035 COP1LCH + 080 W A( E ) Coprocessor first location register (high 3 bits, high 5 bits if ECS) 00036 COP1LCL + 082 W A Coprocessor first location register (low 15 bits) 00037 COP2LCH + 084 W A( E ) Coprocessor second location register (high 3 bits, high 5 bits if ECS) 00038 COP2LCL + 086 W A Coprocessor second location register (low 15 bits) 00039 COPJMP1 088 S A Coprocessor restart at first location 00040 COPJMP2 08A S A Coprocessor restart at second location 00041 Not implemented: 00042 COPINS 08C W A Coprocessor instruction fetch identify 00043 \endverbatim 00044 00045 \note 00046 \li \c COPINS is not implemented. 00047 */ 00048 module ocs_copper( 00049 //% \name Clock and reset 00050 //% @{ 00051 input CLK_I, 00052 input reset_n, 00053 //% @} 00054 00055 //% \name WISHBONE master 00056 //% @{ 00057 output reg CYC_O, 00058 output reg STB_O, 00059 output reg WE_O, 00060 output reg [31:2] ADR_O, 00061 output reg [3:0] SEL_O, 00062 output reg [31:0] master_DAT_O, 00063 input [31:0] master_DAT_I, 00064 input ACK_I, 00065 //% @} 00066 00067 //% \name WISHBONE slave 00068 //% @{ 00069 input CYC_I, 00070 input STB_I, 00071 input WE_I, 00072 input [8:2] ADR_I, 00073 input [3:0] SEL_I, 00074 input [31:0] slave_DAT_I, 00075 output reg ACK_O, 00076 //% @} 00077 00078 //% \name Internal OCS ports 00079 //% @{ 00080 input line_start, 00081 input [8:0] line_number, 00082 input [8:0] column_number, 00083 00084 input [10:0] dma_con, 00085 input blitter_busy 00086 //% @} 00087 ); 00088 00089 reg [15:0] cop_con; 00090 reg [31:0] cop1_loc; 00091 reg [31:0] cop2_loc; 00092 00093 reg [1:0] jump_strobe; 00094 reg [1:0] state; 00095 reg [31:0] pc; 00096 reg [47:0] ir; 00097 reg [1:0] avail; 00098 00099 parameter [1:0] 00100 S_IDLE = 2'd0, 00101 S_LOAD = 2'd1, 00102 S_SAVE = 2'd2; 00103 00104 // MOVE: >= 0x20($80-$FF) always, >= 0x10 && < 0x20 CDANG, < 0x10($00-$3E) never 00105 // WAIT: pos >= params; PAL max(226,312) 00106 // horiz [7:1] bits, DDF, 0x0-0xE2, resolution 4 lowres, 8 hires, horiz blanking 0x0F-0x35, lowres 0x04-0x47 not used 00107 // vert [7:0] bits, 00108 // SKIP: pos >= params then skip next instruction 00109 // 00110 // enable bits: if 0 -> always true, vert[7] not masked, always checked 00111 00112 wire [31:0] move_address; 00113 assign move_address = { 8'd0, 12'hDFF, 3'b0, ir[40:32] }; 00114 00115 wire beam_compare; 00116 assign beam_compare = 00117 (line_number[7:0] & { 1'b1, ir[30:24] }) > (ir[47:40] & { 1'b1, ir[30:24] }) || 00118 ( (line_number[7:0] & { 1'b1, ir[30:24] }) == (ir[47:40] & { 1'b1, ir[30:24] }) && 00119 (column_number[8:0] & { ir[23:17], 2'b0 }) >= ({ ir[39:33], 2'b0 } & { ir[23:17], 2'b0 }) 00120 ); 00121 00122 00123 always @(posedge CLK_I or negedge reset_n) begin 00124 if(reset_n == 1'b0) begin 00125 CYC_O <= 1'b0; 00126 STB_O <= 1'b0; 00127 WE_O <= 1'b0; 00128 ADR_O <= 30'd0; 00129 SEL_O <= 4'b0000; 00130 master_DAT_O <= 32'd0; 00131 ACK_O <= 1'b0; 00132 00133 cop_con <= 16'd0; 00134 cop1_loc <= 32'd0; 00135 cop2_loc <= 32'd0; 00136 00137 jump_strobe <= 2'b11; 00138 state <= S_IDLE; 00139 pc <= 32'd0; 00140 ir <= 48'd0; 00141 avail <= 2'd0; 00142 end 00143 else begin 00144 if(CYC_I == 1'b1 && STB_I == 1'b1 /*&& WE_I == 1'b1**/ && ACK_O == 1'b0) ACK_O <= 1'b1; 00145 else ACK_O <= 1'b0; 00146 00147 // JMP1 00148 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) || 00149 (line_start == 1'b1 && line_number == 9'd0) ) //PAL:25, NTSC: 20 00150 begin 00151 jump_strobe <= 2'b01; 00152 end 00153 // JMP2 00154 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 00155 jump_strobe <= 2'b10; 00156 end 00157 else if(state == S_SAVE && 00158 ((cop_con[1] == 1'b1 && move_address[8:0] <= 9'h03E) || (cop_con[1] == 1'b0 && move_address[8:0] <= 9'h07E))) 00159 begin 00160 jump_strobe <= 2'b11; 00161 end 00162 00163 // 02C: VHPOSW(not used), COPCON, 00164 // 080: COP1LCH, COP1LCL, 00165 // 084: COP2LCH, COP2LCL, 00166 // 088: COPJMP1, COPJMP2, 00167 if(CYC_I == 1'b1 && STB_I == 1'b1 && WE_I == 1'b1 && ACK_O == 1'b0) begin 00168 if({ ADR_I, 2'b0 } == 9'h02C && SEL_I[0] == 1'b1) cop_con[7:0] <= slave_DAT_I[7:0]; 00169 if({ ADR_I, 2'b0 } == 9'h02C && SEL_I[1] == 1'b1) cop_con[15:8] <= slave_DAT_I[15:8]; 00170 if({ ADR_I, 2'b0 } == 9'h02C && SEL_I[2] == 1'b1) ; 00171 if({ ADR_I, 2'b0 } == 9'h02C && SEL_I[3] == 1'b1) ; 00172 if({ ADR_I, 2'b0 } == 9'h080 && SEL_I[0] == 1'b1) cop1_loc[7:0] <= slave_DAT_I[7:0]; 00173 if({ ADR_I, 2'b0 } == 9'h080 && SEL_I[1] == 1'b1) cop1_loc[15:8] <= slave_DAT_I[15:8]; 00174 if({ ADR_I, 2'b0 } == 9'h080 && SEL_I[2] == 1'b1) cop1_loc[23:16] <= slave_DAT_I[23:16]; 00175 if({ ADR_I, 2'b0 } == 9'h080 && SEL_I[3] == 1'b1) cop1_loc[31:24] <= slave_DAT_I[31:24]; 00176 if({ ADR_I, 2'b0 } == 9'h084 && SEL_I[0] == 1'b1) cop2_loc[7:0] <= slave_DAT_I[7:0]; 00177 if({ ADR_I, 2'b0 } == 9'h084 && SEL_I[1] == 1'b1) cop2_loc[15:8] <= slave_DAT_I[15:8]; 00178 if({ ADR_I, 2'b0 } == 9'h084 && SEL_I[2] == 1'b1) cop2_loc[23:16] <= slave_DAT_I[23:16]; 00179 if({ ADR_I, 2'b0 } == 9'h084 && SEL_I[3] == 1'b1) cop2_loc[31:24] <= slave_DAT_I[31:24]; 00180 end 00181 else if(state == S_IDLE) begin 00182 // DMAEN, COPEN 00183 if(dma_con[9] == 1'b0 || dma_con[7] == 1'b0 ) begin 00184 jump_strobe <= 2'b11; 00185 end 00186 else if(jump_strobe == 2'b11) begin 00187 // no operation 00188 end 00189 else if(jump_strobe == 2'b01) begin 00190 jump_strobe <= 2'b00; 00191 pc <= cop1_loc; 00192 avail <= 2'd0; 00193 state <= S_LOAD; 00194 end 00195 else if(jump_strobe == 2'b10) begin 00196 jump_strobe <= 2'b00; 00197 pc <= cop2_loc; 00198 avail <= 2'd0; 00199 state <= S_LOAD; 00200 end 00201 else if(avail < 2'd2) begin 00202 state <= S_LOAD; 00203 end 00204 // MOVE 00205 else if(ir[32] == 1'b0) begin 00206 state <= S_SAVE; 00207 end 00208 // WAIT 00209 else if(ir[32] == 1'b1 && ir[16] == 1'b0 && (ir[31] == 1'b1 || blitter_busy == 1'b0) && beam_compare == 1'b1) begin 00210 avail <= avail - 2'd2; 00211 ir <= { ir[15:0], 32'd0 }; 00212 state <= S_LOAD; 00213 end 00214 // SKIP 00215 else if(ir[32] == 1'b1 && ir[16] == 1'b1 && (ir[31] == 1'b1 || blitter_busy == 1'b0) && beam_compare == 1'b1) begin 00216 if(avail == 2'd2) pc <= pc + 32'd4; 00217 else pc <= pc + 32'd2; 00218 00219 avail <= 2'd0; 00220 ir <= { ir[15:0], 32'd0 }; 00221 state <= S_LOAD; 00222 end 00223 00224 end 00225 else if(state == S_LOAD) begin 00226 if(ACK_I == 1'b1) begin 00227 CYC_O <= 1'b0; 00228 STB_O <= 1'b0; 00229 00230 if(pc[1] == 1'b0 && avail == 2'd0) begin 00231 pc <= pc + 32'd4; 00232 avail <= avail + 2'd2; 00233 ir[47:16] <= master_DAT_I[31:0]; 00234 end 00235 else if(pc[1] == 1'b0 && avail == 2'd1) begin 00236 pc <= pc + 32'd4; 00237 avail <= avail + 2'd2; 00238 ir[31:0] <= master_DAT_I[31:0]; 00239 end 00240 else if(pc[1] == 1'b1 && avail == 2'd0) begin 00241 pc <= pc + 32'd2; 00242 avail <= avail + 2'd1; 00243 ir[47:32] <= master_DAT_I[15:0]; 00244 end 00245 else if(pc[1] == 1'b1 && avail == 2'd1) begin 00246 pc <= pc + 32'd2; 00247 avail <= avail + 2'd1; 00248 ir[31:16] <= master_DAT_I[15:0]; 00249 end 00250 00251 state <= S_IDLE; 00252 end 00253 else begin 00254 CYC_O <= 1'b1; 00255 STB_O <= 1'b1; 00256 WE_O <= 1'b0; 00257 ADR_O <= pc[31:2]; 00258 SEL_O <= 4'b1111; 00259 end 00260 end 00261 else if(state == S_SAVE) begin 00262 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)) 00263 begin 00264 CYC_O <= 1'b0; 00265 STB_O <= 1'b0; 00266 00267 avail <= avail - 2'd2; 00268 ir <= { ir[15:0], 32'd0 }; 00269 00270 state <= S_IDLE; 00271 end 00272 else begin 00273 CYC_O <= 1'b1; 00274 STB_O <= 1'b1; 00275 WE_O <= 1'b1; 00276 ADR_O <= move_address[31:2]; 00277 if(move_address[1] == 1'b0) begin 00278 SEL_O <= 4'b1100; 00279 master_DAT_O <= { ir[31:16], 16'd0 }; 00280 end 00281 else begin 00282 SEL_O <= 4'b0011; 00283 master_DAT_O <= { 16'd0, ir[31:16] }; 00284 end 00285 end 00286 end 00287 end 00288 end 00289 00290 endmodule 00291
Generated on Mon Dec 20 2010 21:20:18 for aoOCS by 1.7.2
powered by: WebSVN 2.1.0