📄 piccore.vhd
字号:
top := stack_cell(0); for I in 1 to STACK_SIZE - 1 loop top := top or stack_cell(I); end loop; stacktop_node <= top; end process;-- MAIN EFSM: description of register value changes in each clock cycle u2:process (clkin) -- Intermidiate nodes used for resource sharing variable ramin_node : std_logic_vector(7 downto 0); -- result of reading RAM/Special registers variable incpc_node : std_logic_vector(12 downto 0); -- value of PC + 1 variable mask_node : std_logic_vector(7 downto 0); -- bit mask for logical operations variable add_node : std_logic_vector(8 downto 0); -- result of 8bit addition (std_logic_vector) variable addLow_node : std_logic_vector(4 downto 0); -- reulst of low-4bit addition (std_logic_vector) variable aluout_zero_node : std_logic; -- H if ALUOUT = 0 variable writew_node : std_logic; -- H if destination is W register variable writeram_node : std_logic; -- H if destination is RAM/Special registers variable int_node : std_logic; -- H if interrupt request comes variable wdtreset_node : std_logic; -- H if WDT-reset request comes variable reset_cond : std_logic; -- H if any reset request comes (jump to Qreset state)-- >> added on Dec 10,2000 variable stack_full_node : integer range 0 to STACK_SIZE - 1;-- << added on Dec 10,2000--> added ver1.00c, 2002/08/07 variable extbit_node : std_logic;--< begin if (clkin'event and clkin = '1') then -- 1. Intermidiate nodes for resource sharing -- 1-1. Result of reading RAM; one of data sources (see pp.13 of PIC16F84 data sheet) if (ADDR_SRAM = '1') then ramin_node := ramdtin; -- data bus output of external SRAM elsif (ADDR_EEDATA = '1') then ramin_node := eedata_reg; -- data bus output of external EEPROM elsif (ADDR_TMR0 = '1') then ramin_node := tmr0_reg; -- TMR0 elsif (ADDR_PCL = '1') then ramin_node := pc_reg(7 downto 0); -- PCL elsif (ADDR_STAT = '1') then ramin_node := status_reg; -- STATUS elsif (ADDR_FSR = '1') then ramin_node := fsr_reg; -- FSR elsif (ADDR_PORTA = '1') then for I in 0 to 4 loop if (trisa_reg(I) = '1') then ramin_node(I) := portain_sync_reg(I); -- PORT B (when input mode) else ramin_node(I) := portaout_reg(I); -- PORT B (when output mode) end if; end loop; ramin_node(7 downto 5) := "000"; elsif (ADDR_PORTB = '1') then for I in 0 to 7 loop if (trisb_reg(I) = '1') then ramin_node(I) := portbin_sync_reg(I); -- PORT B (when input mode) else ramin_node(I) := portbout_reg(I); -- PORT B (when output mode) end if; end loop; elsif (ADDR_EEADR = '1') then ramin_node := eeadr_reg; -- EEADR elsif (ADDR_PCLATH = '1') then ramin_node := "000" & pclath_reg; -- PCLATH (5bit) elsif (ADDR_INTCON = '1') then ramin_node := intcon_reg; -- INTCON elsif (ADDR_OPTION = '1') then ramin_node := option_reg; -- OPTION elsif (ADDR_TRISA = '1') then ramin_node := "000" & trisa_reg; -- TRISA elsif (ADDR_TRISB = '1') then ramin_node := trisb_reg; -- TRISB elsif (ADDR_EECON1 = '1') then ramin_node := "000" & eecon1_reg; -- EECON1 (5bit) else ramin_node := (others => '0'); end if; -- 1-2. PC + 1 incpc_node := pc_reg + "0000000000001"; -- 1-3. Adder (ALU)--> changed ver1.00c, 2002/08/07 -- full 8bit-addtion-- add_node := ("0" & aluinp1_reg) + ("0" & aluinp2_reg); add_node := ("0" & aluinp1_reg) + aluinp2_reg; -- lower 4bit-addtion if (INST_SUBLW = '1' or INST_SUBWF = '1') then extbit_node := aluinp2_reg(4); else extbit_node := '0'; end if;-- addLow_node := ("0" & aluinp1_reg(3 downto 0)) + ("0" & aluinp2_reg(3 downto 0)); addLow_node := ("0" & aluinp1_reg(3 downto 0)) + (extbit_node & aluinp2_reg(3 downto 0));--< -- 1-4. Test if aluout = 0 if (aluout_reg = "00000000") then aluout_zero_node := '1'; else aluout_zero_node := '0'; end if; -- 1-5. Determine destination if (intstart_reg = '1') then writew_node := '0'; writeram_node := '0'; elsif (INST_MOVWF = '1' or INST_BCF = '1' or INST_BSF = '1' or INST_CLRF = '1') then writew_node := '0'; writeram_node := '1'; elsif (INST_MOVLW = '1' or INST_ADDLW = '1' or INST_SUBLW = '1' or INST_ANDLW = '1' or INST_IORLW = '1' or INST_XORLW = '1' or INST_RETLW = '1' or INST_CLRW = '1') then writew_node := '1'; writeram_node := '0'; elsif (INST_MOVF = '1' or INST_SWAPF = '1' or INST_ADDWF = '1' or INST_SUBWF = '1' or INST_ANDWF = '1' or INST_IORWF = '1' or INST_XORWF = '1' or INST_DECF = '1' or INST_INCF = '1' or INST_RLF = '1' or INST_RRF = '1' or INST_DECFSZ = '1' or INST_INCFSZ = '1' or INST_COMF = '1') then writew_node := not inst_reg(7); -- ("d" field of fetched instruction) writeram_node := inst_reg(7); -- ("d" field of fetched instruction) else writew_node := '0'; writeram_node := '0'; end if; -- 1-6. Interrupt request (see pp.17 of PIC16F84 data sheet) int_node := intcon_reg(7) -- GIE and ( (intcon_reg(3) and intcon_reg(0)) -- RBIE and RBIF or (intcon_reg(4) and intcon_reg(1)) -- INTE and INTF or (intcon_reg(5) and intcon_reg(2)) -- T0IE and T0IF or (intcon_reg(6) and eecon1_reg(4)) -- EEIE and EEIF(EECON1) ); -- 1-7. Reset conditions wdtreset_node := wdt_full_sync_reg(1) and (not wdt_full_sync_reg(2)); -- WDT if (poweron_sync_reg = '0' or mclr_sync_reg = '0' or wdtreset_node = '1') then -- (all of reset triggers) reset_cond := '1'; else reset_cond := '0'; end if; -- 2. EFSM body case state_reg is -- 2-1. Reset state (see pp.14 and pp.42 of PIC16F84 data sheet) when Qreset => pc_reg <= (others => '0'); -- 0 status_reg(7 downto 5) <= "000"; pclath_reg <= (others => '0'); -- 0 intcon_reg(7 downto 1) <= "0000000"; option_reg <= (others => '1'); trisa_reg <= (others => '1'); trisb_reg <= (others => '1'); tmr0_reg <= (others => '0'); -- (specification: don't care) exec_op_reg <= '0'; intclr_reg <= (others => '1'); -- clear int intstart_reg <= '0'; writeram_reg <= '0'; sleepflag_reg <= '0'; -- (set /T0 and /PD properly; see pp.42 and pp.46 of data sheet) if (poweron_sync_reg = '0') then -- Power-on Reset status_reg(4) <= '1'; -- /T0 = 1 status_reg(3) <= '1'; -- /PD = 1 elsif (mclr_sync_reg = '0') then -- MCLR reset/MCLR wake up from sleep status_reg(4) <= '1'; -- /T0 = 1 status_reg(3) <= not sleepflag_reg; -- /PD = 1 if normal reset, /PD = 0 if wake up elsif (wdtreset_node = '1') then -- WDT reset/WDT wake up from sleep status_reg(4) <= '0'; -- /T0 = 0 status_reg(3) <= not sleepflag_reg; -- /PD = 1 if normal reset, /PD = 0 if wake up end if; eecon1_reg(4) <= '0'; -- (set WRERR bit in EECON1 properly; see pp.33 and pp.34 of data sheet) if (poweron_sync_reg = '0') then eecon1_reg(3) <= '0'; -- clear WRERR else eecon1_reg(3) <= eecon1_reg(1); -- substitute WR into WRERR end if; eecon1_reg(2 downto 0) <= "000"; if (poweron_sync_reg = '0') then -- NOTICE: do NOT clear stack pointer for MCLR reset or WDT reset (the value must be hold) stack_pnt_reg <= 0; end if; if (reset_cond = '0') then -- go to Q1 if reset signal is disasserted. state_reg <= Q1; end if; -- 2-2. Q1 cycle when Q1 => -- 2-2-1. Clear external interrupt registers if GIE=0 if (intcon_reg(7) = '1') then intclr_reg <= (others => '0'); else -- GIE = 0 intclr_reg <= (others => '1'); -- clear interrupt end if; -- 2-2-2. Read I/O port portain_sync_reg <= porta_in; portbin_sync_reg <= portb_in; -- 2-2-3. Read/Write EEPROM, if necessary if (intstart_reg = '0') then if (eecon1_reg(0) = '1' and rdeep_sync_reg = '1') then -- reading EEPROM complete eedata_reg <= eepdtin; eecon1_reg(0) <= '0'; -- clear EECON1_RD end if; if (eecon1_reg(1) = '1' and wreep_sync_reg = '1') then -- writing EEPROM complete if (intcon_reg(7) = '1' and intcon_reg(6) = '1') then eecon1_reg(4) <= '1'; -- INT (EE write complete) end if; eecon1_reg(1) <= '0'; -- clear EECON1_WR end if;--> deleted ver1.00c, 2002/08/07-- if (exec_op_reg = '1') then-- ramadr_reg <= ramadr_node; -- RAM read address-- end if;--< end if; -- 2-2-4. Check increment-TMR0 request if (inctmr_sync_reg = "01") then inctmrhold_reg <= '1'; end if; -- 2-2-5. Goto next cycle if (reset_cond = '1') then state_reg <= Qreset; else -- if in the sleep mode, wait until wake-up triggers comes if (sleepflag_reg = '1' and intstart_reg = '0') then if (inte_sync_reg = '1' or rbint_sync_reg = '1') then -- if PORT-B interrupts come, then resume execution -- otherwise, if WDT reset/MCLR reset come, then goto Qreset sleepflag_reg <= '0'; state_reg <= Q2; end if; else state_reg <= Q2; end if; end if; -- 2-3. Q2 cycle when Q2 => -- 2-3-1. Read data-RAM and substitute source values to alu-input registers if (exec_op_reg = '1' and intstart_reg = '0') then -- if NOT STALLED -- 2-3-1-1. Set aluinp1 register (source #1) if (INST_MOVF = '1' or INST_SWAPF = '1' or INST_ADDWF = '1' or INST_SUBWF = '1' or INST_ANDWF = '1' or INST_IORWF = '1' or INST_XORWF = '1' or INST_DECF = '1' or INST_INCF = '1' or INST_RLF = '1' or INST_RRF = '1' or INST_BCF = '1' or INST_BSF = '1' or INST_BTFSC = '1' or INST_BTFSS = '1' or INST_DECFSZ = '1' or INST_INCFSZ = '1' or INST_COMF = '1') then aluinp1_reg <= ramin_node; -- RAM/Special registers elsif (INST_MOVLW = '1' or INST_ADDLW = '1' or INST_SUBLW = '1' or INST_ANDLW = '1' or INST_IORLW = '1' or INST_XORLW = '1' or INST_RETLW = '1') then aluinp1_reg <= inst_reg(7 downto 0); -- Immidiate value ("k") elsif (INST_CLRF = '1' or INST_CLRW = '1') then aluinp1_reg <= (others => '0'); -- 0 else aluinp1_reg <= w_reg; -- W register end if; -- 2-3-1-2. Set aluinp2 register (source #2) case inst_reg(9 downto 7) is -- construct bit-mask for logical operations/bit test when "000" => mask_node := "00000001"; when "001" => mask_node := "00000010"; when "010" => mask_node := "00000100"; when "011" => mask_node := "00001000"; when "100" => mask_node := "00010000"; when "101" => mask_node := "00100000"; when "110" => mask_node := "01000000";-- when "111" => mask_node := "10000000"; when others => mask_node := "10000000"; end case; if (INST_DECF = '1' or INST_DECFSZ = '1') then aluinp2_reg <= (others => '1'); -- -1 (for decrement) elsif (INST_INCF = '1' or INST_INCFSZ = '1') then--> modified ver1.00c, 2002/08/07-- aluinp2_reg <= "00000001"; -- 1 (for increment) aluinp2_reg <= "000000001"; -- 1 (for increment) elsif (INST_SUBLW = '1' or INST_SUBWF = '1') then-- aluinp2_reg <= (not w_reg) + "00000001"; -- -1 * W register (for subtract) aluinp2_reg <= ("1" & (not w_reg)) + "000000001"; -- -1 * W register (for subtract) elsif (INST_BCF = '1') then-- aluinp2_reg <= not mask_node; -- mask for BCF: value of only one position is '0' aluinp2_reg <= "0" & (not mask_node); -- mask for BCF: value of only one position is '0' -- operation of BCF: AND with inverted mask ("1..101..1") elsif (INST_BTFSC = '1' or INST_BTFSS = '1' or INST_BSF = '1') then-- aluinp2_reg <= mask_node; -- operation of BSF: OR with mask_node ("0..010..0") aluinp2_reg <= "0" & mask_node; -- operation of BSF: OR with mask_node ("0..010..0") -- operation of FSC and FSS: AND with mask_node and then compare with zero else-- aluinp2_reg <= w_reg; -- W register
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -