00001 ///////////////////////////////////////////////////////////////////// 00002 //// //// 00003 //// Mini-RISC-1 //// 00004 //// Mini-Risc Core //// 00005 //// //// 00006 //// //// 00007 //// Author: Rudolf Usselmann //// 00008 //// rudi@asics.ws //// 00009 //// //// 00010 //// //// 00011 //// D/L from: http://www.opencores.org/cores/minirisc/ //// 00012 //// //// 00013 ///////////////////////////////////////////////////////////////////// 00014 //// //// 00015 //// Copyright (C) 2000-2002 Rudolf Usselmann //// 00016 //// www.asics.ws //// 00017 //// rudi@asics.ws //// 00018 //// //// 00019 //// This source file may be used and distributed without //// 00020 //// restriction provided that this copyright statement is not //// 00021 //// removed from the file and that any derivative work contains //// 00022 //// the original copyright notice and the associated disclaimer.//// 00023 //// //// 00024 //// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// 00025 //// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// 00026 //// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// 00027 //// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR //// 00028 //// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, //// 00029 //// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES //// 00030 //// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE //// 00031 //// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR //// 00032 //// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF //// 00033 //// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT //// 00034 //// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT //// 00035 //// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE //// 00036 //// POSSIBILITY OF SUCH DAMAGE. //// 00037 //// //// 00038 ///////////////////////////////////////////////////////////////////// 00039 00040 // CVS Log 00041 // 00042 // $Id: risc_core.v,v 1.3 2002/10/01 12:44:24 rudi Exp $ 00043 // 00044 // $Date: 2002/10/01 12:44:24 $ 00045 // $Revision: 1.3 $ 00046 // $Author: rudi $ 00047 // $Locker: $ 00048 // $State: Exp $ 00049 // 00050 // Change History: 00051 // $Log: risc_core.v,v $ 00052 // Revision 1.3 2002/10/01 12:44:24 rudi 00053 // Tweaked code a bit - trying to get it run faster ... 00054 // 00055 // Revision 1.2 2002/09/27 15:35:40 rudi 00056 // Minor update to newer devices ... 00057 // 00058 // 00059 // 00060 // 00061 // 00062 // 00063 // 00064 // 00065 // 00066 // 00067 // 00068 00069 `timescale 1ns / 10ps 00070 //%@file this is new one 00071 module mrisc( 00072 clk, 00073 rst_in, 00074 00075 inst_addr, 00076 inst_data, 00077 00078 portain, 00079 portbin, 00080 portcin, 00081 00082 portaout, 00083 portbout, 00084 portcout, 00085 00086 trisa, 00087 trisb, 00088 trisc, 00089 00090 tcki, 00091 wdt_en ); 00092 00093 // Basic Core I/O. 00094 input clk; 00095 input rst_in; 00096 00097 // Program memory interface 00098 output [10:0] inst_addr; 00099 input [11:0] inst_data; 00100 00101 // Basic I/O Ports 00102 input [7:0] portain; 00103 input [7:0] portbin; 00104 input [7:0] portcin; 00105 00106 output [7:0] portaout; 00107 output [7:0] portbout; 00108 output [7:0] portcout; 00109 00110 output [7:0] trisa; 00111 output [7:0] trisb; 00112 output [7:0] trisc; 00113 00114 input tcki; 00115 input wdt_en; 00116 00117 // This should be set to the ROM location where our restart vector is. 00118 // As set here, we have 512 words of program space. 00119 parameter PC_RST_VECTOR = 11'h000, // Should be: 11'h7FF, 00120 STAT_RST_VALUE = 8'h18, 00121 OPT_RST_VALUE = 8'h3f, 00122 FSR_RST_VALUE = 7'h0, 00123 TRIS_RST_VALUE = 8'hff; 00124 00125 parameter ALU_ADD = 4'h0, 00126 ALU_SUB = 4'h1, 00127 ALU_INC = 4'h2, 00128 ALU_DEC = 4'h3, 00129 00130 ALU_AND = 4'h4, 00131 ALU_CLR = 4'h5, 00132 ALU_NOT = 4'h6, 00133 ALU_IOR = 4'h7, 00134 ALU_MOV = 4'h8, 00135 ALU_MOVW = 4'h9, 00136 ALU_RLF = 4'ha, 00137 ALU_RRF = 4'hb, 00138 ALU_SWP = 4'hc, 00139 ALU_XOR = 4'hd, 00140 ALU_BCF = 4'he, 00141 ALU_BSF = 4'hf; 00142 00143 parameter // Byte Oriented RF Operations 00144 I_ADDWF = 12'b0001_11??_????, 00145 I_ANDWF = 12'b0001_01??_????, 00146 I_CLRF = 12'b0000_011?_????, 00147 I_CLRW = 12'b0000_0100_0000, 00148 I_COMF = 12'b0010_01??_????, 00149 I_DEC = 12'b0000_11??_????, 00150 I_DECFSZ = 12'b0010_11??_????, 00151 I_INCF = 12'b0010_10??_????, 00152 I_INCFSZ = 12'b0011_11??_????, 00153 I_IORWF = 12'b0001_00??_????, 00154 I_MOV = 12'b0010_00??_????, 00155 I_MOVWF = 12'b0000_001?_????, 00156 I_NOP = 12'b0000_0000_0000, 00157 I_RLF = 12'b0011_01??_????, 00158 I_RRF = 12'b0011_00??_????, 00159 I_SUBWF = 12'b0000_10??_????, 00160 I_SWAPF = 12'b0011_10??_????, 00161 I_XORWF = 12'b0001_10??_????, 00162 00163 // Bit Oriented RF Operations 00164 I_BCF = 12'b0100_????_????, 00165 I_BSF = 12'b0101_????_????, 00166 I_BTFSC = 12'b0110_????_????, 00167 I_BTFSS = 12'b0111_????_????, 00168 00169 // Literal & Controll Operations 00170 I_ANDLW = 12'b1110_????_????, 00171 I_CALL = 12'b1001_????_????, 00172 I_CLRWDT = 12'b0000_0000_0100, 00173 I_GOTO = 12'b101?_????_????, 00174 I_IORLW = 12'b1101_????_????, 00175 I_MOVLW = 12'b1100_????_????, 00176 I_OPTION = 12'b0000_0000_0010, 00177 I_RETLW = 12'b1000_????_????, 00178 I_SLEEP = 12'b0000_0000_0011, 00179 I_TRIS = 12'b0000_0000_0???, 00180 I_XORLW = 12'b1111_????_????; 00181 00182 parameter // sfr register address encodings 00183 INDF_ADDR = 3'h0, 00184 TMR0_ADDR = 3'h1, 00185 PCL_ADDR = 3'h2, 00186 STAT_ADDR = 3'h3, 00187 FSR_ADDR = 3'h4, 00188 PORTA_ADDR = 3'h5, 00189 PORTB_ADDR = 3'h6, 00190 PORTC_ADDR = 3'h7; 00191 00192 parameter // Source 1 Select 00193 K_SEL = 2'b10, 00194 SFR_SEL = 2'b00, 00195 RF_SEL = 2'b01; 00196 00197 parameter // STATUS Register status bits we 00198 STAT_WR_C = 3'b001, 00199 STAT_WR_DC = 3'b010, 00200 STAT_WR_Z = 3'b100; 00201 00202 00203 // Instruction Register 00204 reg rst; 00205 reg [11:0] instr_0, instr_1; 00206 reg rst_r1, rst_r2; 00207 wire valid; 00208 reg valid_1; 00209 00210 reg [7:0] mask; 00211 reg [7:0] sfr_rd_data; 00212 reg [3:0] alu_op; 00213 reg src1_sel; 00214 reg [1:0] src1_sel_; 00215 00216 wire [7:0] dout; // ALU output 00217 wire [7:0] src1; // ALU Source 1 00218 00219 reg [2:0] stat_bwe; // status bits we 00220 wire c_out, dc_out, z_out; 00221 00222 reg pc_skz, pc_skz_; 00223 reg pc_bset, pc_bset_; 00224 reg pc_bclr, pc_bclr_; 00225 reg pc_call, pc_call_; 00226 reg pc_goto, pc_goto_; 00227 reg pc_retlw, pc_retlw_; 00228 00229 wire invalidate_1; 00230 wire invalidate_0_; 00231 reg invalidate_0; 00232 00233 // stage 1 dst decode 00234 reg w_we_; 00235 reg rf_we_; 00236 reg sfr_we_; 00237 reg tris_we_; 00238 00239 // stage 2 dst decode 00240 reg w_we; 00241 wire rf_we; 00242 reg rf_we1, rf_we2, rf_we3; 00243 00244 reg opt_we; 00245 reg trisa_we; 00246 reg trisb_we; 00247 reg trisc_we; 00248 00249 wire indf_we_; 00250 reg tmr0_we; 00251 wire pc_we_; 00252 reg pc_we; 00253 reg stat_we; 00254 reg fsr_we; 00255 reg porta_we; 00256 reg portb_we; 00257 reg portc_we; 00258 00259 wire bit_sel; 00260 wire [7:0] tmr0_next, tmr0_next1, tmr0_plus_1; 00261 wire tmr0_cnt_en; 00262 reg wdt_clr; 00263 wire wdt_to; 00264 wire wdt_en; 00265 wire tcki; 00266 00267 wire [7:0] sfr_rd_data_tmp1, sfr_rd_data_tmp2, sfr_rd_data_tmp3; 00268 00269 // Register File Connections 00270 wire [1:0] rf_rd_bnk, rf_wr_bnk; 00271 wire [4:0] rf_rd_addr, rf_wr_addr; 00272 wire [7:0] rf_rd_data, rf_wr_data; 00273 00274 // Program Counter 00275 reg [10:0] inst_addr; 00276 reg [10:0] pc; 00277 wire [10:0] pc_next; 00278 wire [10:0] pc_plus_1; 00279 wire [10:0] stack_out; 00280 reg [10:0] pc_r, pc_r2; 00281 wire [10:0] pc_next1, pc_next2, pc_next3; 00282 00283 // W Register 00284 reg [7:0] w; // Working Register 00285 reg [7:0] status; // Status Register 00286 wire [7:0] status_next; 00287 reg [6:0] fsr; // fsr register ( for indirect addressing) 00288 wire [6:0] fsr_next; 00289 reg [7:0] tmr0; // Timer 0 00290 reg [5:0] option; // Option Register 00291 00292 // Tristate Control registers. 00293 reg [7:0] trisa; 00294 reg [7:0] trisb; 00295 reg [7:0] trisc; 00296 00297 // I/O Port registers 00298 reg [7:0] porta_r; // PORTA input register 00299 reg [7:0] portb_r; // PORTB input register 00300 reg [7:0] portc_r; // PORTC input register 00301 reg [7:0] portaout; // PORTA output register 00302 reg [7:0] portbout; // PORTB output register 00303 reg [7:0] portcout; // PORTC output register 00304 00305 //////////////////////////////////////////////////////////////////////// 00306 // External Reset is Synchrounous to clock 00307 always @(posedge clk) 00308 rst <= #1 rst_in; 00309 00310 //////////////////////////////////////////////////////////////////////// 00311 // Synchrounous Register File 00312 register_file u0( .clk( clk ), 00313 .rst( rst ), 00314 .rf_rd_bnk( rf_rd_bnk ), 00315 .rf_rd_addr( rf_rd_addr ), 00316 .rf_rd_data( rf_rd_data ), 00317 .rf_we( rf_we ), 00318 .rf_wr_bnk( rf_wr_bnk ), 00319 .rf_wr_addr( rf_wr_addr ), 00320 .rf_wr_data( rf_wr_data ) 00321 ); 00322 00323 //////////////////////////////////////////////////////////////////////// 00324 // Always Fetch Next Instruction 00325 always @(posedge clk) 00326 instr_0 <= #1 inst_data; 00327 00328 //////////////////////////////////////////////////////////////////////// 00329 // Instr Decode & Read Logic 00330 //% clock divider super 00331 always @(posedge clk) 00332 begin 00333 rst_r1 <= #1 rst | wdt_to; 00334 rst_r2 <= #1 rst | rst_r1 | wdt_to; 00335 end 00336 00337 assign valid = ~rst_r2 & ~invalidate_1; 00338 always @(posedge clk) 00339 valid_1 <= #1 valid; 00340 //% clock divider 00341 always @(posedge clk) 00342 instr_1 <= #1 instr_0; 00343 00344 always @(posedge clk) //# Basic Decode extracted directly from the instruction 00345 begin 00346 // Mask for bit modification instructions 00347 case(instr_0[7:5]) // synopsys full_case parallel_case 00348 0: mask <= #1 8'h01; 00349 1: mask <= #1 8'h02; 00350 2: mask <= #1 8'h04; 00351 3: mask <= #1 8'h08; 00352 4: mask <= #1 8'h10; 00353 5: mask <= #1 8'h20; 00354 6: mask <= #1 8'h40; 00355 7: mask <= #1 8'h80; 00356 endcase 00357 end 00358 00359 always @(posedge clk) 00360 pc_r <= #1 pc; // Previous version of PC to accomodate for pipeline 00361 00362 always @(posedge clk) // SFR Read Operands 00363 if(src1_sel_[1]) sfr_rd_data <= #1 instr_0[7:0]; 00364 else 00365 case(instr_0[2:0]) // synopsys full_case parallel_case 00366 1: sfr_rd_data <= #1 tmr0_next; 00367 2: sfr_rd_data <= #1 pc_r[7:0]; 00368 3: sfr_rd_data <= #1 status_next; 00369 4: sfr_rd_data <= #1 {1'b1, fsr_next}; 00370 5: sfr_rd_data <= #1 porta_r; 00371 6: sfr_rd_data <= #1 portb_r; 00372 7: sfr_rd_data <= #1 portc_r; 00373 endcase 00374 00375 00376 /* 00377 always @(posedge clk) 00378 sfr_rd_data <= #1 sfr_rd_data_tmp1; 00379 00380 00381 reg [3:0] sfr_sel; 00382 wire [3:0] sfr_sel_src; 00383 00384 assign sfr_sel_src = {src1_sel_[1],instr_0[2:0]}; 00385 00386 always @(sfr_sel_src) 00387 casex(sfr_sel_src) // synopsys full_case parallel_case 00388 4'b1_???: sfr_sel = 4'b01_11; 00389 4'b0_001: sfr_sel = 4'bxx_00; 00390 4'b0_010: sfr_sel = 4'b00_11; 00391 4'b0_011: sfr_sel = 4'bxx_01; 00392 4'b0_100: sfr_sel = 4'bxx_10; 00393 4'b0_101: sfr_sel = 4'b10_11; 00394 4'b0_11?: sfr_sel = 4'b11_11; 00395 endcase 00396 00397 00398 mux4_8 u1( .sel(sfr_sel[1:0]), .out(sfr_rd_data_tmp1), 00399 .in0(tmr0_next), .in1(status_next), 00400 .in2({1'b1, fsr_next}), .in3(sfr_rd_data_tmp2) ); 00401 00402 mux4_8 u2( .sel(sfr_sel[3:2]), .out(sfr_rd_data_tmp2), 00403 .in0(pc_r[7:0]), .in1(instr_0[7:0]), 00404 .in2(porta_r), .in3(sfr_rd_data_tmp3) ); 00405 00406 mux2_8 u2b( .sel(instr_0[0]), .out(sfr_rd_data_tmp3), 00407 .in0(portb_r), .in1(portc_r) ); 00408 * 00409 00410 reg instd_zero; 00411 00412 always @(posedge clk) 00413 instd_zero <= #1 !(|inst_data[4:0]); 00414 00415 // Register File Read Port 00416 assign rf_rd_bnk = fsr_next[6:5]; 00417 assign rf_rd_addr = instd_zero ? fsr_next[4:0] : instr_0[4:0]; 00418 00419 // ALU OP 00420 always @(posedge clk) 00421 casex(instr_0) // synopsys full_case parallel_case 00422 // Byte Oriented RF Operations 00423 I_ADDWF: alu_op <= #1 ALU_ADD; // ADDWF 00424 I_ANDWF: alu_op <= #1 ALU_AND; // ANDWF 00425 I_CLRF: alu_op <= #1 ALU_CLR; // CLRF 00426 I_CLRW: alu_op <= #1 ALU_CLR; // CLRW 00427 I_COMF: alu_op <= #1 ALU_NOT; // COMF 00428 I_DEC: alu_op <= #1 ALU_DEC; // DEC 00429 I_DECFSZ: alu_op <= #1 ALU_DEC; // DECFSZ 00430 I_INCF: alu_op <= #1 ALU_INC; // INCF 00431 I_INCFSZ: alu_op <= #1 ALU_INC; // INCFSZ 00432 I_IORWF: alu_op <= #1 ALU_IOR; // IORWF 00433 I_MOV: alu_op <= #1 ALU_MOV; // MOV 00434 I_MOVWF: alu_op <= #1 ALU_MOVW; // MOVWF 00435 I_RLF: alu_op <= #1 ALU_RLF; // RLF 00436 I_RRF: alu_op <= #1 ALU_RRF; // RRF 00437 I_SUBWF: alu_op <= #1 ALU_SUB; // SUBWF 00438 I_SWAPF: alu_op <= #1 ALU_SWP; // SWAPF 00439 I_XORWF: alu_op <= #1 ALU_XOR; // XORWF 00440 // Bit Oriented RF Operations 00441 I_BCF: alu_op <= #1 ALU_BCF; // BCF 00442 I_BSF: alu_op <= #1 ALU_BSF; // BSF 00443 // Literal & Controll Operations 00444 I_ANDLW: alu_op <= #1 ALU_AND; // ANDLW 00445 I_IORLW: alu_op <= #1 ALU_IOR; // IORLW 00446 I_MOVLW: alu_op <= #1 ALU_MOV; // MOWLW 00447 I_RETLW: alu_op <= #1 ALU_MOV; // RETLW 00448 I_XORLW: alu_op <= #1 ALU_XOR; // XORLW 00449 endcase 00450 00451 00452 // Source Select 00453 // This CPU source 1 can be one of: rf (or sfr) or k, 00454 // second source (if any) is always w 00455 always @(instr_0) 00456 casex(instr_0) // synopsys full_case parallel_case 00457 I_ANDLW: src1_sel_ = K_SEL; 00458 I_CALL: src1_sel_ = K_SEL; 00459 I_GOTO: src1_sel_ = K_SEL; 00460 I_IORLW: src1_sel_ = K_SEL; 00461 I_MOVLW: src1_sel_ = K_SEL; 00462 I_RETLW: src1_sel_ = K_SEL; 00463 I_XORLW: src1_sel_ = K_SEL; 00464 default: src1_sel_ = ( (instr_0[4:3]==2'h0) & (instr_0[2:0] != 3'h0 )) ? SFR_SEL : RF_SEL; 00465 endcase 00466 00467 always @(posedge clk) 00468 src1_sel <= #1 src1_sel_[0]; 00469 00470 // Destination Select 00471 // Destination can be one of: rf, w, option, tris OR one of sfr registers: 00472 // indf, tmr0, pc, status, fsr, porta, portb, portc, option, trisa, trisb, trisc 00473 // Stage 1 00474 // select w, pc, rf or sfr 00475 reg w_we1, w_we1_; 00476 00477 always @(instr_0) 00478 begin 00479 casex(instr_0) // synopsys full_case parallel_case 00480 I_ADDWF, I_ANDWF, I_COMF, I_DEC, 00481 I_DECFSZ, I_INCF, I_INCFSZ, I_IORWF, 00482 I_MOV, I_RLF, I_RRF, I_SUBWF, 00483 I_SWAPF, I_XORWF: // w or f 00484 w_we1_ = 1; 00485 default: w_we1_ = 0; 00486 endcase 00487 end 00488 00489 always @(instr_0) 00490 begin 00491 w_we_ = 0; 00492 rf_we_ = 0; 00493 sfr_we_ = 0; 00494 tris_we_= 0; 00495 casex(instr_0) // synopsys full_case parallel_case 00496 00497 I_ADDWF, I_ANDWF, I_COMF, I_DEC, 00498 I_DECFSZ, I_INCF, I_INCFSZ, I_IORWF, 00499 I_MOV, I_RLF, I_RRF, I_SUBWF, 00500 I_SWAPF, I_XORWF: // w or f 00501 begin 00502 rf_we_ = instr_0[5] & (instr_0[4] | instr_0[3]); 00503 sfr_we_ = instr_0[5] & ~instr_0[4] & ~instr_0[3]; 00504 end 00505 00506 I_MOVWF, I_CLRF, I_BCF, I_BSF: // only f 00507 begin 00508 rf_we_ = instr_0[4] | instr_0[3]; 00509 sfr_we_ = ~instr_0[4] & ~instr_0[3]; 00510 end 00511 00512 I_CLRW, I_IORLW, I_MOVLW, 00513 I_ANDLW, I_RETLW, I_XORLW: w_we_ = 1; // only w 00514 I_TRIS: tris_we_ = 1; // trisa or trisb or trisc 00515 00516 endcase 00517 end 00518 00519 assign indf_we_ = sfr_we_ & (instr_0[2:0] == INDF_ADDR); 00520 assign pc_we_ = sfr_we_ & (instr_0[2:0] == PCL_ADDR); 00521 00522 // Stage 2 destination encoder 00523 // write enable outputs are registered now 00524 always @(posedge clk) w_we <= #1 w_we_; // working register write 0 enable 00525 00526 always @(posedge clk) w_we1 <= #1 w_we1_; // working register write 1 enable 00527 00528 00529 // Register File Write Enable is composed of thee conditions: 1) direct register writing (0x10-0x1f); 00530 // 2) Direct Global Register writing (0x08-0x0f), and 3) Indirect Register File Writing 00531 // The logic has been partitioned and balanced between the decode and execute stage ... 00532 assign rf_we = rf_we1 | (rf_we2 & rf_we3); // register file write enable Composite 00533 00534 always @(posedge clk) 00535 rf_we1 <= #1 valid & rf_we_; // register file write enable 1 00536 00537 always @(posedge clk) 00538 rf_we2 <= #1 valid & (fsr_next[4] | fsr_next[3]);// register file write enable 2 00539 00540 always @(posedge clk) 00541 rf_we3 <= #1 indf_we_; // register file write enable 3 00542 00543 always @(posedge clk) 00544 wdt_clr <= #1 instr_0[11:0] == I_CLRWDT; 00545 00546 00547 always @(posedge clk) 00548 opt_we <= #1 instr_0[11:0] == I_OPTION; 00549 00550 00551 always @(posedge clk) 00552 trisa_we <= #1 tris_we_ & (instr_0[2:0] == PORTA_ADDR); 00553 00554 always @(posedge clk) 00555 trisb_we <= #1 tris_we_ & (instr_0[2:0] == PORTB_ADDR); 00556 00557 always @(posedge clk) 00558 trisc_we <= #1 tris_we_ & (instr_0[2:0] == PORTC_ADDR); 00559 00560 always @(posedge clk) 00561 begin 00562 // SFR registers 00563 tmr0_we <= #1 sfr_we_ & (instr_0[2:0] == TMR0_ADDR); 00564 pc_we <= #1 valid & pc_we_; 00565 stat_we <= #1 valid & sfr_we_ & (instr_0[2:0] == STAT_ADDR); 00566 fsr_we <= #1 valid & sfr_we_ & (instr_0[2:0] == FSR_ADDR); 00567 porta_we <= #1 sfr_we_ & (instr_0[2:0] == PORTA_ADDR); 00568 portb_we <= #1 sfr_we_ & (instr_0[2:0] == PORTB_ADDR); 00569 portc_we <= #1 sfr_we_ & (instr_0[2:0] == PORTC_ADDR); 00570 end 00571 00572 00573 // Instructions that directly modify PC 00574 always @(instr_0) 00575 begin 00576 pc_skz_ = 0; 00577 pc_bset_ = 0; 00578 pc_bclr_ = 0; 00579 pc_call_ = 0; 00580 pc_goto_ = 0; 00581 pc_retlw_ = 0; 00582 casex(instr_0) // synopsys full_case parallel_case 00583 // Byte Oriented RF Operations 00584 I_DECFSZ, 00585 I_INCFSZ: pc_skz_ = 1; 00586 // Bit Oriented RF Operations 00587 I_BTFSS: pc_bset_ = 1; 00588 I_BTFSC: pc_bclr_ = 1; 00589 // Literal & Controll Operations 00590 I_CALL: pc_call_ = 1; 00591 I_GOTO: pc_goto_ = 1; 00592 I_RETLW: pc_retlw_ = 1; 00593 endcase 00594 end 00595 00596 always @(posedge clk) 00597 begin 00598 pc_skz <= #1 valid & pc_skz_; 00599 pc_bset <= #1 valid & pc_bset_; 00600 pc_bclr <= #1 valid & pc_bclr_; 00601 pc_call <= #1 valid & pc_call_; 00602 pc_goto <= #1 valid & pc_goto_; 00603 pc_retlw <= #1 valid & pc_retlw_; 00604 end 00605 00606 assign invalidate_0_ = (pc_call_ | pc_goto_ | pc_retlw_ | pc_we_); 00607 00608 always @(posedge clk) 00609 invalidate_0 <= #1 invalidate_0_; 00610 00611 // Status bits WE 00612 always @(posedge clk) 00613 begin 00614 stat_bwe <= #1 0; 00615 if(valid) 00616 casex(instr_0) // synopsys full_case parallel_case 00617 // Byte Oriented RF Operations 00618 I_ADDWF: stat_bwe <= #1 STAT_WR_C | STAT_WR_DC | STAT_WR_Z; 00619 I_ANDWF: stat_bwe <= #1 STAT_WR_Z; 00620 I_CLRF: stat_bwe <= #1 STAT_WR_Z; 00621 I_CLRW: stat_bwe <= #1 STAT_WR_Z; 00622 I_COMF: stat_bwe <= #1 STAT_WR_Z; 00623 I_DEC: stat_bwe <= #1 STAT_WR_Z; 00624 I_INCF: stat_bwe <= #1 STAT_WR_Z; 00625 I_IORWF: stat_bwe <= #1 STAT_WR_Z; 00626 I_MOV: stat_bwe <= #1 STAT_WR_Z; 00627 I_RLF: stat_bwe <= #1 STAT_WR_C; 00628 I_RRF: stat_bwe <= #1 STAT_WR_C; 00629 I_SUBWF: stat_bwe <= #1 STAT_WR_C | STAT_WR_DC | STAT_WR_Z; 00630 I_XORWF: stat_bwe <= #1 STAT_WR_Z; 00631 // Literal & Controll Operations 00632 I_ANDLW: stat_bwe <= #1 STAT_WR_Z; 00633 //I_CLRWDT: // Modifies TO & PD *** FIX ME *** 00634 I_IORLW: stat_bwe <= #1 STAT_WR_Z; 00635 //I_SLEEP: // Modifies TO & PD *** FIX ME *** 00636 I_XORLW: stat_bwe <= #1 STAT_WR_Z; 00637 endcase 00638 end 00639 00640 //////////////////////////////////////////////////////////////////////// 00641 // Wr & Execute Logic (including PC) 00642 // Second Pipeline Stage 00643 //////////////////////////////////////////////////////////////////////// 00644 00645 // Source OP Sel 00646 //assign src1 = src1_sel ? rf_rd_data : sfr_rd_data; 00647 mux2_8 u3( .sel(src1_sel), .in0(sfr_rd_data), .in1(rf_rd_data), .out(src1) ); 00648 00649 alu u4( .s1( src1 ), 00650 .s2( w ), 00651 .mask( mask ), 00652 .out( dout ), 00653 .op( alu_op ), 00654 .c_in( status[0] ), 00655 .c( c_out ), 00656 .dc( dc_out ), 00657 .z( z_out ) 00658 ); 00659 00660 // Register file connections 00661 assign rf_wr_bnk = fsr[6:5]; 00662 assign rf_wr_addr = (instr_1[4:0]==0) ? fsr[4:0] : instr_1[4:0]; 00663 assign rf_wr_data = dout; 00664 00665 wire [7:0] status_next2; 00666 00667 // Deal with all special registers (SFR) writes 00668 /* 00669 always @(rst or status or stat_we or stat_bwe or dout or c_out or dc_out or z_out) 00670 if(rst) status_next = STAT_RST_VALUE; 00671 else 00672 begin 00673 status_next = status; // Default Keep Value 00674 if(stat_we) status_next = dout | 8'h18; 00675 else 00676 begin 00677 if(stat_bwe[0]) status_next[0] = c_out; 00678 if(stat_bwe[1]) status_next[1] = dc_out; 00679 if(stat_bwe[2]) status_next[2] = z_out; 00680 end 00681 end 00682 * 00683 00684 assign status_next2[0] = stat_bwe[0] ? c_out : status[0]; 00685 assign status_next2[1] = stat_bwe[1] ? dc_out : status[1]; 00686 assign status_next2[2] = stat_bwe[2] ? z_out : status[2]; 00687 00688 mux2_8 u21( .sel(stat_we), .in1( {dout | 8'h18} ), .in0( {status[7:3],status_next2[2:0]} ), .out(status_next) ); 00689 00690 always @(posedge clk) 00691 if(rst) status <= #1 STAT_RST_VALUE; 00692 else status <= #1 status_next; 00693 00694 //assign fsr_next = fsr_we ? dout[6:0] : fsr; 00695 00696 mux2_7 u31( .sel(fsr_we), .in1(dout[6:0]), .in0(fsr), .out(fsr_next) ); 00697 00698 always @(posedge clk) 00699 if(rst) fsr <= #1 FSR_RST_VALUE; 00700 else fsr <= #1 fsr_next; 00701 00702 always @(posedge clk) 00703 if(valid_1 & (w_we | (w_we1 & ~instr_1[5])) ) w <= #1 dout; 00704 00705 always @(posedge clk) 00706 if(rst) trisa <= #1 TRIS_RST_VALUE; 00707 else 00708 if(trisa_we & valid_1) trisa <= #1 w; 00709 00710 always @(posedge clk) 00711 if(rst) trisb <= #1 TRIS_RST_VALUE; 00712 else 00713 if(trisb_we & valid_1) trisb <= #1 w; 00714 00715 always @(posedge clk) 00716 if(rst) trisc <= #1 TRIS_RST_VALUE; 00717 else 00718 if(trisc_we & valid_1) trisc <= #1 w; 00719 00720 always @(posedge clk) 00721 if(rst) option <= #1 OPT_RST_VALUE; 00722 else 00723 if(opt_we & valid_1) option <= #1 w[5:0]; 00724 00725 always @(posedge clk) 00726 if(porta_we & valid_1) portaout <= #1 dout; 00727 00728 always @(posedge clk) 00729 if(portb_we & valid_1) portbout <= #1 dout; 00730 00731 always @(posedge clk) 00732 if(portc_we & valid_1) portcout <= #1 dout; 00733 00734 always @(posedge clk) 00735 begin 00736 porta_r <= #1 portain; 00737 portb_r <= #1 portbin; 00738 portc_r <= #1 portcin; 00739 end 00740 00741 /////////////////////////////////////////////////////////////////////// 00742 // Timer Logic 00743 00744 //assign tmr0_next = tmr0_we ? dout : tmr0_cnt_en ? tmr0_plus_1 : tmr0; 00745 //assign tmr0_next = tmr0_we ? dout : tmr0_cnt_en ? (tmr0 + 1) : tmr0; 00746 00747 00748 mux2_8 u5( .sel(tmr0_we & valid_1), 00749 .in0(tmr0_next1), .in1(dout), 00750 .out(tmr0_next) ); 00751 mux2_8 u6( .sel(tmr0_cnt_en), 00752 .in0(tmr0), .in1(tmr0_plus_1), 00753 .out(tmr0_next1) ); 00754 00755 inc8 u7( .in(tmr0), .out(tmr0_plus_1) ); 00756 00757 always @(posedge clk) 00758 tmr0 <= #1 tmr0_next; 00759 00760 presclr_wdt u8( .clk( clk ), 00761 .rst( rst ), 00762 .tcki( tcki ), 00763 .option( option[5:0] ), 00764 .tmr0_we( tmr0_we & valid_1 ), 00765 .tmr0_cnt_en( tmr0_cnt_en ), 00766 .wdt_en( wdt_en ), 00767 .wdt_clr( wdt_clr & valid_1 ), 00768 .wdt_to( wdt_to ) 00769 ); 00770 00771 00772 //////////////////////////////////////////////////////////////////////// 00773 // Programm Counter Logic 00774 00775 always @(posedge clk) 00776 pc_r2 <= #1 pc_r; 00777 00778 // 'inst_addr' is a duplication of the 'pc'. The only time when it is really needed 00779 // is when the program memory is not on the chip and we want to place the registers 00780 // directly in the IO pads to reduce Tcq (For example in a Xilinx FPGA implementation). 00781 // If the program memory is on the chip or if the implmentation allows feedback from 00782 // registers in the IO cells, this is not needed. Synopsys FPGA compiler appears to 00783 // make the correct decission either way, and gett rid of unneded logic ... 00784 00785 always @(posedge clk) 00786 if(rst) inst_addr <= #1 PC_RST_VECTOR; 00787 else inst_addr <= #1 pc_next; 00788 00789 always @(posedge clk) 00790 if(rst) pc <= #1 PC_RST_VECTOR; 00791 else pc <= #1 pc_next; 00792 00793 /* 00794 always @(pc_plus_1 or dout or pc_we or status or stack_out or 00795 pc_call or pc_goto or pc_retlw or instr_1) 00796 if(pc_we) pc_next = {status[6:5], 1'b0, dout}; 00797 else 00798 if(!pc_call & !pc_goto & !pc_retlw) pc_next = pc_plus_1; 00799 else 00800 if(pc_call) pc_next = {status[6:5], 1'b0, instr_1[7:0]}; 00801 else 00802 if(pc_goto) pc_next = {status[6:5], instr_1[8:0]}; 00803 else 00804 if(pc_retlw) pc_next = stack_out; 00805 * 00806 00807 00808 wire [10:0] pc_tmp1, pc_tmp2, pc_tmp3; 00809 wire pc_sel1; 00810 00811 assign pc_tmp1 = {status[6:5], 1'b0, dout[7:0]}; 00812 assign pc_tmp2 = {status[6:5], 1'b0, instr_1[7:0]}; 00813 assign pc_tmp3 = {status[6:5], instr_1[8:0]}; 00814 assign pc_sel1 = (!pc_call & !pc_goto & !pc_retlw); 00815 00816 mux2_11 u9 ( .sel(pc_we), .in0(pc_next1), .in1(pc_tmp1), .out(pc_next) ); 00817 mux2_11 u10( .sel(pc_sel1), .in0(pc_next2), .in1(pc_plus_1), .out(pc_next1) ); 00818 mux2_11 u11( .sel(pc_call), .in0(pc_next3), .in1(pc_tmp2), .out(pc_next2) ); 00819 mux2_11 u12( .sel(pc_goto), .in0(stack_out), .in1(pc_tmp3), .out(pc_next3) ); 00820 00821 00822 inc11 u13( .in(pc), .out(pc_plus_1) ); 00823 00824 reg invalidate_1_r1, invalidate_1_r2; 00825 00826 assign invalidate_1 = (pc_skz & z_out) | (pc_bset & bit_sel) | 00827 (pc_bclr & !bit_sel) | (invalidate_0 & valid_1) | invalidate_1_r1; 00828 00829 00830 always @(posedge clk) 00831 begin 00832 invalidate_1_r1 <= #1 (invalidate_0 & valid_1) | invalidate_1_r2; 00833 invalidate_1_r2 <= #1 (invalidate_0 & valid_1); 00834 end 00835 00836 //assign bit_sel = src1[ instr_1[7:5] ]; 00837 mux8_1 u22( .sel(instr_1[7:5]), .in(src1), .out(bit_sel) ); 00838 00839 sfifo4x11 u14( .clk(clk), .push(pc_call), .din(pc_r2), .pop(pc_retlw), .dout(stack_out) ); 00840 00841 endmodule