verilog八位十进制计数器实验报告附源代码.docx
《verilog八位十进制计数器实验报告附源代码.docx》由会员分享,可在线阅读,更多相关《verilog八位十进制计数器实验报告附源代码.docx(13页珍藏版)》请在冰点文库上搜索。
verilog八位十进制计数器实验报告附源代码
8位10进制计数器实验报告
一、实验目的
●学习时序逻辑电路
●学会用verilog语言设计时序逻辑电路
●掌握计数器的电路结构
●掌握数码管动态扫描显示原理
二、实验内容
实现一个8bit十进制(BCD码)计数器
端口设置:
用拨动开关实现复位和使能
LED灯来表示8位数据
用数码管显示16进制的八位数据
1.复位时计数值为8‘h0
2.复位后,计数器实现累加操作,步长为1,逢9进1,,计数值达到8‘h99后,从0开始继续计数
3.使能信号为1时正常计数,为0时暂停计数,为1时可继续计数。
4.每0.5s计数值加1
5.8位的结果显示在LED灯上,其中LED灯亮表示对应的位为1,LED灯灭表示对应的灯为0
6.用isim进行仿真,用forever语句模拟时钟信号输入,并给变量赋值仿真initial语句。
7.用7段数码管的后两位显示16进制下8位结果。
三、实验结果
烧写结果:
拨动reset开关到1时,LED灯显示10010000,7段数码管显示“90”。
之后拨动WE开关呢,开始计数,LED开始变化并且7段数码管开始计数。
从99后到达00,LED重新开始从00000000开始亮,且数码管重新从00开始计数。
之后拨动WE开关,暂停计数,LED暂停亮灭,七段数码管暂停变化,WE拨回1,继续计数。
拨动复位信号时,无视WE信号,直接复位。
仿真结果:
当输入reset信号时波形变化如下
当达到一个扫描信号的周期时的波形如下
当达到一个以上计数信号的周期时的波形
实验分析:
实验总体结构和模块间关系如图所示:
(其中还需要补上使能信号)
实验原理:
由于要求实现数码管和LED灯的显示,先考虑LED灯,可以直接由8位输出信号控制,而数码管需要同时显示两个不同的数字,需要时分复用,即快速的交替显示十位和个位,利用人眼的视觉暂留来达到同时显示。
这样就需要两种不同的频率信号。
一种是每0.5s一次,作为计数信号,用脉冲生成器生成,另一种是1ms一次的扫描信号,用降频器生成,将计数信号输入计数器来计数,并将计数的值和扫描信号同时输入扫描显示模块。
在扫描显示模块里用一个变量值在0和1间交替来指导选择信号选择数码管的不位数。
交替的条件是收到扫描信号。
7段数码管和LED灯都与计数值的变量相连即可实现。
实现细节
1.首先写一个脉冲生成器(div.v),每0.5s输出一次计数脉冲cnt
2.写一个计数器(cnt.v)设置一个8位计数变量,分成两个4位变量dnum(十位)和num(个位)。
如果接受到rst信号,则将计数变量置成x90.否则每次接受到计数信号,将计数变量的值增1,(同时考虑进位和回到x00的情况)
3.写一个扫描信号生成器(scan.v),每1ms生成一次扫描信号
4.写一个显示器(display.v),设置对数码管位数的4位选择信号sel和led灯的控制变量dnum(高4位)和num(低四位)。
设置seg作为7段数码管的控制变量。
设置一个中间变量a(初值0),如果接受到scan信号,将a0变1或1变0.如果a为0,sel为x1101,显示数码管十位,如果a为1,sel为x1110,显示数码管个位。
5.以上各个模块均由时钟信号控制。
6.写一个top模块综合以上模块。
附录(源代码):
Div.v模块:
modulediv(
inputclk,
inputrst,
outputregcnt
);
reg[25:
0]cnt_div;
always@(posedgeclkorposedgerst)
begin
if(rst)
cnt_div<=26'b0;
elseif(cnt_div==26'd49_999_999)
cnt_div<=26'b0;
else
cnt_div<=cnt_div+26'b1;
end
always@(posedgeclkorposedgerst)
begin
if(rst)
cnt<=1'b0;
elseif(cnt_div==26'd49_999_999)
cnt<=1'b1;
else
cnt<=1'b0;
end
endmodule
cnt.v模块:
modulecnt(
inputclk,
inputWE,
inputrst,
inputcnt,
outputreg[3:
0]dnum,
outputreg[3:
0]num
);
always@(posedgeclk)
begin
if(rst)
begin
dnum<=4'h9;
num<=4'h0;
end
elseif(WE&&cnt)
begin
if(num==4'h9)
begin
num<=4'h0;
if(dnum==4'h9)
dnum<=4'h0;
else
dnum<=dnum+4'h1;
end
else
num<=num+4'h1;
end
end
endmodule
scan.v模块:
modulescan(
inputclk,
outputregscan_sgn
);
reg[16:
0]scan_cnt;
initialscan_sgn=0;
initialscan_cnt=0;
always@(posedgeclk)
begin
if(scan_cnt==17'd99_999)
scan_cnt<=17'd0;
else
scan_cnt<=scan_cnt+17'b1;
end
always@(posedgeclk)
begin
if(scan_cnt==17'd99_999)
scan_sgn<=1'b1;
else
scan_sgn<=1'b0;
end
endmodule
display.v模块:
moduledisplay(
inputclk,
inputscan_sgn,
input[3:
0]num,
input[3:
0]dnum,
outputreg[7:
0]seg,
outputreg[3:
0]sel
);
rega=0;
//initiala=0;
always@(posedgescan_sgn)
begin
if(a==1'b0)
a=1'b1;
else
a=1'b0;
end
always@(posedgeclk)
begin
if(a==1'b0)
begin
sel=4'b1101;
case(dnum)
4'h0:
seg=8'b0000_0011;
4'h1:
seg=8'b1001_1111;
4'h2:
seg=8'b0010_0101;
4'h3:
seg=8'b0000_1101;
4'h4:
seg=8'b1001_1001;
4'h5:
seg=8'b0100_1001;
4'h6:
seg=8'b0100_0001;
4'h7:
seg=8'b0001_1111;
4'h8:
seg=8'b0000_0001;
default:
seg=8'b0000_1001;
endcase
end
else
begin
sel=4'b1110;
case(num)
4'h0:
seg=8'b0000_0011;
4'h1:
seg=8'b1001_1111;
4'h2:
seg=8'b0010_0101;
4'h3:
seg=8'b0000_1101;
4'h4:
seg=8'b1001_1001;
4'h5:
seg=8'b0100_1001;
4'h6:
seg=8'b0100_0001;
4'h7:
seg=8'b0001_1111;
4'h8:
seg=8'b0000_0001;
default:
seg=8'b0000_1001;
endcase
end
end
endmodule
top模块:
moduletop(
inputclk,
inputrst,
inputWE,
output[7:
0]seg,
output[3:
0]sel,
output[3:
0]dnum,
output[3:
0]num
);
wire[3:
0]dnum;
wire[3:
0]num;
wirecnt;
wirescan_sgn;
divu_div(
.clk(clk),
.rst(rst),
.cnt(cnt)
);
cntu_cnt(
.clk(clk),
.rst(rst),
.WE(WE),
.cnt(cnt),
.dnum(dnum),
.num(num)
);
scanu_scan(
.clk(clk),
.scan_sgn(scan_sgn)
);
displayu_display(
.clk(clk),
.sel(sel),
.seg(seg),
.dnum(dnum),
.num(num),
.scan_sgn(scan_sgn)
);
endmodule
ucf文件:
Net"seg<7>"LOC=T17;
Net"seg<6>"LOC=T18;
Net"seg<5>"LOC=U17;
Net"seg<4>"LOC=U18;
Net"seg<3>"LOC=M14;
Net"seg<2>"LOC=N14;
Net"seg<1>"LOC=L14;
Net"seg<0>"LOC=M13;
Net"sel<0>"LOC=N16;
Net"sel<1>"LOC=N15;
Net"sel<2>"LOC=P18;
Net"sel<3>"LOC=P17;
NET"WE"LOC=T9;
NET"rst"LOC=T10;
NET"clk"LOC=V10;
Net"num<0>"LOC=U16;
Net"num<1>"LOC=V16;
Net"num<2>"LOC=U15;
Net"num<3>"LOC=V15;
Net"dnum<0>"LOC=M11;
Net"dnum<1>"LOC=N11;
Net"dnum<2>"LOC=R11;
Net"dnum<3>"LOC=T11;
仿真代码:
moduletest5;
//Inputs
regclk;
regrst;
regWE;
//Outputs
wire[7:
0]seg;
wire[3:
0]sel;
wire[3:
0]dnum;
wire[3:
0]num;
//InstantiatetheUnitUnderTest(UUT)
topuut(
.clk(clk),
.rst(rst),
.WE(WE),
.seg(seg),
.sel(sel),
.dnum(dnum),
.num(num)
);
initialbegin
clk=0;
#100;
WE=1;
rst=1;
#10;
rst=0;
end
always#1clk=~clk;
endmodule
対本实验的总结和体会;
1、要仿真正确是烧写的前提,先仿真正确再烧写
2、要给每个模块定义的变量一个initial语句,否则在仿真中会出现变量的值未定义的xxxx的情形
3、实验时仿真一直出现的一个问题是没有写initial语句,导致各个模块的中间变量没有初值,而很多输出变量的变化条件都是根据中间变量的上升沿河下降沿来触发的,这样中间变量即使有值也不会产生电平变化,导致仿真时输出没有变化(虽然烧写到板子上没有问题)
4、理解了仿真的原理是将整个project当成一个黑匣子,在isim的仿真程序中需要写语句模拟整个project的输入信号比如clk(用forever语句),rst和WE变量(在程序中赋值)
5、为了能使仿真时各个变量异步的变化,比如在时钟变化的过程中使rst等其他输入变量变化,但是initial语句又是顺序执行的,此时可以写多个initial语句来并行得是变量变化。
6、