📄 piccore.v
字号:
end else if (INST_MOVLW == 1'b1 || INST_ADDLW == 1'b1 || INST_SUBLW == 1'b1 || INST_ANDLW == 1'b1 || INST_IORLW == 1'b1 || INST_XORLW == 1'b1 || INST_RETLW == 1'b1) begin aluinp1_reg <= inst_reg[7:0]; // Immidiate value ("k") end else if (INST_CLRF == 1'b1 || INST_CLRW == 1'b1) begin aluinp1_reg <= {8{1'b0}}; // 0 end else begin aluinp1_reg <= w_reg; // W register end // 2-3-1-2. Set aluinp2 register (source #2) case (inst_reg[9:7]) // construct bit-mask for logical operations/bit test 3'b000: begin mask_node = 8'b00000001; end 3'b001: begin mask_node = 8'b00000010; end 3'b010: begin mask_node = 8'b00000100; end 3'b011: begin mask_node = 8'b00001000; end 3'b100: begin mask_node = 8'b00010000; end 3'b101: begin mask_node = 8'b00100000; end 3'b110: begin mask_node = 8'b01000000; end default: begin mask_node = 8'b10000000; end endcase if (INST_DECF == 1'b1 || INST_DECFSZ == 1'b1) begin aluinp2_reg <= {(8 - 0 + 1){1'b1}}; // -1 (for decrement) end else if (INST_INCF == 1'b1 || INST_INCFSZ == 1'b1) begin//> modified ver1.00c, 2002/08/07// aluinp2_reg <= 8'b00000001; // 1 (for increment) aluinp2_reg <= 9'b000000001; // 1 (for increment) end else if (INST_SUBLW == 1'b1 || INST_SUBWF == 1'b1) begin// aluinp2_reg <= (~w_reg) + 8'b00000001; // -1 * W register (for subtract) aluinp2_reg <= ({1'b1, ( ~w_reg)}) + 9'b000000001; // -1 * W register (for subtract) end else if (INST_BCF == 1'b1) begin// aluinp2_reg <= ~mask_node; // mask for BCF: value of only one position is '0' aluinp2_reg <= {1'b0, ( ~mask_node)}; // mask for BCF: value of only one position is '0' end else if (INST_BTFSC == 1'b1 || INST_BTFSS == 1'b1 || INST_BSF == 1'b1) begin // operation of BCF: AND with inverted mask ("1..101..1")// aluinp2_reg <= mask_node; // operation of BSF: OR with mask_node ("0..010..0") aluinp2_reg <= {1'b0, mask_node}; // operation of BSF: OR with mask_node ("0..010..0") end else begin // operation of FSC and FSS: AND with mask_node and then compare with zero// aluinp2_reg <= w_reg; // W register aluinp2_reg <= {1'b0, w_reg}; // W register end//< // 2-3-1-3. Set stack pointer register (pop stack) if (INST_RET == 1'b1 || INST_RETLW == 1'b1 || INST_RETFIE == 1'b1) begin if (stack_pnt_reg == 0) begin stack_pnt_reg <= 8 - 1; // if pointer=0, then next value should be 8-1 end else begin stack_pnt_reg <= stack_pnt_reg - 1; // otherwise, current value - 1 end end end // 2-3-1-4. Set ramadr register (set RAM write address)//> deleted ver1.00c, 2002/08/07// ramadr_reg <= ramadr_node; // RAM write address//< // 2-3-2. Change clkout output clkout_reg <= 1'b1; // 2-3-3. Check increment-TMR0 request if (inctmr_sync_reg == 2'b01) begin inctmrhold_reg <= 1'b1; end // 2-3-4. Goto next cycle if (reset_cond == 1'b1) begin state_reg <= Qreset; end else begin state_reg <= Q3; end end // 2-4. Q3 cycle Q3: begin // 2-4-1. Calculation and store result into alu-output regsiter if (exec_op_reg == 1'b1 && intstart_reg == 1'b0) begin // if NOT STALLED // 2-4-1-1. Set aluout register if (INST_RLF == 1'b1) begin aluout_reg <= {aluinp1_reg[6:0], status_reg[0]}; // rotate left end else if (INST_RRF == 1'b1) begin aluout_reg <= {status_reg[0], aluinp1_reg[7:1]}; // rotate right end else if (INST_SWAPF == 1'b1) begin aluout_reg <= {aluinp1_reg[3:0], aluinp1_reg[7:4]}; // swap H-nibble and L-nibble end else if (INST_COMF == 1'b1) begin aluout_reg <= ~aluinp1_reg; // logical inversion end else if (INST_ANDLW == 1'b1 || INST_ANDWF == 1'b1 || INST_BCF == 1'b1 || INST_BTFSC == 1'b1 || INST_BTFSS == 1'b1) begin//> modified ver1.00c, 2002/08/07// aluout_reg <= aluinp1_reg & aluinp2_reg; // logical AND/bit clear/bit test aluout_reg <= aluinp1_reg & aluinp2_reg[7:0]; // logical AND/bit clear/bit test end else if (INST_BSF == 1'b1 || INST_IORLW == 1'b1 || INST_IORWF == 1'b1) begin// aluout_reg <= aluinp1_reg | aluinp2_reg; // logical OR/bit set aluout_reg <= aluinp1_reg | aluinp2_reg[7:0]; // logical OR/bit set end else if (INST_XORLW == 1'b1 || INST_XORWF == 1'b1) begin// aluout_reg <= aluinp1_reg ^ aluinp2_reg; // logical XOR aluout_reg <= aluinp1_reg ^ aluinp2_reg[7:0]; // logical XOR//< end else if (INST_ADDLW == 1'b1 || INST_ADDWF == 1'b1 || INST_SUBLW == 1'b1 || INST_SUBWF == 1'b1 || INST_DECF == 1'b1 || INST_DECFSZ == 1'b1 || INST_INCF == 1'b1 || INST_INCFSZ == 1'b1) begin //< aluout_reg <= add_node[7:0]; // addition/subtraction/increment/decrement end else begin aluout_reg <= aluinp1_reg; // pass through end // 2-4-1-2. Set C flag and DC flag//> modified ver1.00c, 2002/08/07// if (INST_ADDLW == 1'b1 || INST_ADDWF == 1'b1 || INST_SUBLW == 1'b1 || INST_SUBWF == 1'b1) begin// status_reg(1) <= addLow_node(4); // DC flag// status_reg(0) <= add_node(8); // C flag if (INST_ADDLW == 1'b1 || INST_ADDWF == 1'b1) begin status_reg[1] <= addLow_node[4]; // DC flag status_reg[0] <= add_node[8]; // C flag end else if (INST_SUBLW == 1'b1 || INST_SUBWF == 1'b1) begin status_reg[1] <= ~addLow_node[4]; // DC flag status_reg[0] <= ~add_node[8]; // C flag//< end else if (INST_RLF == 1'b1) begin status_reg[0] <= aluinp1_reg[7]; // C flag end else if (INST_RRF == 1'b1) begin status_reg[0] <= aluinp1_reg[0]; // C flag end // 2-4-1-3. Set data-SRAM write enable (hazard-free) if (writeram_node == 1'b1 && ADDR_SRAM == 1'b1) begin writeram_reg <= 1'b1; end else begin writeram_reg <= 1'b0; end end else begin // (if stalled) writeram_reg <= 1'b0; end // 2-4-2. Check external interrupt and set interrupt flag / Increment TMR0 if (intstart_reg == 1'b0) begin if (intcon_reg[7] == 1'b1) begin // GIE // PORT-B0 INT if (inte_sync_reg == 1'b1) begin intcon_reg[1] <= 1'b1; // set INTF intclr_reg[0] <= 1'b1; // clear external int-registers (intrise_reg(0) and intdown_reg(0)) end // PORT-B[4-7] INT if (rbint_sync_reg == 1'b1) begin intcon_reg[0] <= 1'b1; // set RBIF intclr_reg[4:1] <= 4'b1111; // clear external int-registers (intrise_reg(4-1) and intdown_reg(4-1)) end end end // Increment TMR0 if (inctmrhold_reg == 1'b1 || inctmr_sync_reg == 2'b01) begin // increment trigger comes tmr0_reg <= tmr0_reg + 8'b00000001; // increment inctmrhold_reg <= 1'b0; // if intstart = '0' and GIE = '1' and T0IE = '1' and timer full, then set T0IF if (intstart_reg == 1'b0 && intcon_reg[7] == 1'b1 && intcon_reg[5] == 1'b1 && tmr0_reg == 8'b11111111) begin intcon_reg[2] <= 1'b1; // set T0IF end end // 2-4-3. Goto next cycle if (reset_cond == 1'b1) begin state_reg <= Qreset; end else begin state_reg <= Q4; end end // 2-5. Q4 cycle Q4: begin // 2-5-1. Fetch next program-instruction inst_reg <= progdata; if (exec_op_reg == 1'b0 && intstart_reg == 1'b0) begin // if STALLED pc_reg <= incpc_node; // increment PC exec_op_reg <= 1'b1; // end of stall end else begin // if NOT stalled (note: if intstart_reg = '1', only stack/pc-operations in this else-clause will be performed) // 2-5-2. Store calculation result into distination, set PC and flags, and determine if execute next cycle or not // 2-5-2-1. Set W register, if not in stall cycle (intstart_reg = '0') and distination is W if (writew_node == 1'b1) begin // ('0' if intstart_reg = '1') w_reg <= aluout_reg; // write W reg end // 2-5-2-2. Set data RAM/special registers, if not in stall cycle (intstart_reg = '0') if (writeram_node == 1'b1) begin // ('0' if intstart_reg = '1') if (ADDR_STAT == 1'b1) begin status_reg[7:5] <= aluout_reg[7:5]; // write IRP,RP1,RP0 // status(4),status(3)...unwritable, see below (/PD,/T0 part) status_reg[1:0] <= aluout_reg[1:0]; // write DC,C end if (ADDR_FSR == 1'b1) begin fsr_reg <= aluout_reg; // write FSR end if (ADDR_PORTA == 1'b1) begin portaout_reg <= aluout_reg[4:0]; // write PORT-A end if (ADDR_PORTB == 1'b1) begin portbout_reg <= aluout_reg; // write PORT-B end if (ADDR_EEDATA == 1'b1) begin eedata_reg <= aluout_reg; // write EEDATA end if (ADDR_EEADR == 1'b1) begin eeadr_reg <= aluout_reg; // write EEADR end if (ADDR_PCLATH == 1'b1) begin pclath_reg <= aluout_reg[4:0]; // write PCLATH end if (ADDR_INTCON == 1'b1) begin intcon_reg[6:0] <= aluout_reg[6:0]; // write INTCON (except GIE) end // intcon(7)...see below (GIE part) if (ADDR_OPTION == 1'b1) begin option_reg <= aluout_reg; // write OPTION end if (ADDR_TRISA == 1'b1) begin trisa_reg <= aluout_reg[4:0]; // write TRISA end if (ADDR_TRISB == 1'b1) begin trisb_reg <= aluout_reg; // write TRISB end if (ADDR_TMR0 == 1'b1) begin tmr0_reg <= aluout_reg; // write TMR0 end if (ADDR_EECON1 == 1'b1) begin // write EECON1 eecon1_reg[4:3] <= aluout_reg[4:3]; eecon1_reg[2] <= aluout_reg[2] & existeeprom; // WREN can be set only when EEPROM exists if (aluout_reg[2:0] == 3'b110) begin // if write enabled, write bit = '1', and no current read eecon1_reg[1] <= 1'b1; // WR: only SET-operation is allowed to user end if (aluout_reg[1:0] == 2'b01) begin // if no current write, and read bit = '1' eecon1_reg[0] <= 1'b1; // RD: only SET-operation is allowed to user end end end // 2-5-2-3. Set/clear Z flag, if not in stall cycle (intstart_reg = '0') if (intstart_reg == 1'b0) begin//---> changed v1.00d, 2004/08/26 // if (ADDR_STAT == 1'b1) begin if (writeram_node == 1'b1 && ADDR_STAT == 1'b1 && INST_CLRF == 1'b0) begin//---< changed v1.00d, 2004/08/26 status_reg[2] <= aluout_reg[2]; // (distination is Z flag) end else if (INST_ADDLW == 1'b1 || INST_ADDWF == 1'b1 || INST_ANDLW == 1'b1 || INST_ANDWF == 1'b1 || INST_CLRF == 1'b1 || INST_CLRW == 1'b1 || INST_COMF == 1'b1 || INST_DECF == 1'b1 || INST_INCF == 1'b1 || INST_MOVF == 1'b1 || INST_SUBLW == 1'b1 || INST_SUBWF == 1'b1 || INST_XORLW == 1'b1 || INST_XORWF == 1'b1) begin status_reg[2] <= aluout_zero_node; // Z=1 if result == 0 end else if (INST_IORLW == 1'b1 || INST_IORWF == 1'b1) begin// SELECT ONE OF THE FOLLOWING TWO SENTENCES // IORLW or IORWF instructions: status_reg[2] <= ~aluout_zero_node; // Z=1 if result != 0 (same behavior with PIC16F84 data sheet pp.61-62)// status_reg(2) <= aluout_zero_node; // Z=1 if resutl == 0 (same behavior with the other instructions) end end // 2-5-2-4. Set PC register and determine if execute next cycle or not if (intstart_reg == 1'b1) begin // After interrupt-stall cycle ends, jump to interrupt vector pc_reg <= 13'b0000000000100; // (interrupt vector) exec_op_reg <= 1'b0; // the next cycle is stall cycle end else if (INST_RET == 1'b1 || INST_RETLW == 1'b1 || INST_RETFIE == 1'b1) begin // "return" instructions pc_reg <= stacktop_node; // pc <= top of poped stack (the stack is poped at Q2 cycle) exec_op_reg <= 1'b0; // the next cycle is stall cycle end else if (INST_GOTO == 1'b1 || INST_CALL == 1'b1) begin // "goto/call" instructions pc_reg <= {pclath_reg[4:3], inst_reg[10:0]}; // (see pp.18 of PIC16F84 data sheet) exec_op_reg <= 1'b0; end else if (((INST_BTFSC == 1'b1 || INST_DECFSZ == 1'b1 || INST_INCFSZ == 1'b1) && aluout_zero_node == 1'b1) || (INST_BTFSS == 1'b1 && aluout_zero_node == 1'b0)) begin // bit_test instrcutions pc_reg <= incpc_node; exec_op_reg <= 1'b0; // the next cycle is stall cycle, if test conditions are met. end else if (writeram_node == 1'b1 && ADDR_PCL == 1'b1) begin // PCL is data-distination pc_reg <= {pclath_reg[4:0], aluout_reg}; // (see pp.18 of PIC16F84 data sheet) exec_op_reg <= 1'b0; end else begin // this check MUST be located AFTER the above if/elsif sentences if (int_node == 1'b0) begin // check if interrupt trigger comes pc_reg <= incpc_node; // if not, the next instruction fetch/execution will be performed normally end else begin pc_reg <= pc_reg; // if so, value of PC must be hold (will be pushed into stack at the end of next instruction cycle) end exec_op_reg <= 1'b1; end // 2-5-2-5. Push current PC value into stack, if necessary if (INST_CALL == 1'b1 || intstart_reg == 1'b1) begin // CALL instruction or End of interrupt-stall cycle // write PC-value into stack top if (stack_pos_node[0] == 1'b1) begin // check if the stack cell is stack top or not stack_reg[0] <= pc_reg; // if so, write PC value end if (stack_pos_node[1] == 1'b1) begin stack_reg[1] <= pc_reg; end if (stack_pos_node[2] == 1'b1) begin stack_reg[2] <= pc_reg; end if (stack_pos_node[3] == 1'b1) begin stack_reg[3] <= pc_reg; end if (stack_pos_node[4] == 1'b1) begin stack_reg[4] <= pc_reg; end if (stack_pos_node[5] == 1'b1) begin stack_reg[5] <= pc_reg; end if (stack_pos_node[6] == 1'b1) begin stack_reg[6] <= pc_reg; end if (stack_pos_node[7] == 1'b1) begin stack_reg[7] <= pc_reg; end // increment stack pointer// >> Changed on Dec 10,2000 stack_full_node = 8 - 1;// if (stack_pnt_reg == 8 - 1) then if (stack_pnt_reg == stack_full_node) begin// << Changed on Dec 10,2000 stack_pnt_reg <= 0; end else begin stack_pnt_reg <= stack_pnt_reg + 1; end end // 2-5-2-6. Set GIE bit in intcon register (intcon_reg(7)) if (intstart_reg == 1'b0) begin if (int_node == 1'b1) begin // interrupt trigger comes intcon_reg[7] <= 1'b0; // clear GIE intstart_reg <= 1'b1; // the next cycle is interrupt-stall cycle end else if (INST_RETFIE == 1'b1) begin // "return from interrupt" instruction intcon_reg[7] <= 1'b1; intstart_reg <= 1'b0; end else if (writeram_node == 1'b1 && ADDR_INTCON == 1'b1) begin // distination is GIE intcon_reg[7] <= aluout_reg[7]; intstart_reg <= 1'b0; end else begin intstart_reg <= 1'b0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -