EDA设计:计数器
本次主要介绍一下关于EDA的实验:计数器,包括模4计数器、模10计数器、模n计数器。
文章目录
前言
本次主要介绍一下关于EDA的实验:计数器,包括模4计数器、模10计数器、模n计数器。
一、设计内容及原理
(1)基础任务:设计一个4位二进制计数器,由发光二极管显示输出。
(2)拓展任务:设计一个模10的计数器,输出结果由数码管显示.。
(3)提高任务:设计一个模 N 的计数器,N 值可自己通过外部设定(通过外部设定N值,可以改变模值,模值由拨码开关设定,数码管显示), 模值和输出结果都由数码管显示。
二、设计过程(及设计步骤)
2.1 基础任务
(1)源程序:
module mod(rst,clk,led); //声明模块名,端口信号
input clk; //时钟
input rst; //清零端
output reg [2:0] led;
reg [31:0] sum;
reg clk1;
always@(posedge rst or posedge clk) //时钟分频
begin
if(!rst)
begin
sum<=0;
clk1<=0;
end
else if(sum==50000000) //分频50M次
begin
clk1<=~clk1; //时钟翻转
sum<=0; //sum清零
end
else
sum<=sum+1'b1; //sum累加直至50M
end
always@(posedge rst or posedge clk1) //模4计数器
begin
if(!rst)
led<=0;
else if(led==3) //当led为3时,立即清零
led<=0;
else
led<=led+1; //led累加计数,表示0到3
end
endmodule
(2)仿真程序:
module sim_mod;
reg rst;
reg clk;
wire[2:0] led;
mod u0( //实例化模4计数器
.rst(rst),
.led(led),
.clk(clk)
);
parameter PERIOD = 10; //参数声明,并赋值为10
always
begin //每隔5,时钟翻转一次
clk = 1'b0;
#(PERIOD/2) clk = 1'b1;
#(PERIOD/2);
end
initial
begin //对clk,rst进行赋值
clk = 1'b0;
rst = 1'b0;
#100;
rst = 1'b1;
end
endmodule
(3)约束程序:
set_property -dict {PACKAGE_PIN P17 IOSTANDARD LVCMOS33} [get_ports clk ]
set_property -dict {PACKAGE_PIN P15 IOSTANDARD LVCMOS33} [get_ports rst ]
set_property -dict {PACKAGE_PIN K2 IOSTANDARD LVCMOS33} [get_ports {led[0]}]
set_property -dict {PACKAGE_PIN J2 IOSTANDARD LVCMOS33} [get_ports {led[1]}]
set_property -dict {PACKAGE_PIN J3 IOSTANDARD LVCMOS33} [get_ports {led[2]}]
2.2 提高任务
(1)源程序:
module mod(rst,clk,wei,b); //声明模块名,端口信号
input clk; //时钟
input rst; //清零端
output reg wei=1'b1; //位选
output reg [7:0] b; //段选
reg [3:0] led;
reg [31:0] sum=0;
reg clk1=0;
always@(posedge rst or posedge clk) //时钟分频
begin
if(!rst)
begin
sum<=0;
clk1<=0;
end
else if(sum==50000000) //分频50M次
begin
clk1<=~clk1; //时钟翻转
sum<=0; //sum清零
end
else
sum<=sum+1'b1; //sum累加直至50M
end
always@(posedge rst or posedge clk1) //模10的计数器
begin
if(!rst)
led<=0;
else if(led==9) //当led为9时,立即清零
led<=0;
else
led<=led+1; //led累加计数,表示0到9
end
always@(led)
begin
case(led) //led输入不同的值时,对应数码管的输出
0:b=8'b11111100;
1:b=8'b01100000;
2:b=8'b11011010;
3:b=8'b11110010;
4:b=8'b01100110;
5:b=8'b10110110;
6:b=8'b10111110;
7:b=8'b11100000;
8:b=8'b11111110;
9:b=8'b11110110;
endcase
end
endmodule
(2)仿真程序:
module sim_mod;
reg rst;
reg clk;
wire[7:0] b;
modn u0( //实例化模10计数器
.rst(rst),
.b(b),
.clk(clk)
);
parameter PERIOD = 10; //参数声明,并赋值为10
always
begin //每隔5,时钟翻转一次
clk = 1'b0;
#(PERIOD/2) clk = 1'b1;
#(PERIOD/2);
end
initial
begin //对clk,rst进行赋值
clk = 1'b0;
rst = 1'b0;
#100;
rst = 1'b1;
end
endmodule
(3)约束程序:
set_property -dict {PACKAGE_PIN P17 IOSTANDARD LVCMOS33} [get_ports clk ]
set_property -dict {PACKAGE_PIN P15 IOSTANDARD LVCMOS33} [get_ports rst ]
set_property -dict {PACKAGE_PIN C1 IOSTANDARD LVCMOS33} [get_ports wei]
set_property -dict {PACKAGE_PIN B4 IOSTANDARD LVCMOS33} [get_ports {b[7]}]
set_property -dict {PACKAGE_PIN A4 IOSTANDARD LVCMOS33} [get_ports {b[6]}]
set_property -dict {PACKAGE_PIN A3 IOSTANDARD LVCMOS33} [get_ports {b[5]}]
set_property -dict {PACKAGE_PIN B1 IOSTANDARD LVCMOS33} [get_ports {b[4]}]
set_property -dict {PACKAGE_PIN A1 IOSTANDARD LVCMOS33} [get_ports {b[3]}]
set_property -dict {PACKAGE_PIN B3 IOSTANDARD LVCMOS33} [get_ports {b[2]}]
set_property -dict {PACKAGE_PIN B2 IOSTANDARD LVCMOS33} [get_ports {b[1]}]
set_property -dict {PACKAGE_PIN D5 IOSTANDARD LVCMOS33} [get_ports {b[0]}]
2.3 拓展任务
(1)源程序:
module mod(rst,clk,n,wei,wei1,led,b,a); //声明模块名,端口信号
input clk; //时钟
input rst; //清零端
input [3:0] n; //模的取值
output reg wei=1'b1; //位选
output reg wei1=1'b1; //位选
output reg [7:0] b; //段选,显示模
output reg [7:0] a; //段选,显示计数过程
output reg [3:0] led;
reg [31:0] sum=0;
reg clk1=0;
always@(*)
begin
case(n) //不同模的取值,对应数码管的显示
2:b=8'b11011010;
3:b=8'b11110010;
4:b=8'b01100110;
5:b=8'b10110110;
6:b=8'b10111110;
7:b=8'b11100000;
8:b=8'b11111110;
9:b=8'b11110110;
10:b=8'b11101110;
11:b=8'b00111110;
12:b=8'b10011100;
13:b=8'b01111010;
14:b=8'b10011110;
15:b=8'b10001110;
endcase
end
always@(posedge rst or posedge clk) //时钟分频
begin
if(!rst)
begin
sum<=0;
clk1<=0;
end
else if(sum==50000000) //分频50M次
begin
clk1<=~clk1; //时钟翻转
sum<=0; //sum清零
end
else
sum<=sum+1'b1; //sum累加直至50M
end
always@(posedge rst or posedge clk1) //模n计数器
begin
if(!rst)
led<=0;
else if(led==(n-1)) //当led为n-1时,立即清零
led<=0;
else
led<=led+1; //led累加计数,表示0到n-1
end
always@(led)
begin
case(led) //led输入不同的值时,对应数码管的输出
0:a=8'b11111100;
1:a=8'b01100000;
2:a=8'b11011010;
3:a=8'b11110010;
4:a=8'b01100110;
5:a=8'b10110110;
6:a=8'b10111110;
7:a=8'b11100000;
8:a=8'b11111110;
9:a=8'b11110110;
10:a=8'b11101110;
11:a=8'b00111110;
12:a=8'b10011100;
13:a=8'b01111010;
14:a=8'b10011110;
15:a=8'b10001110;
endcase
end
endmodule
(2)仿真程序:
module sim_mod;
reg rst;
reg clk;
reg [3:0] n;
wire[3:0] led;
wire[7:0] b;
wire[7:0] a;
mod u0( //实例化模n计数器
.rst(rst),
.clk(clk),
.n(n),
.led(led),
.b(b),
.a(a)
);
parameter PERIOD = 10; //参数声明,并赋值为10
always
begin //每隔5,时钟翻转一次
clk = 1'b0;
#(PERIOD/2) clk = 1'b1;
#(PERIOD/2);
end
initial
begin //不同n的取值对应的计数器
n=4'b0011; // 模3计数器
clk = 1'b0;
rst = 1'b0;
#100;
rst = 1'b1;
#100;
n=4'b0111; // 模7计数器
clk = 1'b0;
rst = 1'b0;
#100;
rst = 1'b1;
#100;
n=4'b1001; // 模9计数器
clk = 1'b0;
rst = 1'b0;
#100;
rst = 1'b1;
#100;
n=4'b1111; // 模15计数器
clk = 1'b0;
rst = 1'b0;
#100;
rst = 1'b1;
end
endmodule
(3)约束程序:
set_property -dict {PACKAGE_PIN P17 IOSTANDARD LVCMOS33} [get_ports clk ]
set_property -dict {PACKAGE_PIN P15 IOSTANDARD LVCMOS33} [get_ports rst ]
set_property -dict {PACKAGE_PIN R1 IOSTANDARD LVCMOS33} [get_ports {n[0]}]
set_property -dict {PACKAGE_PIN N4 IOSTANDARD LVCMOS33} [get_ports {n[1]}]
set_property -dict {PACKAGE_PIN M4 IOSTANDARD LVCMOS33} [get_ports {n[2]}]
set_property -dict {PACKAGE_PIN R2 IOSTANDARD LVCMOS33} [get_ports {n[3]}]
set_property -dict {PACKAGE_PIN K2 IOSTANDARD LVCMOS33} [get_ports {led[0]}]
set_property -dict {PACKAGE_PIN J2 IOSTANDARD LVCMOS33} [get_ports {led[1]}]
set_property -dict {PACKAGE_PIN J3 IOSTANDARD LVCMOS33} [get_ports {led[2]}]
set_property -dict {PACKAGE_PIN H4 IOSTANDARD LVCMOS33} [get_ports {led[3]}]
set_property -dict {PACKAGE_PIN H1 IOSTANDARD LVCMOS33} [get_ports wei]
set_property -dict {PACKAGE_PIN G1 IOSTANDARD LVCMOS33} [get_ports wei1]
set_property -dict {PACKAGE_PIN B4 IOSTANDARD LVCMOS33} [get_ports {b[7]}]
set_property -dict {PACKAGE_PIN A4 IOSTANDARD LVCMOS33} [get_ports {b[6]}]
set_property -dict {PACKAGE_PIN A3 IOSTANDARD LVCMOS33} [get_ports {b[5]}]
set_property -dict {PACKAGE_PIN B1 IOSTANDARD LVCMOS33} [get_ports {b[4]}]
set_property -dict {PACKAGE_PIN A1 IOSTANDARD LVCMOS33} [get_ports {b[3]}]
set_property -dict {PACKAGE_PIN B3 IOSTANDARD LVCMOS33} [get_ports {b[2]}]
set_property -dict {PACKAGE_PIN B2 IOSTANDARD LVCMOS33} [get_ports {b[1]}]
set_property -dict {PACKAGE_PIN D5 IOSTANDARD LVCMOS33} [get_ports {b[0]}]
set_property -dict {PACKAGE_PIN D4 IOSTANDARD LVCMOS33} [get_ports {a[7]}]
set_property -dict {PACKAGE_PIN E3 IOSTANDARD LVCMOS33} [get_ports {a[6]}]
set_property -dict {PACKAGE_PIN D3 IOSTANDARD LVCMOS33} [get_ports {a[5]}]
set_property -dict {PACKAGE_PIN F4 IOSTANDARD LVCMOS33} [get_ports {a[4]}]
set_property -dict {PACKAGE_PIN F3 IOSTANDARD LVCMOS33} [get_ports {a[3]}]
set_property -dict {PACKAGE_PIN E2 IOSTANDARD LVCMOS33} [get_ports {a[2]}]
set_property -dict {PACKAGE_PIN D2 IOSTANDARD LVCMOS33} [get_ports {a[1]}]
set_property -dict {PACKAGE_PIN H2 IOSTANDARD LVCMOS33} [get_ports {a[0]}]
三、仿真结果
3.1 基础任务(模4计数器)
结果分析:led对应亮起的灯。如图所示,100ns之前对应的是清零端起作用的情况,led恒为0。100ns之后对应的是模4计数器,有4种情况,000,001,010,011,依次进行循环。
3.2 提高任务(模10计数器)
结果分析:8位b对应亮起的数码管的数字。如图所示,100ns之前对应的是清零端起作用的情况,led恒为0。100ns之后对应的是模10计数器,有10种情况,从0到9,数字依次进行循环。
3.3 拓展任务(模n计数器)
结果分析:n对应不同模的取值,模n可取[2:15],b对应模n的显示,a对应计数过程中数字的变化过程。如图所示,仿真时,这里我模n分别取的是3,7,11,15。从上面红色框中可以看出led的变化过程。n=3时,led从0到2,数字依次进行循环; n=7时,led从0到6,数字依次进行循环; n=11时,led从0到10,数字依次进行循环; n=15时,led从0到14,数字依次进行循环。
四、 硬件验证
4.1 基础任务
结果分析:硬件仿真时, led依次显示000,001,010,011,和预期结果相符。上图是其中的两个过程,显示001,011。
4.2 提高任务
结果分析:硬件仿真时,数码管依次显示0到9。上图是其中的两个过程,数码管显示3,8。
4.3 拓展任务
结果分析:硬件仿真时,上图数码管的左边显示模的大小(n可取2到15),由拨码开关确定;上图数码管的右边,显示计数的过程。经过试验,和预期结果相符。上图是其中的两个过程:第一幅图:模取7时,数码管显示计数过程1;第二幅图:模取9时,数码管显示计数过程5。
五、 问题解决
1.问题:基础任务进行硬件仿真时,没有显示错误,但是没有现象。
解决办法:需要添加时钟分频,确保每经过一定时间后,计数过程进行一次变化,也就是led变化一次。
2.问题:编写模n的仿真文件时,添加的n每隔一定时间,n=n+1’b1,但是仿真出来的现象和预期不符。
解决办法:我选取模n为3,7,9,11的时候,进行仿真计数,同时为了观察方便,我在每一段计数过程前添加了一段清零端作用(led恒为0)的时候。
3.问题:做提高任务时,仿真结果计数过程循环亮,但是显示模值的数码管没有显示
解决办法:经检查约束文件,发现是定义两位位选(wei,wei1)时,只连接了wei1,忘记定义wei对应连接的管脚了。
六、 心得体会
在进行本次实验时,我一开始是按照书上的程序进行编写基础任务的,编写仿真文件时,在#10后的程序总是灰色的,而且仿真出来的结果总是恒定的红线或者蓝线。由于仿真程序中//是注释符,约束程序中的#是注释符,我从这一点发现了端倪,发现是将仿真程序放到了约束文件中,真是太崩溃了。
后来软件仿真成功后,和预期结果相符,硬件仿真时也没有错误,但是就是没有实验现象。后来查阅资料,发现是时钟的频率太高,为100Mhz,led进行循环时,人眼的分辨能力有限,无法识别,需要进行时钟分频。
做提高任务时,和基础任务没有什么区别,只是将输出由led变为了数码管,然后将模4计数变成了模10计数。
最后做扩展任务时,设计源文件时遇到了很大的困难,不知道如何改变模,不知道如何同时显示两位不同数码管的输出等等。经过一番努力,发现n是由拨码开关确定的,用一个case语句,将n对应的模值输出到数码管上。确定n后,开始对应的计数,然后将计数的过程输出到数码管上。这里,表示两位不同数码管的显示时,我用了两组数码管分别表示模的大小以及计数的过程,最后成功做出来了,真是太不容易了。
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)