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

📄 tiny16.v

📁 这个是专门用在ALtera第二代PLD MAXII上的16位微处理器IP核
💻 V
字号:
/****************************************************************************/
//
//	Instruction Set
//
//	0000 0000 nnnn nnnn		pfx
//	0000 1aaa nnnn nnnn		alui
//	0001 0aaa nnnn nnnn		alua
//	0001 1aaa 0000 0000		alux
//	0010 0000 0000 0000		psha
//	0010 0000 0000 0001		pshp
//	0010 0000 0000 0010		pula
//	0010 0000 0000 0011		pulp
//	0010 0000 0000 010c		ldc
//	0010 0000 0000 0110		ldsx
//	0010 0000 0000 0111		ldxs
//	0010 0000 0000 1000		inx
//	0010 0000 0000 1001		dex
//	0010 0000 0000 1010		swap
//	0010 0000 0000 1100		ror
//	0010 0000 0000 1101		rol
//	0010 001n nnnn nnnn		stix
//	0010 010n nnnn nnnn		ldai
//	0010 011n nnnn nnnn		ldxi
//	0010 100n nnnn nnnn		lda
//	0010 101n nnnn nnnn		ldx
//	0010 110n nnnn nnnn		sta
//	0010 111n nnnn nnnn		stx
//	0011 000n nnnn nnnn		ldix
//  01cc nnnn nnnn nnnn		jprc
//	10cc nnnn nnnn nnnn		jrsc
//	11cc 0000 0000 0000		retc
//	
/****************************************************************************/

module tiny16(
	clock,
	address,
	data_in,
	data_out,
	go_read,
	go_write,
	complete,
	cond_true);

parameter		reset = 0;
parameter		fetch = 1;
parameter		exec_1 = 2;
parameter		exec_2 = 3;

input			clock;
input	[15:0]	data_in;
input			complete;

output	[15:0]	address;
output	[15:0]	data_out;
output			go_read;
output			go_write;
output			cond_true;

reg				go_read;
reg				go_write;
reg		[15:0]	address;
reg		[15:0]	data_out;

reg		[5:0]	fsm, next_state;
reg				pc_ena;
reg		[15:0]	pc, pc_data;
reg				sp_ena;
reg		[15:0]	sp, sp_data;
reg				k_ena;
reg		[7:0]	k, k_data, preserve_k;
reg				ra_ena;
reg				cflag, cflag_data, cflag_ena, zflag, zflag_data, zflag_ena;
reg		[15:0]	ra, ra_data;
reg				rx_ena;
reg		[15:0]	rx, rx_data;
reg				ir_ena;
reg		[15:0]	ir, ir_data;
wire			cond_true;
reg		[15:0]	alu_b;
wire	[16:0]	alu_result;

reg				add_sub_cout;
wire				add_sub_carry;
reg		[15:0]	add_sub_result;
lpm_add_sub		add_sub(.dataa(ra), .datab(alu_b), .cin(add_sub_carry), .add_sub(~ir[9]),
					.result(add_sub_result), .cout(add_sub_cout));
defparam		add_sub.lpm_width = 16;
defparam		add_sub.lpm_representation = "UNSIGNED";

assign	add_sub_carry = (ir[10:8] == 0) ? 1'b0 :
						(ir[10:8] == 1) ? cflag :
						(ir[10:8] == 2) ? 1'b1 :
						(ir[10:8] == 3) ? ~cflag : 1'b1;

assign 	cond_true	=	(ir[13:12] == 0) ? cflag :
						(ir[13:12] == 1) ? zflag :
						(ir[13:12] == 2) ? ~zflag : 1'b1;

assign	alu_result	=	(ir[10:8] == 0) ? {add_sub_cout, add_sub_result} :
						(ir[10:8] == 1) ? {add_sub_cout, add_sub_result} :
						(ir[10:8] == 2) ? {~add_sub_cout, add_sub_result} :
						(ir[10:8] == 3) ? {~add_sub_cout, add_sub_result} :
						(ir[10:8] == 4) ? {cflag, (ra & alu_b)} :
						(ir[10:8] == 5) ? {cflag, (ra | alu_b)} :
						(ir[10:8] == 6) ? {cflag, (ra ^ alu_b)} : {~add_sub_cout, ra};

