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

📄 piccore.v

📁 PIC源代码很不错
💻 V
📖 第 1 页 / 共 4 页
字号:
// PICCORE.vhd// CPU core of CQPIC (PIC16F84/16F84A)// (1) Version 1.00a		Nov 1  1999// (2) Version 1.00b		Dec 10 2000		made a patch for BUG in MAX+plus2 VHDL compiler// (3) Version 1.00c		Aug 07 2002		made a patch for carry flag operations at substraction operations// (4) Version 1.00d		Aug 26 2004		debugged Z flag behavior (in case such that distinations are same as them)//// Copyright(c)1999-2004 Sumio Morioka// e-mail:morioka@fb3.so-net.ne.jp, URL:http://www02.so-net.ne.jp/~morioka/cqpic.htmmodule piccore(progdata, progadr, 				ramdtin, ramdtout, ramadr, readram, writeram, 				existeeprom, eepdtin, eepdtout, eepadr, readeepreq, readeepack, writeeepreq, writeeepack, 				porta_in, porta_out, porta_dir, 				portb_in, portb_out, portb_dir, 				rbpu, 				int0, int4, int5, int6, int7, 				t0cki, 				wdtena, wdtclk, wdtfull, 				powerdown, startclkin, 				ponrst_n, mclr_n, 				clkin, clkout);	// program ROM data bus/address bus	input	[13:0]	progdata;	// ROM read data	output	[12:0]	progadr;	// ROM address	// data RAM data bus/address bus/control signals	input	[7:0]	ramdtin;	// RAM read data	output	[7:0]	ramdtout;	// RAM write data	output	[8:0]	ramadr;		// RAM address; ramadr(8..7) indicates RAM-BANK	output			readram;	// RAM read strobe (H active)	output			writeram;	// RAM write strobe (H active)	// EEPROM data bus/address bus	input			existeeprom;// Set to '1' if EEPROM is implemented.	input	[7:0]	eepdtin;	// EEPROM read data	output	[7:0]	eepdtout;	// EEPROM write data	output	[7:0]	eepadr;		// EEPROM address	output			readeepreq;	// EEPROM read request (H active)	input			readeepack;	// EEPROM read acknowledge (H active)	output			writeeepreq;// EEPROM write request (H active)	input			writeeepack;// EEPROM write acknowledge (H active)	// I/O ports	input	[4:0]	porta_in;	// PORT-A input data	output	[4:0]	porta_out;	// PORT-A output data	output	[4:0]	porta_dir;	// TRISA: PORT-A signal direction (H:input, L:output)	input	[7:0]	portb_in;	// PORT-B input data	output	[7:0]	portb_out;	// PORT-B output data	output	[7:0]	portb_dir;	// TRISB: PORT-B signal direction (H:input, L:output)	output			rbpu;		// PORT_B pull-up enable (usually not used)	// PORT-B interrupt input	input			int0;		// PORT-B(0) INT	input			int4;		// PORT-B(4) INT	input			int5;		// PORT-B(5) INT	input			int6;		// PORT-B(6) INT	input			int7;		// PORT-B(7) INT	// TMR0 Control	input			t0cki;		// T0CKI (PORT-A(4))	// Watch Dog Timer Control	input			wdtena;		// WDT enable (H active)	input			wdtclk;		// WDT clock	output			wdtfull;	// WDT-full indicator (H active)	// CPU clock stop/start indicators	output			powerdown;	// SLEEP-mode; if H, you can stop system clock clkin	output			startclkin;	// WAKEUP; if H, you should turn on clock for waking up from sleep-mode	// CPU reset	input			ponrst_n;	// Power-on reset (L active)	input			mclr_n;		// Normal reset (L active)	// CPU clock	input			clkin;		// Clock input	output			clkout;		// Clock output (clkin/4)	// User registers	reg 	[7:0]	w_reg;		// W	reg 	[7:0]	tmr0_reg;	// TMR0	reg 	[12:0]	pc_reg;		// PCH/PCL	reg 	[7:0]	status_reg;	// STATUS	reg 	[7:0]	fsr_reg;	// FSR	reg 	[4:0]	portain_sync_reg;	// PORTA IN (synchronizer)	reg 	[4:0]	portaout_reg;		// PORTA OUT	reg 	[7:0]	portbin_sync_reg;	// PORTB IN (synchronizer)	reg 	[7:0]	portbout_reg;		// PORTB OUT	reg 	[7:0]	eedata_reg;	// EEDATA	reg 	[7:0]	eeadr_reg;	// EEADR	reg 	[4:0]	pclath_reg;	// PCLATH	reg 	[7:0]	intcon_reg;	// INTCON	reg 	[7:0]	option_reg;	// OPTION	reg 	[4:0]	trisa_reg;	// TRISA	reg 	[7:0]	trisb_reg;	// TRISB	reg 	[4:0]	eecon1_reg;	// EECON1	// Internal registers for controlling instruction execution	reg 	[13:0]	inst_reg;		// Hold fetched op-code/operand	reg 	[7:0]	aluinp1_reg;	// data source (1 of 2)//> changed ver1.00c, 2002/08/07	//	reg [7:0]	aluinp2_reg		// data source (2 of 2)	reg 	[8:0]	aluinp2_reg;	// data source (2 of 2)//<	reg 	[7:0]	aluout_reg;		// result of calculation	reg 			exec_op_reg;	// if L (i.e. GOTO instruction etc), stall exec of instruction	reg 			intstart_reg;	// if H (i.e. interrupt), stall exec of instruction	reg 			sleepflag_reg;	// if H, sleeping	// Stack	reg 	[12:0]	stack_reg	[8 - 1:0];	// stack body (array of data-registers)	reg 	[2:0]	stack_pnt_reg;			// stack pointer (binary encoded)	wire	[8 - 1:0]	stack_pos_node;		// same with stack pointer, but one-hot encoded	reg 	[12:0]	stacktop_node;			// data value of stack-top	// WDT register and its control	reg 	[7:0]	wdt_reg;				// WDT counter	reg 			wdt_full_reg;			// WDT->CPU; hold WDT-full signal until CPU is reset	reg 	[2:0]	wdt_full_sync_reg;		// CPU; synchronizer for wdt_full_reg	reg 			wdt_clr_reg;			// CPU->WDT; request to zero-clear wdt_reg	reg 			wdt_clr_reqhold_reg;	// CPU; hold a clear-request if previous request is still processing	reg 	[1:0]	wdtclr_req_reg;			// WDT; synchronizer for wdt_clr_reg	wire			wdtclr_ack;				// WDT->CPU; ack to wdt_clr_reg (same with wdtclr_req_reg(1))	reg 			wdtclr_ack_sync_reg;	// CPU; synchronizer for wdtclr_ack	reg 			wdtfull_clr_reg;		// CPU->WDT; requst to clear wdt_full_reg	reg 	[1:0]	wdtfullclr_req_reg;		// WDT; synchronizer for wdtfull_clr_reg	// TMR0 prescaler	wire			psck;			// clock for prescaler	reg 	[7:0]	pscale_reg;		// prescaler	reg 			ps_full_reg;	// clock for TMR0, from prescaler	wire			inctmrck;		// clock for TMR0	reg 			inctmrhold_reg;	// hold TMR0 increment request	// Interrupt registers/nodes	reg 	[4:0]	intrise_reg;	// detect positive edge of PORT-B inputs	reg 	[4:0]	intdown_reg;	// detect negative edge of PORT-B inputs	wire			rb0_int, rb4_int, rb5_int, rb6_int, rb7_int;	// interrupt trigger	wire			rbint;			// RB4-7 interrupt trigger	wire			inte;			// RB0   interrupt trigger	reg 	[4:0]	intclr_reg;		// CPU; clear intrise_reg and intdown_reg	// State register	parameter	STATEBIT_SIZE	= 3;	reg 	[STATEBIT_SIZE - 1:0]	state_reg;	parameter	Qreset	= 3'b100;	// reset state	parameter	Q1	= 3'b000;		// state Q1	parameter	Q2	= 3'b001;		// state Q2	parameter	Q3	= 3'b011;		// state Q3	parameter	Q4	= 3'b010;		// state Q4	// Result of decoding instruction	wire			INST_ADDLW, INST_ADDWF, INST_ANDLW, INST_ANDWF, INST_BCF, INST_BSF, INST_BTFSC, INST_BTFSS;	wire			INST_CALL, INST_CLRF, INST_CLRW, INST_CLRWDT, INST_COMF, INST_DECF, INST_DECFSZ;	wire			INST_GOTO, INST_INCF, INST_INCFSZ, INST_IORLW, INST_IORWF, INST_MOVLW, INST_MOVF, INST_MOVWF;	wire			INST_RETFIE, INST_RETLW, INST_RET, INST_RLF, INST_RRF;	wire			INST_SLEEP, INST_SUBLW, INST_SUBWF, INST_SWAPF, INST_XORLW, INST_XORWF;	// Result of calculating RAM access address	wire	[8:0]	ramadr_node;	// RAM access address	wire			ADDR_TMR0, ADDR_PCL, ADDR_STAT, ADDR_FSR, ADDR_PORTA, ADDR_PORTB;	wire			ADDR_EEDATA, ADDR_EEADR, ADDR_PCLATH, ADDR_INTCON, ADDR_OPTION, ADDR_TRISA, ADDR_TRISB;	//	wire ADDR_EECON1, ADDR_EECON2, ADDR_SRAM															: std_logic;	wire			ADDR_EECON1, ADDR_SRAM;	// Other output registers (for removing hazards)	reg 			writeram_reg;	// data-sram write strobe//> deleted ver1.00c, 2002/08/07	//	reg	[8:0]	ramadr_reg		// data-sram address//<	reg 			clkout_reg;		// clkout output	// Synchronizers	reg 			inte_sync_reg;	reg 			rbint_sync_reg;	reg 	[1:0]	inctmr_sync_reg;	reg 			rdeep_sync_reg;	reg 			wreep_sync_reg;	reg 			mclr_sync_reg;	reg 			poweron_sync_reg;// CPU synchronizers	always @(posedge clkin) begin		inte_sync_reg		<= inte;		rbint_sync_reg		<= rbint;		wdtclr_ack_sync_reg	<= wdtclr_ack;		mclr_sync_reg		<= mclr_n;		poweron_sync_reg	<= ponrst_n;		rdeep_sync_reg		<= readeepack;		wreep_sync_reg		<= writeeepack;		inctmr_sync_reg[0]	<= inctmrck;		inctmr_sync_reg[1]	<= inctmr_sync_reg[0];		if (poweron_sync_reg == 1'b0 || mclr_sync_reg == 1'b0) begin			wdt_full_sync_reg	<= 3'b000;		end else begin			wdt_full_sync_reg[0]	<= wdt_full_reg;			wdt_full_sync_reg[1]	<= wdt_full_sync_reg[0];	// (remove meta-stable)			wdt_full_sync_reg[2]	<= wdt_full_sync_reg[1];	// (detect positive edge)		end	end// Decode OPcode	(see pp.54 of PIC16F84 data sheet)	// only 1 signal of the following signals will be '1'	assign	INST_CALL	= (inst_reg[13:11] == 3'b100)   ? 1'b1 : 1'b0;	assign	INST_GOTO	= (inst_reg[13:11] == 3'b101)   ? 1'b1 : 1'b0;	assign	INST_BCF	= (inst_reg[13:10] == 4'b0100)  ? 1'b1 : 1'b0;	assign	INST_BSF	= (inst_reg[13:10] == 4'b0101)  ? 1'b1 : 1'b0;	assign	INST_BTFSC	= (inst_reg[13:10] == 4'b0110)  ? 1'b1 : 1'b0;	assign	INST_BTFSS	= (inst_reg[13:10] == 4'b0111)  ? 1'b1 : 1'b0;	assign	INST_MOVLW	= (inst_reg[13:10] == 4'b1100)  ? 1'b1 : 1'b0;	assign	INST_RETLW	= (inst_reg[13:10] == 4'b1101)  ? 1'b1 : 1'b0;	assign	INST_SUBLW	= (inst_reg[13:9] == 5'b11110)  ? 1'b1 : 1'b0;	assign	INST_ADDLW	= (inst_reg[13:9] == 5'b11111)  ? 1'b1 : 1'b0;	assign	INST_IORLW	= (inst_reg[13:8] == 6'b111000) ? 1'b1 : 1'b0;	assign	INST_ANDLW	= (inst_reg[13:8] == 6'b111001) ? 1'b1 : 1'b0;	assign	INST_XORLW	= (inst_reg[13:8] == 6'b111010) ? 1'b1 : 1'b0;	assign	INST_SUBWF	= (inst_reg[13:8] == 6'b000010) ? 1'b1 : 1'b0;	assign	INST_DECF	= (inst_reg[13:8] == 6'b000011) ? 1'b1 : 1'b0;	assign	INST_IORWF	= (inst_reg[13:8] == 6'b000100) ? 1'b1 : 1'b0;	assign	INST_ANDWF	= (inst_reg[13:8] == 6'b000101) ? 1'b1 : 1'b0;	assign	INST_XORWF	= (inst_reg[13:8] == 6'b000110) ? 1'b1 : 1'b0;	assign	INST_ADDWF	= (inst_reg[13:8] == 6'b000111) ? 1'b1 : 1'b0;	assign	INST_MOVF	= (inst_reg[13:8] == 6'b001000) ? 1'b1 : 1'b0;	assign	INST_COMF	= (inst_reg[13:8] == 6'b001001) ? 1'b1 : 1'b0;	assign	INST_INCF	= (inst_reg[13:8] == 6'b001010) ? 1'b1 : 1'b0;	assign	INST_DECFSZ	= (inst_reg[13:8] == 6'b001011) ? 1'b1 : 1'b0;	assign	INST_RRF	= (inst_reg[13:8] == 6'b001100) ? 1'b1 : 1'b0;	assign	INST_RLF	= (inst_reg[13:8] == 6'b001101) ? 1'b1 : 1'b0;	assign	INST_SWAPF	= (inst_reg[13:8] == 6'b001110) ? 1'b1 : 1'b0;	assign	INST_INCFSZ	= (inst_reg[13:8] == 6'b001111) ? 1'b1 : 1'b0;	assign	INST_MOVWF	= (inst_reg[13:7] == 7'b0000001) ? 1'b1 : 1'b0;	assign	INST_CLRW	= (inst_reg[13:7] == 7'b0000010) ? 1'b1 : 1'b0;	assign	INST_CLRF	= (inst_reg[13:7] == 7'b0000011) ? 1'b1 : 1'b0;	assign	INST_RET	= (inst_reg[13:0] == 14'b00000000001000) ? 1'b1 : 1'b0;	assign	INST_RETFIE	= (inst_reg[13:0] == 14'b00000000001001) ? 1'b1 : 1'b0;	assign	INST_SLEEP	= (inst_reg[13:0] == 14'b00000001100011) ? 1'b1 : 1'b0;	assign	INST_CLRWDT	= (inst_reg[13:0] == 14'b00000001100100) ? 1'b1 : 1'b0;// Calculate RAM access address	(see pp.19 of PIC16F84 data sheet)	// if "d"=0, indirect addressing is used, so RAM address is BANK+FSR	// otherwise, RAM address is BANK+"d"	// (see pp.19 of PIC16F84 data sheet)	assign	ramadr_node	= (inst_reg[6:0] == 7'b0000000) 				? {status_reg[7], fsr_reg[7:0]} : {status_reg[6:5], inst_reg[6:0]};	// check if this is an access to external RAM or not	assign	ADDR_SRAM	= (ramadr_node[6:0] > 7'b0001011) ? 1'b1	// 0CH-7FH, 8CH-FFH						: 1'b0;	// check if this is an access to special register or not	// only 1 signal of the following signals will be '1'	assign	ADDR_TMR0	= (ramadr_node[7:0] == 8'b00000001) ? 1'b1	// 01H				: 1'b0;	assign	ADDR_PCL	= (ramadr_node[6:0] == 7'b0000010) ? 1'b1		// 02H, 82H				: 1'b0;	assign	ADDR_STAT	= (ramadr_node[6:0] == 7'b0000011) ? 1'b1		// 03H, 83H				: 1'b0;	assign	ADDR_FSR	= (ramadr_node[6:0] == 7'b0000100) ? 1'b1		// 04H, 84H				: 1'b0;	assign	ADDR_PORTA	= (ramadr_node[7:0] == 8'b00000101) ? 1'b1	// 05H				: 1'b0;	assign	ADDR_PORTB	= (ramadr_node[7:0] == 8'b00000110) ? 1'b1	// 06H				: 1'b0;	assign	ADDR_EEDATA	= (ramadr_node[7:0] == 8'b00001000) ? 1'b1	// 08H				: 1'b0;	assign	ADDR_EEADR	= (ramadr_node[7:0] == 8'b00001001) ? 1'b1	// 09H				: 1'b0;	assign	ADDR_PCLATH	= (ramadr_node[6:0] == 7'b0001010) ? 1'b1		// 0AH, 8AH				: 1'b0;	assign	ADDR_INTCON	= (ramadr_node[6:0] == 7'b0001011) ? 1'b1		// 0BH, 8BH				: 1'b0;	assign	ADDR_OPTION	= (ramadr_node[7:0] == 8'b10000001) ? 1'b1	// 81H				: 1'b0;	assign	ADDR_TRISA	= (ramadr_node[7:0] == 8'b10000101) ? 1'b1	// 85H				: 1'b0;	assign	ADDR_TRISB	= (ramadr_node[7:0] == 8'b10000110) ? 1'b1	// 86H				: 1'b0;	assign	ADDR_EECON1	= (ramadr_node[7:0] == 8'b10001000) ? 1'b1	// 88H				: 1'b0;	//	assign ADDR_EECON2	= (ramadr_node[7:0] == 8'b10001001 ? 1'b1 : 1'b0;	// 89H// Read value of PC-STACK top	// convert binary value of stack pointer into onehot value (for reducing circuit)	assign	stack_pos_node[0]	= (stack_pnt_reg == 0) ? 1'b1 : 1'b0;	assign	stack_pos_node[1]	= (stack_pnt_reg == 1) ? 1'b1 : 1'b0;	assign	stack_pos_node[2]	= (stack_pnt_reg == 2) ? 1'b1 : 1'b0;	assign	stack_pos_node[3]	= (stack_pnt_reg == 3) ? 1'b1 : 1'b0;	assign	stack_pos_node[4]	= (stack_pnt_reg == 4) ? 1'b1 : 1'b0;	assign	stack_pos_node[5]	= (stack_pnt_reg == 5) ? 1'b1 : 1'b0;	assign	stack_pos_node[6]	= (stack_pnt_reg == 6) ? 1'b1 : 1'b0;	assign	stack_pos_node[7]	= (stack_pnt_reg == 7) ? 1'b1 : 1'b0;	// pick up value of stack-top from stack cells	reg 	[12:0]	stack_cell;	// value of each stack cell	reg 	[12:0]	top;		// value of stack top	wire	[12:0]	stack0_node;	wire	[12:0]	stack1_node;	wire	[12:0]	stack2_node;	wire	[12:0]	stack3_node;	wire	[12:0]	stack4_node;	wire	[12:0]	stack5_node;	wire	[12:0]	stack6_node;	wire	[12:0]	stack7_node;	assign	stack0_node	= stack_reg[0];	assign	stack1_node	= stack_reg[1];	assign	stack2_node	= stack_reg[2];	assign	stack3_node	= stack_reg[3];	assign	stack4_node	= stack_reg[4];	assign	stack5_node	= stack_reg[5];	assign	stack6_node	= stack_reg[6];	assign	stack7_node	= stack_reg[7];	always @(stack0_node or stack1_node or stack2_node or stack3_node				or stack4_node or stack5_node or stack6_node or stack7_node				or stack_pos_node) begin		if (stack_pos_node[0] == 1'b1) begin	// (if the position is stack top)			stack_cell[0]	= stack0_node;		end else begin			stack_cell[0]	= 13'b0000000000000;		end		if (stack_pos_node[1] == 1'b1) begin			stack_cell[1]	= stack1_node;		end else begin			stack_cell[1]	= 13'b0000000000000;		end		if (stack_pos_node[2] == 1'b1) begin			stack_cell[2]	= stack2_node;		end else begin			stack_cell[2]	= 13'b0000000000000;		end		if (stack_pos_node[3] == 1'b1) begin			stack_cell[3]	= stack3_node;		end else begin			stack_cell[3]	= 13'b0000000000000;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -