本帖最后由 FEM炮。 于 2016-10-2 18:57 编辑
国庆也没出去玩,就呆在了学校,今天做了一个简易的含1序列检测器,串行输入一段数据,检测并统计序列中1的个数。首先编写了一个主控制程序,其中的按键消抖直接采用了,锆石科技的例程,自己编写了功能模块。以下是代码程序
- module jiance1
- (
- //输入端口
- CLK_50M,RST_N,KEY,SEG_EN,
- //输出端口
- a
- );
- //---------------------------------------------------------------------------
- //-- 外部端口声明
- //---------------------------------------------------------------------------
- input CLK_50M; //时钟的端口,开发板用的50MHz晶振
- input RST_N; //复位的端口,低电平复位
- input [ 3:0] KEY; //对应开发板上的KEY
- output reg SEG_EN; //数码管使能端口
- output reg a; //有1输入时,给a赋1,为1计数器提供计数脉冲
- //---------------------------------------------------------------------------
- //-- 内部端口声明
- //---------------------------------------------------------------------------
- reg [20:0] time_cnt; //用来计数按键延迟的定时计数器
- reg [20:0] time_cnt_n; //time_cnt的下一个状态
- reg [ 3:0] key_in_r; //用来接收按键信号的寄存器
- reg [ 3:0] key_out; //消抖完成输出按键
- reg [ 3:0] key_out_n; //key_out的下一个状态
- wire key_press; //检测按键有没有变化
- reg q;
- //设置定时器的时间为20ms,计算方法为 (20*10^3)us / (1/50)us 50MHz为开发板晶振
- parameter SET_TIME_20MS = 21'd1_000_000;
- //---------------------------------------------------------------------------
- //-- 按键消抖与检测部分
- //---------------------------------------------------------------------------
- //---------------------------------------------------------------------------
- //-- 逻辑功能实现
- //---------------------------------------------------------------------------
- //时序电路,用来key_in_r寄存器赋值
- always @ (posedge CLK_50M, negedge RST_N)
- begin
- if(!RST_N) //判断复位
- key_in_r <= 8'h00; //初始化key_in_r值
- else
- key_in_r <= KEY; //将按键的值赋值给key_in_r
- end
- assign key_press = key_in_r ^ KEY; //检测按键有没有变化
- //时序电路,用来给time_cnt寄存器赋值
- always @ (posedge CLK_50M, negedge RST_N)
- begin
- if(!RST_N) //判断复位
- time_cnt <= 21'h0; //初始化time_cnt值
- else
- time_cnt <= time_cnt_n; //用来给time_cnt赋值
- end
- //组合电路,实现20ms的定时计数器
- always @ (*)
- begin
- if(time_cnt == SET_TIME_20MS || key_press) //判断按键有没有变化、时间有没有到
- time_cnt_n = 21'h0; //如果到达20ms或者按键有了变化,那么定时计数器将会被清零
- else
- time_cnt_n = time_cnt + 1'b1; //如果未到20ms或者按键没有变化,那么定时计数器将会继续累加
- end
- //时序电路,用来key_out寄存器赋值
- always @ (posedge CLK_50M, negedge RST_N)
- begin
- if(!RST_N) //判断复位
- key_out <= 8'h00; //初始化key_out值
- else
- key_out <= key_out_n; //用来给key_out赋值
- end
- //组合电路,每20ms接收一次按键的值
- always @ (*)
- begin
- if(time_cnt == SET_TIME_20MS) //判断20ms时间
- key_out_n = key_in_r; //如果到达20ms,接收一次按键的值
- else
- key_out_n = key_out; //如果未到20ms,保持原状态不变
- end
- //---------------------------------------------------------------------------
- //-- 功能实现部分
- //---------------------------------------------------------------------------
- always @(posedge CLK_50M or negedge key_out[3])
- begin
- if(!key_out[3])
- begin
- if(key_out[2])
- q=1; //寄存start值
- if(q)
- begin
- SEG_EN=0;
- if(key_out[1]) a<=0; //代表输入0
- if(key_out[0]) a<=1; //代表输入1
- end
- end
- else
- q=0;
- end
- endmodule
复制代码
然后又编写了一段简单的译码程序,用于数码管显示统计出的1的个数,代码如下
module yima1(cnt,SEG_DATA);
-
- input [7:0] cnt;
- output reg [ 7:0] SEG_DATA; //数码管端口
- always @ (*)
- begin
- case(cnt)
- 0 : SEG_DATA[6:0] = 7'b0111111; //显示数字 "0"
- 1 : SEG_DATA[6:0] = 7'b0000110; //显示数字 "1"
- 2 : SEG_DATA[6:0] = 7'b1011011; //显示数字 "2"
- 3 : SEG_DATA[6:0] = 7'b1001111; //显示数字 "3"
- 4 : SEG_DATA[6:0] = 7'b1100110; //显示数字 "4"
- 5 : SEG_DATA[6:0] = 7'b1101101; //显示数字 "5"
- 6 : SEG_DATA[6:0] = 7'b1111101; //显示数字 "6"
- 7 : SEG_DATA[6:0] = 7'b0000111; //显示数字 "7"
- 8 : SEG_DATA[6:0] = 7'b1111111; //显示数字 "8"
- 9 : SEG_DATA[6:0] = 7'b1101111; //显示数字 "9"
- 10 : SEG_DATA[6:0] = 7'b1110111; //显示数字 "A"
- 11 : SEG_DATA[6:0] = 7'b1111100; //显示数字 "B"
- 12 : SEG_DATA[6:0] = 7'b1011000; //显示数字 "C"
- 13 : SEG_DATA[6:0] = 7'b1011110; //显示数字 "D"
- 14 : SEG_DATA[6:0] = 7'b1111001; //显示数字 "E"
- 15 : SEG_DATA[6:0] = 7'b1110001; //显示数字 "F"
- default :SEG_DATA[6:0] = 7'b0111111; //显示数字 "0"
- endcase
- end
endmodule
复制代码
最后生成相应的模块,加入了quartus现成的计数器模块,用来统计1的个数,最后的顶层电路文件如下图所示:
具体演示如下,key5为复位键,ke6为start,key7输入0,key8输入1,按下start,并出入序列,能检测并统计1的个数
0
|
|
|
|
做的 很酷啊
|
|
|
|
|