always @ (posedge clock) begin
	fsm <= next_state;
	if(pc_ena == 1'b1)
		pc <= pc_data;
	if(sp_ena == 1'b1)
		sp <= sp_data;
	if(k_ena == 1'b1)
		k <= k_data;
	if(cflag_ena == 1'b1)
		cflag <= cflag_data;
	if(zflag_ena == 1'b1)
		zflag <= zflag_data;
	if(ra_ena == 1'b1)
		ra <= ra_data;
	if(rx_ena == 1'b1)
		rx <= rx_data;
	if(ir_ena == 1'b1)
		ir <= data_in;
end

always @ (fsm, data_in, pc, sp, k, cflag, zflag, cond_true, alu_result, ra, rx, ir, complete) begin
	address <= 0;
	data_out <= 0;
	pc_data <= 0;
	pc_ena <= 1'b0;
	sp_data <= 0;
	sp_ena <= 1'b0;
	k_data <= 0;
	k_ena <= 1'b0;
	cflag_data <= 1'b0;
	cflag_ena <= 1'b0;
	zflag_data <= 1'b0;
	zflag_ena <= 1'b0;
	ra_data <= 0;
	ra_ena <= 1'b0;
	rx_data <= 0;
	rx_ena <= 1'b0;
	alu_b <= 0;
	go_read <= 1'b0;
	go_write <= 1'b0;
	ir_ena <= 1'b0;
	next_state <= fsm;
	case(fsm)
		reset:begin
			pc_data <= 16'b0;
			pc_ena <= 1'b1;
			sp_data <= 16'b0;
			sp_ena <= 16'b0;
			next_state <= fetch;
		end
		
		fetch:begin
			address <= pc;
			pc_data <= pc + 1;
			go_read <= 1'b1;
			if(complete == 1'b1) begin
				ir_ena <= 1'b1;
				pc_ena <= 1'b1;
				next_state <= exec_1;
			end
		end
		
		exec_1:begin
			casex(ir)
				16'b0000_0000_xxxx_xxxx:begin // pfx
					k_data <= ir[7:0];
					k_ena <= 1'b1;
					next_state <= fetch;
				end
				
				16'b0000_1xxx_xxxx_xxxx:begin // alui
					alu_b <= {k, ir[7:0]};
					ra_data <= alu_result[15:0];
					ra_ena <= 1'b1;
					cflag_data <= alu_result[16];
					cflag_ena <= 1'b1;
					zflag_data <= {alu_result[15:0] == 0};
					zflag_ena <= 1'b1;
					k_ena <= 1'b1;
					next_state <= fetch;
				end

				16'b0001_0xxx_xxxx_xxxx:begin // alua
					address <= {k, ir[7:0]};
					go_read <= 1'b1;
					alu_b <= data_in;
					ra_data <= alu_result[15:0];
					cflag_data <= alu_result[16];
					zflag_data <= {alu_result[15:0] == 0};
					if(complete == 1'b1) begin
						ra_ena <= 1'b1;
						cflag_ena <= 1'b1;
						zflag_ena <= 1'b1;
						k_ena <= 1'b1;
						next_state <= fetch;
					end
				end

				16'b0001_1xxx_xxxx_xxxx:begin // alux
					alu_b <= rx;
					ra_data <= alu_result[15:0];
					ra_ena <= 1'b1;
					cflag_data <= alu_result[16];
					cflag_ena <= 1'b1;
					zflag_data <= {alu_result[15:0] == 0};
					zflag_ena <= 1'b1;
					k_ena <= 1'b1;
					next_state <= fetch;
				end
			
				16'b0010_0000_0000_000x:begin // psha, pshp
					address <= sp;
					if(ir[0] == 1'b0) 
						data_out <= ra;
					else
						data_out[1:0] <= {cflag, zflag};
					sp_data <= sp + 1;
					go_write <= 1'b1;
					k_ena <= 1'b1;
					if(complete == 1'b1) begin
						sp_ena <= 1'b1;
						next_state <= fetch;
					end
				end
				
				16'b0010_0000_0000_001x:begin // pula, pulp
					sp_data <= sp - 1;
					sp_ena <= 1'b1;
					k_ena <= 1'b1;
					next_state <= exec_2;
				end
				
				16'b0010_0000_0000_010x:begin // clc, sec
					cflag_data <= ir[0];
					cflag_ena <= 1'b1;
					k_ena <= 1'b1;
					next_state <= fetch;
				end
				
				16'b0010_0000_0000_011x:begin // ldsx, ldsx
					rx_data <= sp;
					sp_data <= rx;
					rx_ena <= ir[0];
					sp_ena <= ~ir[0];
					k_ena <= 1'b1;
					next_state <= fetch;
				end
				
				16'b0010_0000_0000_100x:begin // inx, dex
					if(ir[0] == 1'b0) begin
						rx_data <= rx + 1;
						zflag_data <= {(rx + 1) == 0};
					end
					else begin
						rx_data <= rx - 1;
						zflag_data <= {(rx - 1) == 0};
					end
					rx_ena <= 1'b1;
					zflag_ena <= 1'b1;
					k_ena <= 1'b1;
					next_state <= fetch;
				end
				
				16'b0010_0000_0000_1010:begin // swap
					ra_data <= rx;
					rx_data <= ra;
					ra_ena <= 1'b1;
					rx_ena <= 1'b1;
					k_ena <= 1'b1;
					next_state <= fetch;
				end
				
				16'b0010_0000_0000_1100:begin // ror
					ra_data <= {cflag, ra[15:1]};
					cflag_data <= ra[0];
					ra_ena <= 1'b1;
					cflag_ena <= 1'b1;
					zflag_data <= ({cflag, ra[15:1]} == 0);
					zflag_ena <= 1'b1;
					k_ena <= 1'b1;
					next_state <= fetch;
				end

				16'b0010_0000_0000_1101:begin // rol
					ra_data <= {ra[14:0], cflag};
					cflag_data <= ra[15];
					ra_ena <= 1'b1;
					cflag_ena <= 1'b1;
					zflag_data <= ({ra[14:0], cflag} == 0);
					zflag_ena <= 1'b1;
					k_ena <= 1'b1;
					next_state <= fetch;
				end

				16'b0010_001x_xxxx_xxxx:begin // stix
					address <= rx;
					data_out <= ra;
					go_write <= 1'b1;
					k_ena <= 1'b1;
					if(complete == 1'b1)
						next_state <= fetch;
				end
				
				16'b0010_01xx_xxxx_xxxx:begin // ldai, ldxi
					ra_data <= {k[6:0], ir[8:0]};
					rx_data <= {k[6:0], ir[8:0]};
					ra_ena <= ~ir[9];
					rx_ena <= ir[9];
					k_ena <= 1'b1;
					next_state <= fetch;
				end

				16'b0010_10xx_xxxx_xxxx:begin // lda, ldx
					address <= {k[6:0], ir[8:0]};
					ra_data <= data_in;
					rx_data <= data_in;
					go_read <= 1'b1;
					if(complete == 1'b1) begin
						ra_ena <= ~ir[9];
						rx_ena <= ir[9];
						k_ena <= 1'b1;
						next_state <= fetch;
					end
				end
				
				16'b0010_11xx_xxxx_xxxx:begin // sta, stx
					address <= {k[6:0], ir[8:0]};
					if(ir[9] == 1'b0)
						data_out <= ra;
					else
						data_out <= rx;
					go_write <= 1'b1;
					if(complete == 1'b1) begin
						k_ena <= 1'b1;
						next_state <= fetch;
					end
				end
				
				16'b0011_000x_xxxx_xxxx:begin // ldix
					address <= rx;
					go_read <= 1'b1;
					ra_data <= data_in;
					k_ena <= 1'b1;
					if(complete == 1'b1) begin
						ra_ena <= 1'b1;
						next_state <= fetch;
					end
				end
				
				16'b01xx_xxxx_xxxx_xxxx:begin // jprc
					pc_data <= pc + {k[3:0], ir[11:0]};
					pc_ena <= cond_true;
					k_ena <= 1'b1;
					next_state <= fetch;
				end

				16'b10xx_xxxx_xxxx_xxxx:begin // jrsc
					address <= sp;
					data_out <= pc;
					go_write <= cond_true;
					pc_data <= pc + {k[3:0], ir[11:0]};
					sp_data <= sp + 1;
					if(cond_true == 1'b1)
						if(complete == 1'b1) begin
							pc_ena <= 1'b1;
							sp_ena <= 1'b1;
							k_ena <= 1'b1;
							next_state <= fetch;
						end
						else begin
							pc_ena <= 1'b0;
							sp_ena <= 1'b0;
							k_ena <= 1'b0;
							next_state <= exec_1;
						end
					else begin
						k_ena <= 1'b1;
						next_state <= fetch;
					end
				end
				
				16'b11xx_xxxx_xxxx_xxxx:begin // retc
					k_ena <= 1'b1;
					if(cond_true == 1'b1) begin
						sp_data <= sp - 1;
						sp_ena <= 1'b1;
						next_state <= exec_2;
					end
					else
						next_state <= fetch;
				end
			endcase
		end
		
		exec_2:begin
			casex(ir)
				16'b0010_0000_0000_001x:begin // pula, pulp
					address <= sp;
					go_read <= 1'b1;
					ra_data <= data_in;
					cflag_data <= data_in[1];
					zflag_data <= data_in[0];
					if(complete == 1'b1) begin
						ra_ena <= ~ir[0];
						cflag_ena <= ir[0];
						zflag_ena <= ir[0];
						next_state <= fetch;
					end
				end
				
				16'b11xx_xxxx_xxxx_xxxx:begin // retc
					address <= sp;
					go_read <= 1'b1;
					pc_data <= data_in;
					if(complete == 1'b1) begin
						pc_ena <= 1'b1;
						next_state <= fetch;
					end
				end
				
			endcase
		end
		
		
	endcase
end

endmodule

⌨️ 快捷键说明

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