凭借fpga实现计算器功能


基于fpga的按键输入式计算器设计原理

一 设计思想
fpga开发板上有8个数码管及键盘,可模拟计算器功能,通过NEC红外遥控器获得数据值,后将运算结果显示在数码管上,输入范围0到99999999,输出范围0到99999999,当运算结果大于99999999时显示右边八位,输入数据可以直接显示在数码管上,支持删除,正负数运算等功能,
设计关键在于数据值的获取,只要能准确获得输入值,就可对其进行精确计算,计算部分与显示部分较为简单。
二 fpga实现
分为三部分,输入部分,计算部分,输出部分
输入部分代码如下

//an highlighted blocked
module calculate(
	clk,
	rst_n,
	Get_flag,
	irData,
	irAddr,
	cn,
	bcd_tmp,
	data,
	in5,
	minus
	);
	input clk;
	input rst_n;
	input [15:0]irData;
	input [15:0]irAddr;
	input Get_flag;
	output reg[31:0]data;
	output reg [31:0]in5;
	output reg cn;
	output reg minus;
	reg [1:0]control;
	reg cnt9;
	reg en;
	reg minus_r;
	reg reset;
	reg reset_1;
	reg [3:0]get_data;
	reg minus_get;
	reg [31:0]in6,in7;
	reg [1:0]cnt3,cnt4;
	reg [2:0]cnt8;
	reg [31:0]get_value;
	wire [71:0]shift_reg_out;
	reg value_en;
	integer i;
	output reg[71:0]bcd_tmp;
	reg [71:0]shift_reg;
	reg [7:0]cnt10;
	wire [7:0]get_irData;
	reg [31:0]get_value_r[0:6];
	initial
	begin
		reset<=1'b0;
		cnt4<=1'b0;
	end
	assign get_irData=irData[7:0];
	always@(posedge clk or negedge reset)
	begin
		if(!reset)begin
			get_data<=4'ha;
			cn<=0;
			en<=0;
		end	
		else begin
			case(get_irData)
			8'h87:begin
						get_data<=0;
						cn<=1'b0;
						en<=1'b0;
					end
			8'h92:begin
						get_data<=1;
						cn<=1'b0;
						en<=1'b0;
					end
			8'h93:begin
						get_data<=2;
						cn<=1'b0;
						en<=1'b0;
					end
			8'hcc:begin 
						get_data<=3;
						cn<=1'b0;
						en<=1'b0;
					end
			8'h8e:begin 
						get_data<=4;
						cn<=1'b0;
						en<=1'b0;
					end
			8'h8f:begin 
						get_data<=5;
						cn<=1'b0;
						en<=1'b0;
					end
			8'hc8:begin 
						get_data<=6;
						cn<=1'b0;
						en<=1'b0;
					end
			8'h8a:begin 
						get_data<=7;
						cn<=1'b0;
						en<=1'b0;
					end
			8'h8b:begin 
						get_data<=8;
						cn<=1'b0;
						en<=1'b0;
					end
			8'hc4:begin
						get_data<=9;
						cn<=1'b0;
						en<=1'b0;
					end
			8'h82:begin
						en<=1'b0;
						control<=2'b01;
						cn<=1'b1;
					end
			8'h95:begin
						cn<=1'b0;
						get_data<=4'hf;
						en<=1'b0;
					end
			8'h79:begin
						control<=2'b00;
						cn<=1'b1;
						en<=1'b0;
					end
			8'hda:begin
						control<=2'b10;
						en<=1'b0;
						cn<=1'b1;
					end
			8'hd0:begin
						control<=2'b11;
						cn<=1'b1;
						en<=1'b0;
					end
			8'hce:begin
						cn<=1;
						en<=1;
					end
			default:if((get_irData!=8'hce)&&(get_irData==8'hf1))
						get_data<=4'ha;
			endcase
		end
	end
	always@(posedge clk)
	begin
		if(get_irData==8'hf1)begin
			if((!Get_flag)==1'b1)begin
				cnt4<=cnt4+1;
			end
		end
		else begin
			cnt4<=0;
		end
	end
	always@(posedge clk or negedge reset)
	begin
		if(!reset)begin
			cnt3<=0;
		end
		else if(get_irData==8'hce)begin
			if((!Get_flag)==1'b1)begin
				cnt3<=cnt3+1;
			end
		end
		else begin
			cnt3<=0;
		end
	end
	always@(posedge clk or negedge reset)
	begin
		if(!reset)begin
			cnt9<=0;
		end
		else begin
			if(cn==1'b1)begin
				cnt9<=1'b1;
			end
		end
	end
	always@(posedge clk)
	begin
		if(cnt4==2)begin
			reset_1<=0;
		end
		else begin
			reset_1<=1;
		end
	end
	always@(posedge clk or negedge reset)
	begin
		if(!reset)begin
			cnt8<=0;
		end
		else begin
			if(get_irData==8'hc5)begin
				if((!Get_flag)==1'b1)begin
					cnt8<=cnt8+1;
				end
			end
			else begin
				cnt8<=0;
			end
		end
	end
	always@(posedge clk)
	begin
		if(cnt4==2)begin
			reset<=0;
		end
		else begin
			reset<=reset_1;
		end
	end
	reg en_r;
	wire en_get;
	always@(posedge clk or negedge reset)
	begin
		if(!reset)begin
			en_r<=1'b0;
		end
		else begin
			en_r<=en;
		end
	end
	reg cn_r,cn_r2;
	wire cn_neg;
	always@(posedge clk or negedge reset)
	begin
		if(!reset)begin
			cn_r<=1'b0;
		end
		else begin
			cn_r<=cn;
			cn_r2<=cn_r;
		end
	end
	assign en_get=en_r&(~en);
	always@(posedge clk or negedge reset)
	begin
		if(!reset)begin
			in6<=0;
			in7<=0;
		end
		else if(cn==1'b0)begin
			if(cnt9==1'b0)begin
				in6<=get_value;
			end
			else begin
				in7<=get_value;
			end
		end
		else if(en_get==1'b1)begin
			in6<=in5;
		end
	end
	assign cn_neg=cn_r&(~cn);
	always@(posedge clk or negedge reset)
	begin
		if(!reset)begin
			in5<=0;
			minus<=1'b0;
		end
		else if(en==1'b1)begin
			case(control)
			2'b00:begin
						if(minus_r==1'b0)begin
							in5<=in6+in7;
							if(value_en)begin
								minus<=1;
							end
							else begin
								minus<=0;
							end
						end
						else begin
							if(in6>in7)begin
								in5<=in6-in7;
								if(!minus_r1)
									minus<=1'b0;
								else 
									minus<=1'b1;
							end
							else if(in6==in7)begin
								in5<=in6-in7;
								minus<=1'b0;
							end
							else begin
								in5<=in7-in6;
								if(!minus_r1)
									minus<=1'b1;
								else 
									minus<=1'b0;
							end
						end
					end
			2'b01:begin
						if(minus_r==1'b1)begin
							in5<=in6+in7;
							if(value_en)begin
								minus<=1'b1;
							end
							else begin
								minus<=1'b0;
							end
						end
						else begin
							if(in6>=in7)begin
								in5<=in6-in7;
								if(minus_r1==1'b1)
									minus<=1'b1;
								else 
									minus<=1'b0;
							end
							else begin
								in5<=in7-in6;
								if(minus_r1==1'b1)
									minus<=1'b0;
								else 
									minus<=1'b1;
							end
						end
					end
			2'b10:begin
						in5<=in6*in7;
						minus<=minus_r;	
					end
			2'b11:begin
						in5<=in6/in7;
						minus<=minus_r;
					end
			endcase
		end
	end
	always@(posedge clk or negedge reset)
	begin
		if(!reset)begin
			minus_r<=1'b0;
			minus_r1<=1'b0;
			minus_get<=1'b0;
		end	
		else begin
			if(en_get==1'b1)begin
				minus_r<=minus;
				minus_r1<=minus;
				minus_get<=minus;
			end
			else if(cn==1'b0)begin
				if((get_irData==8'h95)&&(Get_flag==1'b1)&&(minus_get==minus_r)&&(get_value==0))begin
					minus_r<=~minus_r;
				end
				else if((get_irData==8'hc5)&&(data[3:0]==4'hf)&&(Get_flag==1'b1))begin
					minus_r<=~minus_r;
				end
			end
			else begin
				minus_get<=minus_r;
			end
		end
	end	
	reg minus_r1;
	always@(posedge clk or negedge reset)
	begin
		if(!reset)begin
			value_en<=1'b0;
		end
		else if(minus==0)begin
			if((minus_r==1'b1)&&(cnt9==1'b0))begin
				if(control==2'b01)begin
					value_en<=1'b1;
				end
			end
			else if((minus_get==1'b1)&&(cnt9==1'b1))begin
				if(control==2'b00)begin
					value_en<=1'b1;
				end
			end
			else begin
				value_en<=1'b0;
			end
		end
		else begin
			value_en<=1'b1;
		end
	end
	always@(posedge clk or negedge reset)
	begin
		if(!reset)begin
			cnt10<=0;
		end
		else if(en==1'b1)begin
			if(cnt10<33)begin
				cnt10<=cnt10+1;
			end
			else begin
				cnt10<=0;
			end
		end
		else begin
			cnt10<=0;
		end
	end
	always@(posedge clk or negedge reset)
	begin
		if(!reset)begin
			shift_reg<={72{1'b0}};
		end
		else if(cnt10==0)begin
			shift_reg<={72{1'b0}};
		end
		else if(cnt10==1)begin
			shift_reg<={shift_reg[71:33],in5,1'b0};
		end
		else if(cnt10<32)begin
			shift_reg<=(shift_reg_out<<1);
		end
		else if(cnt10==32)begin
			bcd_tmp<=(shift_reg_out<<1);
		end
		else begin
			shift_reg<=shift_reg;
		end
	end
	wire [39:0]bcd_value;
	wire [39:0]shift_reg_out_r;
	assign shift_reg_out={shift_reg_out_r,shift_reg[31:0]};
	assign bcd_value=shift_reg[71:32];
	always@(shift_reg)
	begin
		for(i=1;i<10;i=i+1)
			shift_reg_out_r[i*4-1-:4]<=(bcd_value[i*4-1-:4]>4)?bcd_value[i*4-1-:4]+3:bcd_value[i*4-1-:4];
	end

	always@(posedge clk or negedge reset)
	begin
		if(!reset)begin
			get_value<={32{1'b0}};
			data<={8{4'ha}};
			get_value_r[0]<={32{1'b0}};
			get_value_r[1]<={32{1'b0}};
			get_value_r[2]<={32{1'b0}};
			get_value_r[3]<={32{1'b0}};
			get_value_r[4]<={32{1'b0}};
			get_value_r[5]<={32{1'b0}};
			get_value_r[6]<={32{1'b0}};
		end
		else begin
			if((cn_r2==1'b0)&&(Get_flag==1'b1)&&(get_irData!=8'hce)&&(get_irData!=8'hc5)&&(get_irData!=8'hf1)&&(get_irData!=8'h95))begin
				data<={data[27:0],get_data};
				get_value<=((get_value<<3)+(get_value<<1))+get_data;
				get_value_r[0]<=get_value;
				get_value_r[1]<=get_value_r[0];
				get_value_r[2]<=get_value_r[1];
				get_value_r[3]<=get_value_r[2];
				get_value_r[4]<=get_value_r[3];
				get_value_r[5]<=get_value_r[4];
				get_value_r[6]<=get_value_r[5];
			end
			else if((Get_flag==1'b1)&&(cn_r2==1'b0)&&(get_irData==8'h95)&&(data=={8{4'ha}}))begin
				data<={data[27:0],get_data};
			end
			else if((cnt8>0)&&(Get_flag==1'b1))begin
				data<={4'ha,data[31:4]};
				if(cnt8<7)begin
					get_value<=get_value_r[cnt8-1];
				end
				else begin
					get_value<=get_value_r[6];
				end
			end
			else if(cnt10==33)begin
				data<=bcd_tmp[71:32];
				get_value<=0;
			end
			else if(cn_neg)begin
				data<={8{4'ha}};
				get_value<=0;
			end
		end
	end
	endmodule

所有代码最好写在一个模块,除本模块外需接显示模块,烧写至开发板之后等大约5分钟左右开始工作,如想重新输入 即将复位键拨至0处

  • 3
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值