1、verilog计数器实验报告计数器1、实现目标及介绍实验实现了一个简易的计数器,计数范围可达899(0899),通过key4按键计数,每按下一次,计数加一,百位数显示在led上,个位与十位显示在数码管上。为十进制计数,数码管1计数到九后置零。数码管2获得进位加一,数码管2到9后当再次获得个位进位时再次向百位进一,点亮led1,每百位点亮一个led。此外key4为清零键,可随时按键清零。2、效果展示 计数99清零计数100视频展示(双击观看)3、代码实现与模块分析1.顶层模块 module jishuqi(input wire clk,rst, /时钟和复位输入input wire key1,
2、/拨码计output wire 7:0led,output wire 8:0 segment_led_1,segment_led_2 /数码管输出); wire key_pulse;reg 7:0 cnt; /计时计数器reg 7:0 hud; /百位计数initial hud7:0 = 8b11111111; always (posedge clk or negedge rst) begin /数码管显示要按照十进制的方式显示 if(!rst) begin cnt = 8h00; hud 7:0 = 8b11111111; end else if(key_pulse) begin if(cn
3、t3:0 = 4d9) /个位进位判断 begin cnt3:0 = 4d0; if(cnt7:4 = 4d9 ) /十位进位判断 begin cnt7:4 = 4d0; hud7:0 = hud7:0 - 1b1; end else cnt7:4 = cnt7:4 + 1b1; end else cnt3:0 = cnt3:0 + 1b1; end else cnt = cnt; endassign led = hud;/例化调用数码管显示模块 segment u2(.seg_data_1 (cnt7:4), /g_data input.seg_data_2 (cnt3:0), /g_dat
4、a input.seg_led_1 (segment_led_1), /MSBLSB = SEG,DP,G,F,E,D,C,B,A.seg_led_2 (segment_led_2) /MSBLSB = SEG,DP,G,F,E,D,C,B,A);/例化调用消抖模块debounce u1 ( .clk (clk), .rst (rst), .key (key1), .key_pulse (key_pulse) ); endmodule 2.数码管显示模块module segment (seg_data_1,seg_data_2,seg_led_1,seg_led_2); input 3:0 s
5、eg_data_1;/数码管需要显示09十个数字,所以最少需要4位输入做译码 input 3:0 seg_data_2; /小脚丫上第二个数码管 output 8:0 seg_led_1;/在小脚丫上控制一个数码管需要9个信号 MSBLSB=DIG、DP、G、F、E、D、C、B、A output 8:0 seg_led_2;/在小脚丫上第二个数码管的控制信号 MSBLSB=DIG、DP、G、F、E、D、C、B、A reg 8:0 seg 9:0; /定义了一个reg型的数组变量,相当于一个10*9的存储器,存储器一共有10个数,每个数有9位宽 initial /在过程块中只能给reg型变量赋值
6、,Verilog中有两种过程块always和initial /initial和always不同,其中语句只执行一次 begin seg0 = 9h3f; /对存储器中第一个数赋值9b00_0011_1111,相当于共阴极接地,DP点变低不亮,7段显示数字 0 seg1 = 9h06; /7段显示数字 1 seg2 = 9h5b; /7段显示数字 2 seg3 = 9h4f; /7段显示数字 3 seg4 = 9h66; /7段显示数字 4 seg5 = 9h6d; /7段显示数字 5 seg6 = 9h7d; /7段显示数字 6 seg7 = 9h07; /7段显示数字 7 seg8 = 9h
7、7f; /7段显示数字 8 seg9 = 9h6f; /7段显示数字 9 end assign seg_led_1 = segseg_data_1; /连续赋值,这样输入不同四位数,就能输出对于译码的9位输出 assign seg_led_2 = segseg_data_2; endmodule3.按键消抖模块/按键消抖module debounce (clk,rst,key,key_pulse); parameter N = 2; /要消除的按键的数量 input clk; input rst; input N-1:0 key; /输入的按键 output N-1:0 key_pulse;
8、/按键动作产生的脉冲 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 = N1b1; /初始化时给key_rst赋值全为1,中表示N个1 key_rst_pre = N1b1; en
9、d 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,要延
10、时20ms左右时间,至少需要18位计数器 /产生20ms延时,当检测到key_edge有效是计数器清零开始计数 always (posedge clk or negedge rst) begin if(!rst) cnt = 18h0; else if(key_edge) cnt = 18h0; else cnt = cnt + 1h1; end reg N-1:0 key_sec_pre; /延时后检测电平寄存器变量 reg N-1:0 key_sec; /延时后检测key,如果按键状态变低产生一个时钟的高脉冲。如果按键状态是高的话说明按键无效 always (posedge clk or
11、negedge rst) begin if (!rst) key_sec = N1b1; else if (cnt=18h3ffff) key_sec = key; end always (posedge clk or negedge rst) begin if (!rst) key_sec_pre = N1b1; else key_sec_pre = key_sec; end assign key_pulse = key_sec_pre & (key_sec); endmodule4、源码与源码图片module jishuqi(input wire clk,rst, /时钟和复位输入inpu
12、t wire key1, /拨码计output wire 7:0led,output wire 8:0 segment_led_1,segment_led_2 /数码管输出); wire key_pulse;reg 7:0 cnt; /计时计数器reg 7:0 hud; /百位计数initial hud7:0 = 8b11111111; always (posedge clk or negedge rst) begin /数码管显示要按照十进制的方式显示 if(!rst) begin cnt = 8h00; hud 7:0 = 8b11111111; end else if(key_pulse
13、) begin if(cnt3:0 = 4d9) begin cnt3:0 = 4d0; if(cnt7:4 = 4d9 ) begin cnt7:4 = 4d0; hud7:0 = hud7:0 - 1b1; end else cnt7:4 = cnt7:4 + 1b1; end else cnt3:0 = cnt3:0 + 1b1; end else cnt = cnt; endassign led = hud; segment u2(.seg_data_1 (cnt7:4), /g_data input.seg_data_2 (cnt3:0), /g_data input.seg_led
14、_1 (segment_led_1), /MSBLSB = SEG,DP,G,F,E,D,C,B,A.seg_led_2 (segment_led_2) /MSBLSB = SEG,DP,G,F,E,D,C,B,A);debounce u1 ( .clk (clk), .rst (rst), .key (key1), .key_pulse (key_pulse) ); endmodule/按键消抖module debounce (clk,rst,key,key_pulse); parameter N = 2; /要消除的按键的数量 input clk; input rst; input N-1
15、: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 = N1b1; /初始化时给key
16、_rst赋值全为1,中表示N个1 key_rst_pre = N1b1; 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产生一个时钟周期的高电平
17、 reg 17:0 cnt; /产生延时所用的计数器,系统时钟12MHz,要延时20ms左右时间,至少需要18位计数器 /产生20ms延时,当检测到key_edge有效是计数器清零开始计数 always (posedge clk or negedge rst) begin if(!rst) cnt = 18h0; else if(key_edge) cnt = 18h0; else cnt = cnt + 1h1; end reg N-1:0 key_sec_pre; /延时后检测电平寄存器变量 reg N-1:0 key_sec; /延时后检测key,如果按键状态变低产生一个时钟的高脉冲。如
18、果按键状态是高的话说明按键无效 always (posedge clk or negedge rst) begin if (!rst) key_sec = N1b1; else if (cnt=18h3ffff) key_sec = key; end always (posedge clk or negedge rst) begin if (!rst) key_sec_pre = N1b1; else key_sec_pre = key_sec; end assign key_pulse = key_sec_pre & (key_sec); endmodulemodule segment (s
19、eg_data_1,seg_data_2,seg_led_1,seg_led_2); input 3:0 seg_data_1;/数码管需要显示09十个数字,所以最少需要4位输入做译码 input 3:0 seg_data_2; /小脚丫上第二个数码管 output 8:0 seg_led_1;/在小脚丫上控制一个数码管需要9个信号 MSBLSB=DIG、DP、G、F、E、D、C、B、A output 8:0 seg_led_2;/在小脚丫上第二个数码管的控制信号 MSBLSB=DIG、DP、G、F、E、D、C、B、A reg 8:0 seg 9:0; /定义了一个reg型的数组变量,相当于一
20、个10*9的存储器,存储器一共有10个数,每个数有9位宽 initial /在过程块中只能给reg型变量赋值,Verilog中有两种过程块always和initial /initial和always不同,其中语句只执行一次 begin seg0 = 9h3f; /对存储器中第一个数赋值9b00_0011_1111,相当于共阴极接地,DP点变低不亮,7段显示数字 0 seg1 = 9h06; /7段显示数字 1 seg2 = 9h5b; /7段显示数字 2 seg3 = 9h4f; /7段显示数字 3 seg4 = 9h66; /7段显示数字 4 seg5 = 9h6d; /7段显示数字 5 seg6 = 9h7d; /7段显示数字 6 seg7 = 9h07; /7段显示数字 7 seg8 = 9h7f; /7段显示数字 8 seg9 = 9h6f; /7段显示数字 9 end assign seg_led_1 = segseg_data_1; /连续赋值,这样输入不同四位数,就能输出对于译码的9位输出 assign seg_led_2 = segseg_data_2; endmodule
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1