📄 piccore.vhd
字号:
aluinp2_reg <= "0" & w_reg; -- W register--< end if; -- 2-3-1-3. Set stack pointer register (pop stack) if (INST_RET = '1' or INST_RETLW = '1' or INST_RETFIE = '1') then if (stack_pnt_reg = 0) then stack_pnt_reg <= STACK_SIZE - 1; -- if pointer=0, then next value should be STACK_SIZE-1 else stack_pnt_reg <= stack_pnt_reg - 1; -- otherwise, current value - 1 end if; end if; -- 2-3-1-4. Set ramadr register (set RAM write address)--> deleted ver1.00c, 2002/08/07-- ramadr_reg <= ramadr_node; -- RAM write address--< end if; -- 2-3-2. Change clkout output clkout_reg <= '1'; -- 2-3-3. Check increment-TMR0 request if (inctmr_sync_reg = "01") then inctmrhold_reg <= '1'; end if; -- 2-3-4. Goto next cycle if (reset_cond = '1') then state_reg <= Qreset; else state_reg <= Q3; end if; -- 2-4. Q3 cycle when Q3 => -- 2-4-1. Calculation and store result into alu-output regsiter if (exec_op_reg = '1' and intstart_reg = '0') then -- if NOT STALLED -- 2-4-1-1. Set aluout register if (INST_RLF = '1') then aluout_reg <= aluinp1_reg(6 downto 0) & status_reg(0); -- rotate left elsif (INST_RRF = '1') then aluout_reg <= status_reg(0) & aluinp1_reg(7 downto 1); -- rotate right elsif (INST_SWAPF = '1') then aluout_reg <= aluinp1_reg(3 downto 0) & aluinp1_reg(7 downto 4); -- swap H-nibble and L-nibble elsif (INST_COMF = '1') then aluout_reg <= not aluinp1_reg; -- logical inversion elsif (INST_ANDLW = '1' or INST_ANDWF = '1' or INST_BCF = '1' or INST_BTFSC = '1' or INST_BTFSS = '1') then--> modified ver1.00c, 2002/08/07-- aluout_reg <= aluinp1_reg and aluinp2_reg; -- logical AND/bit clear/bit test aluout_reg <= aluinp1_reg and aluinp2_reg(7 downto 0); -- logical AND/bit clear/bit test elsif (INST_BSF = '1' or INST_IORLW = '1' or INST_IORWF = '1') then-- aluout_reg <= aluinp1_reg or aluinp2_reg; -- logical OR/bit set aluout_reg <= aluinp1_reg or aluinp2_reg(7 downto 0); -- logical OR/bit set elsif (INST_XORLW = '1' or INST_XORWF = '1') then-- aluout_reg <= aluinp1_reg xor aluinp2_reg; -- logical XOR aluout_reg <= aluinp1_reg xor aluinp2_reg(7 downto 0); -- logical XOR--< elsif (INST_ADDLW = '1' or INST_ADDWF = '1' or INST_SUBLW = '1' or INST_SUBWF = '1' or INST_DECF = '1' or INST_DECFSZ = '1' or INST_INCF = '1' or INST_INCFSZ = '1') then aluout_reg <= add_node(7 downto 0); -- addition/subtraction/increment/decrement else aluout_reg <= aluinp1_reg; -- pass through end if; -- 2-4-1-2. Set C flag and DC flag--> modified ver1.00c, 2002/08/07-- if (INST_ADDLW = '1' or INST_ADDWF = '1' or INST_SUBLW = '1' or INST_SUBWF = '1') then-- status_reg(1) <= addLow_node(4); -- DC flag-- status_reg(0) <= add_node(8); -- C flag if (INST_ADDLW = '1' or INST_ADDWF = '1') then status_reg(1) <= addLow_node(4); -- DC flag status_reg(0) <= add_node(8); -- C flag elsif (INST_SUBLW = '1' or INST_SUBWF = '1') then status_reg(1) <= not addLow_node(4); -- DC flag status_reg(0) <= not add_node(8); -- C flag--< elsif (INST_RLF = '1') then status_reg(0) <= aluinp1_reg(7); -- C flag elsif (INST_RRF = '1') then status_reg(0) <= aluinp1_reg(0); -- C flag end if; -- 2-4-1-3. Set data-SRAM write enable (hazard-free) if (writeram_node = '1' and ADDR_SRAM = '1') then writeram_reg <= '1'; else writeram_reg <= '0'; end if; else -- (if stalled) writeram_reg <= '0'; end if; -- 2-4-2. Check external interrupt and set interrupt flag / Increment TMR0 if (intstart_reg = '0') then if (intcon_reg(7) = '1') then -- GIE -- PORT-B0 INT if (inte_sync_reg = '1') then intcon_reg(1) <= '1'; -- set INTF intclr_reg(0) <= '1'; -- clear external int-registers (intrise_reg(0) and intdown_reg(0)) end if; -- PORT-B[4-7] INT if (rbint_sync_reg = '1') then intcon_reg(0) <= '1'; -- set RBIF intclr_reg(4 downto 1) <= "1111"; -- clear external int-registers (intrise_reg(4-1) and intdown_reg(4-1)) end if; end if; end if; -- Increment TMR0 if (inctmrhold_reg = '1' or inctmr_sync_reg = "01") then -- increment trigger comes tmr0_reg <= tmr0_reg + "00000001"; -- increment inctmrhold_reg <= '0'; -- if intstart = '0' and GIE = '1' and T0IE = '1' and timer full, then set T0IF if (intstart_reg = '0' and intcon_reg(7) = '1' and intcon_reg(5) = '1' and tmr0_reg = "11111111") then intcon_reg(2) <= '1'; -- set T0IF end if; end if; -- 2-4-3. Goto next cycle if (reset_cond = '1') then state_reg <= Qreset; else state_reg <= Q4; end if; -- 2-5. Q4 cycle when Q4 => -- 2-5-1. Fetch next program-instruction inst_reg <= progdata; if (exec_op_reg = '0' and intstart_reg = '0') then -- if STALLED pc_reg <= incpc_node; -- increment PC exec_op_reg <= '1'; -- end of stall else -- 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') then -- ('0' if intstart_reg = '1') w_reg <= aluout_reg; -- write W reg end if; -- 2-5-2-2. Set data RAM/special registers, if not in stall cycle (intstart_reg = '0') if (writeram_node = '1') then -- ('0' if intstart_reg = '1') if (ADDR_STAT = '1') then status_reg(7 downto 5) <= aluout_reg(7 downto 5); -- write IRP,RP1,RP0 -- status(4),status(3)...unwritable, see below (/PD,/T0 part) status_reg(1 downto 0) <= aluout_reg(1 downto 0); -- write DC,C end if; if (ADDR_FSR = '1') then fsr_reg <= aluout_reg; -- write FSR end if; if (ADDR_PORTA = '1') then portaout_reg <= aluout_reg(4 downto 0); -- write PORT-A end if; if (ADDR_PORTB = '1') then portbout_reg <= aluout_reg; -- write PORT-B end if; if (ADDR_EEDATA = '1') then eedata_reg <= aluout_reg; -- write EEDATA end if; if (ADDR_EEADR = '1') then eeadr_reg <= aluout_reg; -- write EEADR end if; if (ADDR_PCLATH = '1') then pclath_reg <= aluout_reg(4 downto 0); -- write PCLATH end if; if (ADDR_INTCON = '1') then intcon_reg(6 downto 0) <= aluout_reg(6 downto 0); -- write INTCON (except GIE) -- intcon(7)...see below (GIE part) end if; if (ADDR_OPTION = '1') then option_reg <= aluout_reg; -- write OPTION end if; if (ADDR_TRISA = '1') then trisa_reg <= aluout_reg(4 downto 0); -- write TRISA end if; if (ADDR_TRISB = '1') then trisb_reg <= aluout_reg; -- write TRISB end if; if (ADDR_TMR0 = '1') then tmr0_reg <= aluout_reg; -- write TMR0 end if; if (ADDR_EECON1 = '1') then -- write EECON1 eecon1_reg(4 downto 3) <= aluout_reg(4 downto 3); eecon1_reg(2) <= aluout_reg(2) and existeeprom; -- WREN can be set only when EEPROM exists if (aluout_reg(2 downto 0) = "110") then -- if write enabled, write bit = '1', and no current read eecon1_reg(1) <= '1'; -- WR: only SET-operation is allowed to user end if; if (aluout_reg(1 downto 0) = "01") then -- if no current write, and read bit = '1' eecon1_reg(0) <= '1'; -- RD: only SET-operation is allowed to user end if; end if; end if; -- 2-5-2-3. Set/clear Z flag, if not in stall cycle (intstart_reg = '0') if (intstart_reg = '0') then-----> changed v1.00d, 2004/08/26 -- if (ADDR_STAT = '1') then if (writeram_node = '1' and ADDR_STAT = '1' and INST_CLRF = '0') then-----< changed v1.00d, 2004/08/26 status_reg(2) <= aluout_reg(2); -- (distination is Z flag) elsif (INST_ADDLW = '1' or INST_ADDWF = '1' or INST_ANDLW = '1' or INST_ANDWF = '1' or INST_CLRF = '1' or INST_CLRW = '1' or INST_COMF = '1' or INST_DECF = '1' or INST_INCF = '1' or INST_MOVF = '1' or INST_SUBLW = '1' or INST_SUBWF = '1' or INST_XORLW = '1' or INST_XORWF = '1') then status_reg(2) <= aluout_zero_node; -- Z=1 if result == 0 elsif (INST_IORLW = '1' or INST_IORWF = '1') then-- SELECT ONE OF THE FOLLOWING TWO SENTENCES -- IORLW or IORWF instructions: status_reg(2) <= not 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 if; end if; -- 2-5-2-4. Set PC register and determine if execute next cycle or not if (intstart_reg = '1') then -- After interrupt-stall cycle ends, jump to interrupt vector pc_reg <= "0000000000100"; -- (interrupt vector) exec_op_reg <= '0'; -- the next cycle is stall cycle elsif (INST_RET = '1' or INST_RETLW = '1' or INST_RETFIE = '1') then -- "return" instructions pc_reg <= stacktop_node; -- pc <= top of poped stack (the stack is poped at Q2 cycle) exec_op_reg <= '0'; -- the next cycle is stall cycle elsif (INST_GOTO = '1' or INST_CALL = '1') then -- "goto/call" instructions pc_reg <= pclath_reg(4 downto 3) & inst_reg(10 downto 0); -- (see pp.18 of PIC16F84 data sheet) exec_op_reg <= '0'; elsif ( ((INST_BTFSC = '1' or INST_DECFSZ = '1' or INST_INCFSZ = '1') and aluout_zero_node = '1') or (INST_BTFSS = '1' and aluout_zero_node = '0') ) then -- bit_test instrcutions pc_reg <= incpc_node; exec_op_reg <= '0'; -- the next cycle is stall cycle, if test conditions are met. elsif (writeram_node = '1' and ADDR_PCL = '1') then -- PCL is data-distination pc_reg <= pclath_reg(4 downto 0) & aluout_reg; -- (see pp.18 of PIC16F84 data sheet) exec_op_reg <= '0'; else -- this check MUST be located AFTER the above if/elsif sentences if (int_node = '0') then -- check if interrupt trigger comes pc_reg <= incpc_node; -- if not, the next instruction fetch/execution will be performed normally else 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 if; exec_op_reg <= '1'; end if; -- 2-5-2-5. Push current PC value into stack, if necessary if (INST_CALL = '1' or intstart_reg = '1') then -- CALL instruction or End of interrupt-stall cycle -- write PC-value into stack top for I in 0 to STACK_SIZE - 1 loop if (stack_pos_node(I) = '1') then -- check if the stack cell is stack top or not stack_reg(I) <= pc_reg; -- if so, write PC value end if; end loop; -- increment stack pointer-- >> Changed on Dec 10,2000 stack_full_node := STACK_SIZE - 1;-- if (stack_pnt_reg = STACK_SIZE - 1) then if (stack_pnt_reg = stack_full_node) then-- << Changed on Dec 10,2000 stack_pnt_reg <= 0; else stack_pnt_reg <= stack_pnt_reg + 1; end if; end if; -- 2-5-2-6. Set GIE bit in intcon register (intcon_reg(7)) if (intstart_reg = '0') then if (int_node = '1') then -- interrupt trigger comes intcon_reg(7) <= '0'; -- clear GIE intstart_reg <= '1'; -- the next cycle is interrupt-stall cycle elsif (INST_RETFIE = '1') then -- "return from interrupt" instruction intcon_reg(7) <= '1'; intstart_reg <= '0'; elsif (writeram_node = '1' and ADDR_INTCON = '1') then -- distination is GIE intcon_reg(7) <= aluout_reg(7); intstart_reg <= '0'; else intstart_reg <= '0'; end if; else intstart_reg <= '0'; end if; -- 2-5-2-7. Set/clear /PD and /TO flags if (intstart_reg = '0') then if (INST_CLRWDT = '1' or (INST_SLEEP = '1' and (wdtreset_node = '0' and intstart_reg = '0')) ) then -- CLRWDT or (SLEEP and no interrupt trigger) -- see pp.46,58 and 66 of PIC16F84 data-sheet if (INST_SLEEP = '1') then sleepflag_reg <= '1'; status_reg(4 downto 3) <= "10"; -- SLEEP: /T0,/PD = 1,0 else -- (INST_CLRWDT) status_reg(4 downto 3) <= "11"; -- CLRWDT: /T0,/PD = 1,1 end if; end if; end if; end if; -- (if not stalled) -- 2-5-3. Clear data-SRAM write enable (hazard-free)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -