其他分享
首页 > 其他分享> > HEU大二数电时序逻辑电路设计实验

HEU大二数电时序逻辑电路设计实验

作者:互联网

Contents


1 实验目的

2 实验仪器

3 子任务

3.1 消抖电路

3.2 简易篮球比赛计分器

4 结论心得


1 实验目的

2 实验仪器

在这里插入图片描述

3 子任务

3.1 消抖电路

通常的按键所用开关为机械弹性开关,当机械触点断开、闭合时,由于机械触点的弹性作用,一个按键开关在闭合时不会马上稳定地接通,在断开时也不会一下子断开。因而在闭合及断开的瞬间均伴随有一连串的抖动。按键抖动会引起一次按键被误读多次。为确保CPU对键的一次闭合仅作一次处理,必须去除键抖动。在键闭合稳定时读取键的状态,并且必须判别到键释放稳定后再作处理。

实验原理

RcjHKI.jpg

抖动时间的长短由按键的机械特性决定,一般为 5 m s ~ 10 m s 5ms~10ms 5ms~10ms 。这是一个很重要的时间参数,在很多场合都要用到。按键稳定闭合时间的长短则是由操作人员的按键动作决定的,一般为零点几秒至数秒。单片机一般采用延迟重采样的方式进行消抖。当检测到信号为低时,延迟一段时间(一般为 20 m s 20ms 20ms ),再次检测信号是否为低,如果为低,则证明按键按下,否则认为按键没有按下,继续下一次检查。
最后,通过实现如下功能的电路来验证消抖是否成功。

计数器迭代的流程如图所示:

机械按键触发 消抖电路消抖 计数器迭代一次 数码管显示迭代结果

实验步骤

  1. 根据消抖脉冲要求设计分频计数器。
  2. 设计数码管显示电路。
  3. 编写 V e r i l o g Verilog Verilog 程序并进行调试。
  4. 下载到 F P G A FPGA FPGA 开发板上验证程序相关功能。

具体实现

在 Q u a r t u s Quartus Quartus 中先编写消抖电路程序并封装成一个模块,程序如下所示:

Codes

 module xiaodou
(
  input      clk   , //输入时钟信号,开发板上是50MHz
  input      rst_n , //复位键(低电平触发)
  input      key_in, //对应的机械按键
  output reg clk_500hz, //分频出的500Hz时钟脉冲信号
  output     key_done //按键按下动作完成标志
);
reg [25:0]div_cnt; //分频计数器

always@(posedge clk or negedge rst_n) //获得500Hz时钟脉冲信号
begin
    if(!rst_n)
      begin
	     div_cnt <= 0;
		 clk_500hz <= 0;
	  end
    else if(div_cnt == 99999) //计数十万次反转状态
      begin
	     div_cnt <= 0;
		 clk_500hz <= ~clk_500hz;
	  end
	else 
      begin
	     div_cnt <= div_cnt + 1;
		 clk_500hz <= clk_500hz;
	  end
end


reg qout;
reg key_tmp1,key_tmp2;
parameter n = 10;
reg [25:0] cnt;

always@(posedge clk_500hz or negedge rst_n) 
begin
    if(!rst_n)
		  begin
			 cnt <= 0;
			 qout <= 0;
		  end	  
	else if(key_in == 0) //按键按下
	 begin
	   if(cnt == n-1) //持续2ms的话判定按下
		  begin
			 cnt <= cnt;
			 qout <= 1;
		  end
	   else
		  begin
			 cnt <= cnt+1;
			 qout <= 0;
		  end
	 end
	else
	 begin
		qout <= 0;
		cnt <= 0;
	 end
end	

/*提取前后按键信号*/
always@(posedge clk_500hz or negedge rst_n)
begin
	  if(!rst_n)
	    begin
		 key_tmp1 <= 0;
		 key_tmp2 <= 0;
	    end
	  else 
	    begin
		 key_tmp1 <= qout;
		 key_tmp2 <= key_tmp1;
	    end	  
end
	
	assign key_done = key_tmp1 & (~ key_tmp2);	
		
endmodule 

消抖模块电路逻辑图

在这里插入图片描述

然后编写十进制计数器程序,代码如下:

Codes

 module count
(
   input   clk,
   input   rst_n,
   input   key,
   output  reg[6:0] seg


);
reg[3:0]cnt;
wire key_done;
xiaodou  u1
(
  .clk       (clk     ), //需要分频的信号为50Mhz时钟脉冲信号
  .rst_n     (rst_n   ), //复位键
  .key_in    (key     ), //机械按键
  .clk_500hz (clk_500hz), //分频得到的500Hz时钟脉冲信号
  .key_done  (key_done) //按键动作完成标志
);

