verilog八位十进制计数器实验报告附源代码Word格式.docx
《verilog八位十进制计数器实验报告附源代码Word格式.docx》由会员分享,可在线阅读,更多相关《verilog八位十进制计数器实验报告附源代码Word格式.docx(12页珍藏版)》请在冰豆网上搜索。
仿真结果:
当输入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)
else
=cnt_div+26'
b1;
end
always@(posedgeclkorposedgerst)
begin
if(rst)
cnt<
=1'
elseif(cnt_div==26'
else
end
endmodule
cnt.v模块:
modulecnt(
inputWE,
inputcnt,
outputreg[3:
0]dnum,
0]num
always@(posedgeclk)
begin
dnum<
=4'
h9;
num<
h0;
end
elseif(WE&
&
cnt)
if(num==4'
h9)
num<
if(dnum==4'
dnum<
=dnum+4'
h1;
else
=num+4'
scan.v模块:
modulescan(
outputregscan_sgn
reg[16:
0]scan_cnt;
initialscan_sgn=0;
initialscan_cnt=0;
if(scan_cnt==17'
d99_999)
scan_cnt<
=17'
d0;
=scan_cnt+17'
scan_sgn<
display.v模块:
moduledisplay(
inputscan_sgn,
input[3:
0]num,
outputreg[7:
0]seg,
0]sel
rega=0;
//initiala=0;
always@(posedgescan_sgn)
if(a==1'
b0)
a=1'
sel=4'
b1101;
case(dnum)
4'
h0:
seg=8'
b0000_0011;
h1:
b1001_1111;
h2:
b0010_0101;
h3:
b0000_1101;
h4:
b1001_1001;
h5:
b0100_1001;
h6:
b0100_0001;
h7:
b0001_1111;
h8:
b0000_0001;
default:
b0000_1001;
endcase
b1110;
case(num)
endcase
top模块:
moduletop(
output[7:
output[3:
0]sel,
wire[3:
0]dnum;
0]num;
wirecnt;
wirescan_sgn;
divu_div(
.clk(clk),
.rst(rst),
.cnt(cnt)
);
cntu_cnt(
.WE(WE),
.cnt(cnt),
.dnum(dnum),
.num(num)
scanu_scan(
.scan_sgn(scan_sgn)
displayu_display(
.sel(sel),
.seg(seg),
.num(num),
ucf文件:
Net"
seg<
7>
"
LOC=T17;
6>
LOC=T18;
5>
LOC=U17;
4>
LOC=U18;
3>
LOC=M14;
2>
LOC=N14;
1>
LOC=L14;
0>
LOC=M13;
sel<
LOC=N16;
LOC=N15;
LOC=P18;
LOC=P17;
NET"
WE"
LOC=T9;
rst"
LOC=T10;
clk"
LOC=V10;
num<
LOC=U16;
LOC=V16;
LOC=U15;
LOC=V15;
dnum<
LOC=M11;
LOC=N11;
LOC=R11;
LOC=T11;
仿真代码:
moduletest5;
//Inputs
regclk;
regrst;
regWE;
//Outputs
wire[7:
0]seg;
wire[3:
0]sel;
//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;
対本实验的总结和体会;
1、要仿真正确是烧写的前提,先仿真正确再烧写
2、要给每个模块定义的变量一个initial语句,否则在仿真中会出现变量的值未定义的xxxx的情形
3、实验时仿真一直出现的一个问题是没有写initial语句,导致各个模块的中间变量没有初值,而很多输出变量的变化条件都是根据中间变量的上升沿河下降沿来触发的,这样中间变量即使有值也不会产生电平变化,导致仿真时输出没有变化(虽然烧写到板子上没有问题)
4、理解了仿真的原理是将整个project当成一个黑匣子,在isim的仿真程序中需要写语句模拟整个project的输入信号比如clk(用forever语句),rst和WE变量(在程序中赋值)
5、为了能使仿真时各个变量异步的变化,比如在时钟变化的过程中使rst等其他输入变量变化,但是initial语句又是顺序执行的,此时可以写多个initial语句来并行得是变量变化。