⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 piccore.vhd

📁 PIC源代码很不错
💻 VHD
📖 第 1 页 / 共 4 页
字号:
		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 + -