always@(posedge clk_500hz or negedge rst_n)
begin
 if(!rst_n)
    cnt <= 0;
 else if(key_done) //按下动作完成
   begin
    if(cnt == 9) //计数到9后需要清零
	  cnt <= 0;
	else
      cnt <= cnt + 1;
   end
end

always@(cnt)     //数码管显示模块
begin

   case(cnt)    
    0:seg = 7'b0000001;
    1:seg = 7'b1001111;
    2:seg = 7'b0010010; 
    3:seg = 7'b0000110; 
    4:seg = 7'b1001100; 
    5:seg = 7'b0100100; 
    6:seg = 7'b0100000; 
    7:seg = 7'b0001111; 
    8:seg = 7'b0000000; 
    9:seg = 7'b0000100; 
   endcase
end

endmodule

十进制计数器电路逻辑图

在这里插入图片描述

十进制计数器引脚分配方案

在这里插入图片描述

下载验证

在这里插入图片描述

问题解决

个人认为,这个实验的主要难点在于如何分频出 500 H z 500Hz 500Hz 的时钟脉冲信号。由于临近期末时间紧迫,我没法系统地深入学习 V e r i l o g Verilog Verilog 语言,因此消抖模块的程序也是找的现成的程序进行学习理解。在最初编写的程序里,我的代码是没有以下这段的。

always@(posedge clk_500hz or negedge rst_n)
begin
	  if(!rst_n)
	    begin
		 key_tmp1 <= 0;
		 key_tmp2 <= 0;
	    end
	  else 
	    begin
		 key_tmp1 <= qout;
		 key_tmp2 <= key_tmp1;
	    end	  
end

我以为,只要计数够 2 m s 2ms 2ms (就是稳定状态)还是低电平就可以了,这段代码没啥存在的必要,但实际验证貌似还是会有不成功的情况。后来才发现,从原理上来说,机械按键按下存在前沿抖动和后沿抖动,因此需要取前后按键信号的按下状态来进行强判定是否按下。

3.2 简易篮球比赛计分器

利用开发板上现有的按键、开关和数码管资源实现一个简易篮球比赛计分器。

实验原理

简易篮球比赛计分器的基本功能要求如下:

篮球计分器主要由以下模块构成

带消抖电路的加分按键模块 计数器模块 计分对象控制模块 数码管显示电路

实验步骤

  1. 根据功能要求设计各模块电路。
  2. 对各模块进行逻辑和算法分析。
  3. 编写 V e r i l o g Verilog Verilog 程序并进行调试。
  4. 下载到 F P G A FPGA FPGA 开发板上验证程序相关功能。

具体实现

下面以甲队计分的过程为例描述计分器的设计过程:

加分按键模块三个按钮有一个按下 判断甲队加分控制端开关是否拉为高电平 若甲队加分开关为高电平则加对应分数 数码管显示甲队分数

在 Q u a r t u s Quartus Quartus 中编写程序,总代码如下:

Codes

module ball
(
	input [2:0] o, //表示对应加1,2,3分按键的状态
	input   m,  //甲队加分控制端
	input   m1, //乙队加分控制端
   input   clk, //50MHz时钟脉冲信号
   input   rst_n, //复位键
   input   key, 
   output  reg [6:0] ans1, 
	output  reg [6:0] ans2, 
	output  reg [6:0] ans3, 
	output  reg [6:0] ans4  
);

integer i;
reg [3:0] l;  //甲队分数的十位
reg [3:0] r;  //甲队分数的个位
reg [3:0] l1; //乙队分数的十位
reg [3:0] r1; //乙队分数的个位
//reg [3:0] key1;
//reg [3:0] key2;
//reg [3:0] key3;
wire key_done; //有按键按下
xiaodou  u1  //消抖模块,代码与子任务3.1中略有不同
(
  .clk       (clk     ),
  .rst_n     (rst_n   ),
  .key_in1   (o[0]   ),
  .key_in2	 (o[1]	 ),
  .key_in3   (o[2]    ),
  .clk_500hz (clk_500hz),
  .key_done  (key_done)
);


always@(posedge clk_500hz or negedge rst_n)
	begin
		if (!rst_n) begin  //复位
			l=0; r=0; l1=0; r1=0;
		end
		else begin
			if (key_done) begin //当有加分按键按下时
			for (i=0; i<=2; i=i+1)
			begin
				if (!o[i]) begin //判断是哪个按键按下
					case (i)
						0:begin
							if (m) begin //给甲队加分
								r=r+1;
								if (r==10) begin
									r=0;
									l=l+1;
								end
							end	
							if (m1) begin //给乙队加分
								r1=r1+1;
								if (r1==10) begin
									r1=0;
									l1=l1+1;
								end
							end
						end
						1:begin
							if (m) begin
								r=r+2;
								if (r>=10) begin
									r=r-10;
									l=l+1;
								end
							end
							if (m1) begin
								r1=r1+2;
								if (r1>=10) begin
									r1=r1-10;
									l1=l1+1;
								end
							end
						end
						2:begin
							if (m) begin
								r=r+3;
								if (r>=10) begin
									r=r-10;
									l=l+1;
								end
							end
							if (m1) begin
								r1=r1+3;
								if (r1>=10) begin
									r1=r1-10;
									l1=l1+1;
								end
							end
						end
				endcase
		   end
	   end
	 end
 end

