【重拾FPGA】分开时序和组合逻辑,让写代码思路更清晰

感谢锆石科技。

学了一下锆石科技的按键消抖,真的是突然豁然开朗,收益匪浅。锆石科技代码风格就是将时序逻辑和组合逻辑分开,用类似于状态机的方式赋值,这样真的,让我思路很清晰,逻辑条理也很好,不容易因为赋值问题出现bug。可能是我太菜了呜呜呜。

我就写一下这个计数20ms的按键消抖程序吧。

首先是变量定义,因为要分开时序和组合来写,因此要定义的变量有点多,且都是经过了一个D触发器的:

input clk;
input rst_n;
input key;
	
output led;  //输出led,信号与key_out连接,组合逻辑
	
reg [20:0] time_cnt;  //20ms计数器,时序逻辑
reg [20:0] time_cnt_next;  //计数器下一个状态值,组合逻辑
reg key_in_r;  //按键输入寄存,时序逻辑
reg key_out;  //消抖后的按键输出,时序
reg key_out_next;  //按键输出的下一个状态,组合
	 
wire key_press;  //检测按键按下,组合
	
parameter SET_TIME_20MS = 21'd1_000_000;  //20ms的计数值

通过RTL可以发现,时序逻辑要用的当前状态都是由next状态经过D触发器所得

【重拾FPGA】分开时序和组合逻辑,让写代码思路更清晰_第1张图片

这样便实现了时序和组合的分离

养成这个习惯!!!

开始消抖

1.读取按键值

	//读取key值存入key_in_r寄存
	always@(posedge clk or negedge rst_n)  
	begin
		if(!rst_n)
			key_in_r <= 0;
		else
			key_in_r <= key;
	end

2.计数器启动,由时序和组合逻辑配合

	//计数器模块
	always@(posedge clk or negedge rst_n)
	begin
		if(!rst_n)
			time_cnt <= 21'd0;  //清零
		else
			time_cnt <= time_cnt_next;  //赋值
	end
	
	assign key_press = key_in_r ^ key;  //异或判断按键值是否变化
	//assign key_press = key_in_r & (~key); //判断下降沿
	
	always@(*)
	begin
		if(time_cnt == SET_TIME_20MS || key_press)  //计时满了或者按键值变化
			time_cnt_next = 21'd0;  //清零重新来
		else
			time_cnt_next = time_cnt + 1'b1;  //加一
	end

注意其中key_press的判断方法

3.按键状态检测后的输出

	//按键输出
	always@(posedge clk or negedge rst_n)
	begin
		if(!rst_n)
			key_out <= 0;
		else
			key_out <= key_out_next;  //输出key_out
	end
	
	always@(*)
	begin
		if(time_cnt == SET_TIME_20MS)  //计时满的时候
			key_out_next = key_in_r;  //重新接收key的值用于输出
		else
			key_out_next = key_out;  //保持不变
	end
	
	assign led = key_out;  //led输出与key_out连接

总的来说,变量改变的过程用组合逻辑,将变量的值通过一个D触发器输出时用时序逻辑

你可能感兴趣的:(重拾FPGA)