北邮22级信通院数电:Verilog-FPGA(9)第九周实验(3)实现一个具有清零功能的按键计数器,对按键进行计数并显示

北邮22信通一枚~

跟随课程进度更新北邮信通院数字系统设计的笔记、代码和文章

持续关注作者 迎接数电实验学习~

获取更多文章,请访问专栏:

北邮22级信通院数电实验_青山如墨雨如画的博客-CSDN博客

 

目录


一.代码部分

1.1 counter.v

module counter
(
	input clk,
	input rst,
	input button_1,
	input button_2,
	
	output [8:0] seg_1,
	output [8:0] seg_2
);

	reg [8:0] seg [9:0];
	wire key_pulse_1;
	wire key_pulse_2;
	
	reg [6:0] counting=2'b00;
	reg [3:0] seg_data_1=1'b0;
	reg [3:0] seg_data_2=1'b0;
	
	initial 
		begin 
			seg[0]=9'h3f;
			seg[1]=9'h06;
			seg[2]=9'h5b;
			seg[3]=9'h4f;
			seg[4]=9'h66;
			seg[5]=9'h6d;
			seg[6]=9'h7d;
			seg[7]=9'h07;
			seg[8]=9'h7f;
			seg[9]=9'h6f;
		end
	
	debounce debounce_1
	(
		.clk(clk),
		.rst(rst),
		.key(button_1),
		.key_pulse(key_pulse_1)
		
	);
	
	debounce debounce_2
	(
		.clk(clk),
		.rst(rst),
		.key(button_2),
		.key_pulse(key_pulse_2)
	);

	
always @ (posedge clk or negedge rst)
	begin
		if(!rst)
			begin counting<=0; end
		else 
			begin 
				if(key_pulse_1)
					begin counting<=(counting+1)%100;end
				else if(key_pulse_2)
					begin counting<=(counting-1+100)%100;end
				else
					begin counting<=counting; end
					
				seg_data_1<=counting/10;
				if(counting%10==0)
					begin seg_data_2<=0;end
				else 
					begin seg_data_2<=counting-10*seg_data_1;end
			end
	end
	assign seg_1=seg[seg_data_1];
	assign seg_2=seg[seg_data_2];
endmodule
			
			
			
			
			

1.2 debounce.v

module debounce (clk,rst,key,key_pulse);
 
        parameter       N  =  1;         //要消除的按键的数量
 
	input             clk;
        input             rst;
        input 	[N-1:0]   key;          //输入的按键					
	output  [N-1:0]   key_pulse;        //按键动作产生的脉冲	
 
        reg     [N-1:0]   key_rst_pre;  //定义一个寄存器型变量存储上一个触发时的按键值
        reg     [N-1:0]   key_rst;      //定义一个寄存器变量储存储当前时刻触发的按键值
 
        wire    [N-1:0]   key_edge;      //检测到按键由高到低变化是产生一个高脉冲
 
        //利用非阻塞赋值特点,将两个时钟触发时按键状态存储在两个寄存器变量中
        always @(posedge clk  or  negedge rst)
          begin
             if (!rst) begin
                 key_rst <= {N{1'b1}}; //初始化时给key_rst赋值全为1,{}中表示N个1
                 key_rst_pre <= {N{1'b1}};
             end
             else begin
                 key_rst <= key;       //第一个时钟上升沿触发之后key的值赋给key_rst,
                                       //同时key_rst的值赋给key_rst_pre
                 key_rst_pre <= key_rst;    //非阻塞赋值。
                                            //相当于经过两个时钟触发,
                                            //key_rst存储的是当前时刻key的值,
                                            //key_rst_pre存储的是前一个时钟的key的值
             end    
           end
 
        assign  key_edge = key_rst_pre & (~key_rst);//脉冲边沿检测。
                                                    //当key检测到下降沿时,
                                                    //key_edge产生一个时钟周期的高电平
 
        reg	[17:0]	  cnt;                       //产生延时所用的计数器,系统时钟12MHz,
                                                 //要延时20ms左右时间,至少需要18位计数器     
 
        //产生20ms延时,当检测到key_edge有效是计数器清零开始计数
        always @(posedge clk or negedge rst)
           begin
             if(!rst)
                cnt <= 18'h0;
             else if(key_edge)
                cnt <= 18'h0;
             else
                cnt <= cnt + 1'h1;
             end  
 
        reg     [N-1:0]   key_sec_pre;                //延时后检测电平寄存器变量
        reg     [N-1:0]   key_sec;                    
 
 
        //延时后检测key,如果按键状态变低产生一个时钟的高脉冲。如果按键状态是高的话说明按键无效
        always @(posedge clk  or  negedge rst)
          begin
             if (!rst) 
                 key_sec <= {N{1'b1}};                
             else if (cnt==18'h3ffff)
                 key_sec <= key;  
          end
       always @(posedge clk  or  negedge rst)
          begin
             if (!rst)
                 key_sec_pre <= {N{1'b1}};
             else                   
                 key_sec_pre <= key_sec;             
         end      
       assign  key_pulse = key_sec_pre & (~key_sec);     
 
endmodule

二.管脚分配

三.实现效果

文章出处登录后可见!

已经登录?立即刷新

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
扎眼的阳光的头像扎眼的阳光普通用户
上一篇 2023年12月7日
下一篇 2023年12月7日

相关推荐