赞
踩
这学期我们开设了DSP实验这门课,主要目的是使用开发平台(本校使用黑金动力社区基于飓风IV的初级产品)进行数字信号处理,当然在课程的开始,熟悉开发板的使用方式以及verilog语言的编写时十分必要的,这写东西都是第一次接触,尤其是verilog语言,这次都是按照老师教的一点点知识来写的,所以代码异常繁杂。当然希望以后的文章中我的Verilog代码能够慢慢进步。
将程序设置为一个有限状态机的形式,程序在几种状态之间不断切换。共有以下几个状态(在程序中使用status进行标记):
0.初始状态。此时六个数字均显示为0
1.设置状态。此时可以使用按键调整每一位数的大小,当前选中的位数右下角的小数点会亮
2.计时状态。此时会进行倒计时至数字全部为0
3.结束状态。此时会保持全零状态并使蜂鸣器发出数秒声音。
4.初始化状态。此时对变量重新进行初始化,以便于其进入下一个循环(初始状态)
状态之间的转换:
程序烧在开发板上后即为0状态,点击中间键即可进入1状态,使用上下左右键位设置完事件后再次点击中间键即可进入2状态,计时结束后自动进入3状态,蜂鸣器响几秒后自动进入4状态,数据初始化后自动进入0状态,完成循环。
1.按键的消抖
按键在按下和松开时电位是不稳定的,因此如何记录一次按键的点击是一个值得思考的问题,网上针对此问题已经有了许多算法,这里提出我自己思考的一种策略:
只针对按键的点击事件,而不针对按键的持续按压事件。
首先设置5ms的检测时间间隔,考虑到人的按动速度,此间隔足够短。检测方法,在每个长度为5ms的时间间隔内记录按键电平为0的次数,若不为0,说明这5ms内按键被按动了,并重进行下一个时间间隔的检测,直至出现第一个0电平次数为0的时间间隔。到此可认为完成了一次点击。因为即使考虑按键抖动可能产生的高电平,5ms也足够的。从按键按下到最终相应中间相隔了大概一个时间间隔,但对于人来说,5ms足够短,完全可以忽略不计。
此检测步骤应该与主程序同步进行,因目前尚未掌握子模块与顶层模块的参数传递,故此处利用另一个always块在主module写,这样便可以做到与主程序的module并行执行。
2.倒计时时的数字变化
这个也是我认为值得思考的一个问题。设置的最小时间单位为10ms,倒计时开始后,这一位不断减小至0,而后变为9,以此循环,而每当这一为变成九时,其上一位也要减一。同理,当后两位都从0变到9的时候,分钟单位应该减一,此即为数字变化的设计思路。但要注意的是,由于一分钟是60s,10s的最高位只能达到5而不是9。
容易忽略的地方:
1)每个时钟周期仅仅有五十兆分之一秒,而最低位每次减一需要百分之一秒,因此最低位从0变为9后,会维持很多个时钟周期,因此前一位的判定条件不能简单的为后一位变为9,而必须是后一位第一次变为9,这一点需要注意。
2)即使的设置是后面位数均达到9(10s位是5)时,前一位改变,但存在另一种情况:即开始设置的时间恰好满足这样的条件,这种情况下,前一位不能直接改变,还是应该从最低位开始逐渐减小。
使用的硬件为CYCLONE IV 核心板 DB4CE15,需要配置的管脚包括:
输入时钟
key
蜂鸣器
数码管等
再次说明,我第一次接触verilog语言,代码冗长复杂在所难免,以后会尽量改进
by qiuzelin 2019-3-18
var foo = 'bar'; module num_test(in,dig,sel,key,led,ring); input in; input [4:0] key; //input不能被定义为reg类型 //key 从0-4分别为上下左右中 reg [27:0] cc; output reg [7:0] dig; output reg [5:0] sel; output reg led; reg [2:0] status; reg [27:0] cc_1; //用于状态0时的扫描 reg [10:0] key_sta [4:0] ; //key模块中用用计数的变量 reg [27:0] temp_1; reg [27:0] temp_2; reg [27:0] temp_3; reg [27:0] temp_4; reg [27:0] temp_5; reg [27:0] cc_key_1; reg [27:0] cc_key_2; reg [27:0] cc_key_3; reg [27:0] cc_key_4; reg [27:0] cc_key_5; reg [10:0] key_sta_2; reg [10:0] key_sta_3 [4:0]; //status=1时用到的参量 reg [7:0] num_pool [9:0];//用于存放所有可能的数字取值 reg [7:0] num_pool_2 [9:0];//存放带有小数点的可能取值 reg [27:0] cc_2; reg [25:0] num_value [5:0]; reg [10:0] num_posi; //status=2时用到的参量 reg [27:0] cc_3; reg [27:0] cc_31; reg [25:0] num_value_2 [5:0]; //记录最终设置的时间,对不同位数都要进行判断,此处为不冲突,多设置几组 倒序 //若初始为99毫秒,则秒不需要减一 reg [25:0] num_value_2_1 [5:0]; reg [25:0] num_value_2_2 [5:0]; reg [25:0] num_value_2_3 [5:0]; reg [25:0] num_value_2_4 [5:0]; reg [5:0] index [5:0]; //倒序 //status=3用到的参量 output reg ring; reg [30:0] ring_clc; initial begin ring<=1; led<=0; cc<=0; dig<=8'b11111111; sel<=6'b111111; status<=0; //标记工作状态 cc_1<=0; cc_2<=0; cc_key_1<=0; cc_key_2<=0; cc_key_3<=0; cc_key_4<=0; cc_key_5<=0; temp_1<=0; temp_2<=0; temp_3<=0; temp_4<=0; temp_5<=0; key_sta_2<=0; num_pool[0]<=8'b11000000; num_pool[1]<=8'b11111001; num_pool[2]<=8'b10100100; num_pool[3]<=8'b10110000; num_pool[4]<=8'b10011001; num_pool[5]<=8'b10010010; num_pool[6]<=8'b10000010; num_pool[7]<=8'b11111000; num_pool[8]<=8'b10000000; num_pool[9]<=8'b10010000; num_pool_2[0]<=8'b01000000; num_pool_2[1]<=8'b01111001; num_pool_2[2]<=8'b00100100; num_pool_2[3]<=8'b00110000; num_pool_2[4]<=8'b00011001; num_pool_2[5]<=8'b00010010; num_pool_2[6]<=8'b00000010; num_pool_2[7]<=8'b01111000; num_pool_2[8]<=8'b00000000; num_pool_2[9]<=8'b00010000; num_value[0]<=720000; num_value[1]<=720000; num_value[2]<=720000; //最高位为5,此处整除6 num_value[3]<=720000; num_value[4]<=720000; num_value[5]<=720000; key_sta[0]<=11'b00000000000; key_sta[1]<=11'b00000000000; key_sta[2]<=11'b00000000000; key_sta[3]<=11'b00000000000; key_sta[4]<=11'b00000000000; num_posi<=360; //设置成6的整数倍 cc_3<=0; cc_31<=0; index[0]<=0; index[1]<=0; index[2]<=0; index[3]<=0; index[4]<=0; index[5]<=0; ring_clc<=0; end always @ (posedge in) begin if (status==0) begin if (cc_1==600) begin cc_1<=0; end else if ((0<=cc_1)&&(cc_1<100)) begin dig<=8'b11000000; sel<=6'b111110; cc_1<=cc_1+1; end else if ((100<=cc_1)&&(cc_1<200)) begin dig<=8'b11000000; sel<=6'b111101; cc_1<=cc_1+1; end else if ((200<=cc_1)&&(cc_1<300)) begin dig<=8'b11000000; sel<=6'b111011; cc_1<=cc_1+1; end else if ((300<=cc_1)&&(cc_1<400)) begin dig<=8'b11000000; sel<=6'b110111; cc_1<=cc_1+1; end else if ((400<=cc_1)&&(cc_1<500)) begin dig<=8'b11000000; sel<=6'b101111; cc_1<=cc_1+1; end else if ((500<=cc_1)&&(cc_1<600)) begin dig<=8'b11000000; sel<=6'b011111; cc_1<=cc_1+1; end if (key_sta[4]>key_sta_3[4]) begin key_sta_3[4]<=key_sta[4]; status<=1; end end else if (status==1) begin if (cc_2==6000) begin cc_2<=0; end else if ((0<=cc_2)&&(cc_2<1000)) begin if (num_posi%6==0) begin sel<=6'b111110; dig<=num_pool_2[num_value[0]%10]; if (key_sta_3[0]<key_sta[0]) begin key_sta_3[0]<=key_sta[0]; num_value[0]<=num_value[0]+1; end if (key_sta_3[1]<key_sta[1]) begin key_sta_3[1]<=key_sta[1]; num_value[0]<=num_value[0]-1; end if (key_sta_3[2]<key_sta[2]) begin key_sta_3[2]<=key_sta[2]; num_posi<=num_posi-1; end if (key_sta_3[3]<key_sta[3]) begin key_sta_3[3]<=key_sta[3]; num_posi<=num_posi+1; end end else begin dig<=num_pool[num_value[0]%10]; sel<=6'b111110; end cc_2<=cc_2+1; end else if ((1000<=cc_2)&&(cc_2<2000)) begin if (num_posi%6==1) begin sel<=6'b111101; dig<=num_pool_2[num_value[1]%10]; if (key_sta_3[0]<key_sta[0]) begin key_sta_3[0]<=key_sta[0]; num_value[1]<=num_value[1]+1; end if (key_sta_3[1]<key_sta[1]) begin key_sta_3[1]<=key_sta[1]; num_value[1]<=num_value[1]-1; end if (key_sta_3[2]<key_sta[2]) begin key_sta_3[2]<=key_sta[2]; num_posi<=num_posi-1; end if (key_sta_3[3]<key_sta[3]) begin key_sta_3[3]<=key_sta[3]; num_posi<=num_posi+1; end end else begin dig<=num_pool[num_value[1]%10]; sel<=6'b111101; end cc_2<=cc_2+1; end else if ((2000<=cc_2)&&(cc_2<3000)) begin if (num_posi%6==2) begin sel<=6'b111011; dig<=num_pool_2[num_value[2]%6]; if (key_sta_3[0]<key_sta[0]) begin key_sta_3[0]<=key_sta[0]; num_value[2]<=num_value[2]+1; end if (key_sta_3[1]<key_sta[1]) begin key_sta_3[1]<=key_sta[1]; num_value[2]<=num_value[2]-1; end if (key_sta_3[2]<key_sta[2]) begin key_sta_3[2]<=key_sta[2]; num_posi<=num_posi-1; end if (key_sta_3[3]<key_sta[3]) begin key_sta_3[3]<=key_sta[3]; num_posi<=num_posi+1; end end else begin dig<=num_pool[num_value[2]%6]; sel<=6'b111011; end cc_2<=cc_2+1; end else if ((3000<=cc_2)&&(cc_2<4000)) begin if (num_posi%6==3) begin sel<=6'b110111; dig<=num_pool_2[num_value[3]%10]; if (key_sta_3[0]<key_sta[0]) begin key_sta_3[0]<=key_sta[0]; num_value[3]<=num_value[3]+1; end if (key_sta_3[1]<key_sta[1]) begin key_sta_3[1]<=key_sta[1]; num_value[3]<=num_value[3]-1; end if (key_sta_3[2]<key_sta[2]) begin key_sta_3[2]<=key_sta[2]; num_posi<=num_posi-1; end if (key_sta_3[3]<key_sta[3]) begin key_sta_3[3]<=key_sta[3]; num_posi<=num_posi+1; end end else begin dig<=num_pool[num_value[3]%10]; sel<=6'b110111; end cc_2<=cc_2+1; end else if ((4000<=cc_2)&&(cc_2<5000)) begin if (num_posi%6==4) begin sel<=6'b101111; dig<=num_pool_2[num_value[4]%10]; if (key_sta_3[0]<key_sta[0]) begin key_sta_3[0]<=key_sta[0]; num_value[4]<=num_value[4]+1; end if (key_sta_3[1]<key_sta[1]) begin key_sta_3[1]<=key_sta[1]; num_value[4]<=num_value[4]-1; end if (key_sta_3[2]<key_sta[2]) begin key_sta_3[2]<=key_sta[2]; num_posi<=num_posi-1; end if (key_sta_3[3]<key_sta[3]) begin key_sta_3[3]<=key_sta[3]; num_posi<=num_posi+1; end end else begin dig<=num_pool[num_value[4]%10]; sel<=6'b101111; end cc_2<=cc_2+1; end else if ((5000<=cc_2)&&(cc_2<6000)) begin if (num_posi%6==5) begin sel<=6'b011111; dig<=num_pool_2[num_value[5]%10]; if (key_sta_3[0]<key_sta[0]) begin key_sta_3[0]<=key_sta[0]; num_value[5]<=num_value[5]+1; end if (key_sta_3[1]<key_sta[1]) begin key_sta_3[1]<=key_sta[1]; num_value[5]<=num_value[5]-1; end if (key_sta_3[2]<key_sta[2]) begin key_sta_3[2]<=key_sta[2]; num_posi<=num_posi-1; end if (key_sta_3[3]<key_sta[3]) begin key_sta_3[3]<=key_sta[3]; num_posi<=num_posi+1; end end else begin dig<=num_pool[num_value[5]%10]; sel<=6'b011111; end cc_2<=cc_2+1; end if (key_sta[4]>key_sta_3[4]) begin key_sta_3[4]<=key_sta[4]; status<=2; num_value_2[0]<=num_value[0]; num_value_2[1]<=num_value[1]; num_value_2[2]<=num_value[2]; num_value_2[3]<=num_value[3]; num_value_2[4]<=num_value[4]; num_value_2[5]<=num_value[5]; num_value_2_1[0]<=num_value[0]; num_value_2_1[1]<=num_value[1]; num_value_2_1[2]<=num_value[2]; num_value_2_1[3]<=num_value[3]; num_value_2_1[4]<=num_value[4]; num_value_2_1[5]<=num_value[5]; num_value_2_2[0]<=num_value[0]; num_value_2_2[1]<=num_value[1]; num_value_2_2[2]<=num_value[2]; num_value_2_2[3]<=num_value[3]; num_value_2_2[4]<=num_value[4]; num_value_2_2[5]<=num_value[5]; num_value_2_3[0]<=num_value[0]; num_value_2_3[1]<=num_value[1]; num_value_2_3[2]<=num_value[2]; num_value_2_3[3]<=num_value[3]; num_value_2_3[4]<=num_value[4]; num_value_2_3[5]<=num_value[5]; num_value_2_4[0]<=num_value[0]; num_value_2_4[1]<=num_value[1]; num_value_2_4[2]<=num_value[2]; num_value_2_4[3]<=num_value[3]; num_value_2_4[4]<=num_value[4]; num_value_2_4[5]<=num_value[5]; end end else if (status==2) begin if (cc_3==6000) begin cc_3<=0; cc_31<=cc_31+1; end else if ((0<=cc_3)&&(cc_3<1000)) begin dig<=num_pool[num_value[0]%10]; sel<=6'b111110; cc_3<=cc_3+1; end else if ((1000<=cc_3)&&(cc_3<2000)) begin dig<=num_pool[num_value[1]%10]; sel<=6'b111101; cc_3<=cc_3+1; end else if ((2000<=cc_3)&&(cc_3<3000)) begin dig<=num_pool[num_value[2]%6]; sel<=6'b111011; cc_3<=cc_3+1; end else if ((3000<=cc_3)&&(cc_3<4000)) begin dig<=num_pool[num_value[3]%10]; sel<=6'b110111; cc_3<=cc_3+1; end else if ((4000<=cc_3)&&(cc_3<5000)) begin dig<=num_pool[num_value[4]%10]; sel<=6'b101111; cc_3<=cc_3+1; end else if ((5000<=cc_3)&&(cc_3<6000)) begin cc_3<=cc_3+1; dig<=num_pool[num_value[5]%10]; sel<=6'b011111; end cc_31<=cc_31+1; //对百分秒进行控制 if (cc_31==500000) begin num_value[5]<=num_value[5]-1; cc_31<=0; index[1][0]<=1; index[2][0]<=1; index[3][0]<=1; index[4][0]<=1; index[5][0]<=1; end //对时分秒进行控制 if ((num_value[5]%10==9)&&(index[1][0]==1)) begin if (num_value_2[5]%10==9) begin num_value_2[5]<=0; end else begin num_value[4]<=num_value[4]-1; index[1][0]<=0; end index[2][1]<=1; index[3][1]<=1; index[4][1]<=1; index[5][1]<=1; end //对秒的个位数进行控制 if (((num_value[4]%10==9)&&(num_value[5]%10==9))&&((index[2][1]==1)&&(index[2][0]==1))) begin if ((num_value_2_1[5]%10==9)&&(num_value_2_1[4]%10==9)) begin num_value_2_1[5]<=0; num_value_2_1[4]<=0; end else begin num_value[3]<=num_value[3]-1; end index[2]<=0; index[3][2]<=1; index[4][2]<=1; index[5][2]<=1; end if ((num_value[3]%10==9)&&(num_value[4]%10==9)&&(num_value[5]%10==9)&& (index[3][0]==1)&&(index[3][1]==1)&&(index[3][2]==1)) begin if ((num_value_2_2[5]%10==9)&&(num_value_2_2[4]%10==9)&&(num_value_2_2[3]%10==9)) begin num_value_2_2[5]<=0; num_value_2_2[4]<=0; num_value_2_2[3]<=0; end else begin num_value[2]<=num_value[2]-1; index[3]<=0; end index[4][3]<=1; index[5][3]<=1; end if ((num_value[3]%10==9)&&(num_value[4]%10==9)&&(num_value[5]%10==9)&&(num_value[2]%6==5)&& (index[4][0]==1)&&(index[4][1]==1)&&(index[4][2]==1)&&(index[4][3]==1)) begin if ((num_value_2_3[5]%10==9)&&(num_value_2_3[4]%10==9)&&(num_value_2_3[3]%10==9)&&(num_value_2_3[2]%6==5)) begin num_value_2_3[5]<=0; num_value_2_3[4]<=0; num_value_2_3[3]<=0; num_value_2_3[2]<=0; end else begin num_value[1]<=num_value[1]-1; index[4]<=0; end; index[5][4]<=1; end if ((num_value[3]%10==9)&&(num_value[4]%10==9)&&(num_value[5]%10==9)&&(num_value[2]%6==5)&&(num_value[1]%10==9)&& (index[5][0]==1)&&(index[5][1]==1)&&(index[5][2]==1)&&(index[5][3]==1)&&(index[5][4]==1)) begin if ((num_value_2_4[5]%10==9)&&(num_value_2_4[4]%10==9)&&(num_value_2_4[3]%10==9)&&(num_value_2_4[2]%6==5)&&(num_value_2_4[1]%10==0)) begin num_value_2_4[5]<=0; num_value_2_4[4]<=0; num_value_2_4[3]<=0; num_value_2_4[2]<=0; num_value_2_4[1]<=0; end else begin num_value[0]<=num_value[0]-1; index[5]<=0; end end if ((num_value[3]%10==0)&&(num_value[4]%10==0)&&(num_value[5]%10==0)&&(num_value[2]%6==0)&& (num_value[1]%10==0)&&(num_value[0]%10==0)) begin status<=3; end end / else if (status==3) begin if(ring_clc==125000000) begin status<=4; end else begin ring<=0; ring_clc<=ring_clc+1; end sel<=6'b000000; dig<=8'b11111111; end else if (status==4) //设置一个状态用来对数据进行初始化 begin ring<=1; led<=0; dig<=8'b11111111; sel<=6'b111111; cc_1<=0; cc_2<=0; num_pool[0]<=8'b11000000; num_pool[1]<=8'b11111001; num_pool[2]<=8'b10100100; num_pool[3]<=8'b10110000; num_pool[4]<=8'b10011001; num_pool[5]<=8'b10010010; num_pool[6]<=8'b10000010; num_pool[7]<=8'b11111000; num_pool[8]<=8'b10000000; num_pool[9]<=8'b10010000; num_pool_2[0]<=8'b01000000; num_pool_2[1]<=8'b01111001; num_pool_2[2]<=8'b00100100; num_pool_2[3]<=8'b00110000; num_pool_2[4]<=8'b00011001; num_pool_2[5]<=8'b00010010; num_pool_2[6]<=8'b00000010; num_pool_2[7]<=8'b01111000; num_pool_2[8]<=8'b00000000; num_pool_2[9]<=8'b00010000; num_value[0]<=720000; num_value[1]<=720000; num_value[2]<=720000; //最高位为5,此处整除6 num_value[3]<=720000; num_value[4]<=720000; num_value[5]<=720000; num_posi<=360; //设置成6的整数倍 cc_3<=0; cc_31<=0; index[0]<=0; index[1]<=0; index[2]<=0; index[3]<=0; index[4]<=0; index[5]<=0; ring_clc<=0; num_value_2[0]<=0; num_value_2[1]<=0; num_value_2[2]<=0; num_value_2[3]<=0; num_value_2[4]<=0; num_value_2[5]<=0; num_value_2_1[0]<=0; num_value_2_1[1]<=0; num_value_2_1[2]<=0; num_value_2_1[3]<=0; num_value_2_1[4]<=0; num_value_2_1[5]<=0; num_value_2_2[0]<=0; num_value_2_2[1]<=0; num_value_2_2[2]<=0; num_value_2_2[3]<=0; num_value_2_2[4]<=0; num_value_2_2[5]<=0; num_value_2_2[0]<=0; num_value_2_2[1]<=0; num_value_2_2[2]<=0; num_value_2_2[3]<=0; num_value_2_2[4]<=0; num_value_2_2[5]<=0; num_value_2_2[0]<=0; num_value_2_2[1]<=0; num_value_2_2[2]<=0; num_value_2_2[3]<=0; num_value_2_2[4]<=0; num_value_2_2[5]<=0; status<=0; end end always @ (posedge in) //并行的按键检测运算 begin if (cc_key_1==500000) begin cc_key_1<=0; if (temp_1==0) begin if (key_sta_2[0]>0) begin key_sta[0]<=key_sta[0]+1; key_sta_2[0]<=0; temp_1<=0; end end else begin key_sta_2[0]<=1; temp_1<=0; end end else begin if (key[0] == 0) begin temp_1<=temp_1+1; end cc_key_1<=cc_key_1+1; end if (cc_key_2==500000) begin cc_key_2<=0; if (temp_2==0) begin if (key_sta_2[1]>0) begin key_sta[1]<=key_sta[1]+1; key_sta_2[1]<=0; temp_2<=0; end end else begin key_sta_2[1]<=1; temp_2<=0; end end else begin if (key[1] == 0) begin temp_2<=temp_2+1; end cc_key_2<=cc_key_2+1; end if (cc_key_3==500000) begin cc_key_3<=0; if (temp_3==0) begin if (key_sta_2[2]>0) begin key_sta[2]<=key_sta[2]+1; key_sta_2[2]<=0; temp_3<=0; end end else begin key_sta_2[2]<=1; temp_3<=0; end end else begin if (key[2] == 0) begin temp_3<=temp_3+1; end cc_key_3<=cc_key_3+1; end if (cc_key_4==500000) begin cc_key_4<=0; if (temp_4==0) begin if (key_sta_2[3]>0) begin key_sta[3]<=key_sta[3]+1; key_sta_2[3]<=0; temp_4<=0; end end else begin key_sta_2[3]<=1; temp_4<=0; end end else begin if (key[3] == 0) begin temp_4<=temp_4+1; end cc_key_4<=cc_key_4+1; end if (cc_key_5==500000) begin cc_key_5<=0; if (temp_5==0) begin if (key_sta_2[4]>0) begin key_sta[4]<=key_sta[4]+1; key_sta_2[4]<=0; temp_5<=0; end end else begin key_sta_2[4]<=1; temp_5<=0; end end else begin if (key[4] == 0) begin temp_5<=temp_5+1; end cc_key_5<=cc_key_5+1; end end endmodule
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。