end

always @ (l)
	begin
		case(l)    
			0:ans1 = 7'b0000001;
			1:ans1 = 7'b1001111;
			2:ans1 = 7'b0010010; 
			3:ans1 = 7'b0000110; 
			4:ans1 = 7'b1001100; 
			5:ans1 = 7'b0100100; 
			6:ans1 = 7'b0100000; 
			7:ans1 = 7'b0001111; 
			8:ans1 = 7'b0000000; 
			9:ans1 = 7'b0000100; 
		endcase
	end

always @ (r)
	begin
		case(r)    
			0:ans2 = 7'b0000001;
			1:ans2 = 7'b1001111;
			2:ans2 = 7'b0010010; 
			3:ans2 = 7'b0000110; 
			4:ans2 = 7'b1001100; 
			5:ans2 = 7'b0100100; 
			6:ans2 = 7'b0100000; 
			7:ans2 = 7'b0001111; 
			8:ans2 = 7'b0000000; 
			9:ans2 = 7'b0000100; 
		endcase
	end
always @ (l1)
	begin
		case(l1)    
			0:ans3 = 7'b0000001;
			1:ans3 = 7'b1001111;
			2:ans3 = 7'b0010010; 
			3:ans3 = 7'b0000110; 
			4:ans3 = 7'b1001100; 
			5:ans3 = 7'b0100100; 
			6:ans3 = 7'b0100000; 
			7:ans3 = 7'b0001111; 
			8:ans3 = 7'b0000000; 
			9:ans3 = 7'b0000100; 
		endcase
	end
always @ (r1)
	begin
		case(r1)    
			0:ans4 = 7'b0000001;
			1:ans4 = 7'b1001111;
			2:ans4 = 7'b0010010; 
			3:ans4 = 7'b0000110; 
			4:ans4 = 7'b1001100; 
			5:ans4 = 7'b0100100; 
			6:ans4 = 7'b0100000; 
			7:ans4 = 7'b0001111; 
			8:ans4 = 7'b0000000; 
			9:ans4 = 7'b0000100; 
		endcase
	end

endmodule

其中,消抖电路模块代码如下:

Codes

module xiaodou
(
  input      clk   ,
  input      rst_n ,
  input      key_in1,
  input   	 key_in2,
  input 		 key_in3,
  output reg clk_500hz,
  output     key_done
);
reg [25:0]div_cnt;

always@(posedge clk or negedge rst_n) 
begin
    if(!rst_n)
      begin
	     div_cnt <= 0;
		 clk_500hz <= 0;
	  end
    else if(div_cnt == 99999)
      begin
	     div_cnt <= 0;
		 clk_500hz <= ~clk_500hz;
	  end
	else 
      begin
	     div_cnt <= div_cnt + 1;
		 clk_500hz <= clk_500hz;
	  end
end


reg qout;
reg key_tmp1,key_tmp2;
parameter n = 10;
reg [25:0] cnt;

always@(posedge clk_500hz or negedge rst_n) 
begin
    if(!rst_n)
		  begin
			 cnt <= 0;
			 qout <= 0;
		  end	  
	else if(key_in1==0 || key_in2==0 || key_in3==0) //此处与子任务3.1中的条件不同
	 begin
	   if(cnt == n-1)
		  begin
			 cnt <= cnt;
			 qout <= 1;
		  end
	   else
		  begin
			 cnt <= cnt+1;
			 qout <= 0;
		  end
	 end
	else
	 begin
		qout <= 0;
		cnt <= 0;
	 end
end	


	
always@(posedge clk_500hz or negedge rst_n)
begin
	  if(!rst_n)
	    begin
		 key_tmp1 <= 0;
		 key_tmp2 <= 0;
	    end
	  else 
	    begin
		 key_tmp1 <= qout;
		 key_tmp2 <= key_tmp1;
	    end	  
end
	
	assign key_done = key_tmp1 & (~ key_tmp2);	
		
endmodule 

简易篮球计分器电路逻辑图

在这里插入图片描述

简易篮球计分器引脚分配方案

在这里插入图片描述

下载验证

在这里插入图片描述

问题解决

这个实验是一个综合度较高的基础实验,我个人也是遇到了不少的问题,经过不断修改调试,总结了以下几个主要的问题:

主要的解决方法就是:

4 心得体会

标签:HEU,begin,end,二数,clk,逻辑电路,key,按键,rst
来源: https://blog.csdn.net/weixin_49082066/article/details/118424805