概述
一、实验任务
设计一个计数器,计数器每个时钟信号变化一次计数值,从 0 到 M 循环计数,M 是随着计数循环次数发生循环变化,第一次是 7,第二次是 8,第三次是 9,第四次是 7,第五次是 8,… 以此类推。例如,一个完整的计数循环为
二、实验设备
terasic DE0
quartus II 9.1
三、实验过程
本实验共采用两种方法来实现0~M循环计数。
方法一的设计思路是把一个完整的循环“0 … 7 0 … 8 0 … 9”这27个数写成一个周期,用always不断循环这一个周期。整个设计包括时钟模块(clk module)、循环条件模块(CycleCondition module)以及7段译码器输出模块(cycle789)共三个模块。
“时钟模块”主要进行分频,输出CLK1频率为10HZ,OV频率为1HZ。其中CLK1用于SignalTap的时钟驱动,OV用于使能循环条件模块。当OV为1时使能循环条件模块,当OV为0时循环不执行。“循环条件模块”用于循环产生0-26这27个数。“7段译码器输出模块”用于输出一个完整循环中的27个数字分别对应的7段译码管逻辑值。
(1)三个模块的代码如下
//时钟模块
module clk(
CLK , //system clock,50MHZ(开发板本身的时钟)
CNTVAL, //进行从0到50_000_000的累加,当CNTVAL=50_000_000时,OV=1
CNT, //进行从0到5000_000的累加,当CNT=5000_000时,CLK1=1
OV , //1Hz输出
CLK1); //10HZ输出
input CLK;
output [32-1:0] CNTVAL;
output [32-1:0] CNT;
output OV;
output CLK1;
parameter MAX_VAL = 50_000_000;
parameter MAX = 5000_000;
reg [32-1:0] CNTVAL;
reg [32-1:0] CNT;
reg OV;
reg CLK1;
//分频,生成10HZ
always @(posedge CLK) begin
if(CNT >= MAX)
CNT <= 0;
else
CNT <= CNT + 1'b1;
end
always @(CNT) begin
if (CNT == MAX)
CLK1 = 1'b1;
else
CLK1 = 1'b0;
end
//分频,生成1HZ
always @ (posedge CLK) begin
if(CNTVAL >= MAX_VAL)
CNTVAL <= 0;
else
CNTVAL <= CNTVAL + 1'b1;
end
always @ (CNTVAL) begin
if(CNTVAL == MAX_VAL)
OV = 1'b1;
else
OV = 1'b0;
endendmodule
//循环条件模块
module CycleCondition(
CLK , // clock
CNTVAL, // counter value
EN ); //连接时钟模块的OV(1HZ输出),使数字以1HZ的频率进行变化
input CLK;
input EN;
output [5-1:0] CNTVAL;
reg [5-1:0] CNTVAL;
reg OV;
always @ (posedge CLK) begin
if(EN) begin // work enable
if(CNTVAL >= 26)
CNTVAL <= 0;
else
CNTVAL <= CNTVAL + 1'b1;
end
else
CNTVAL <= CNTVAL ;
endendmodule
//7段译码器输出模块
module cycle789(
IN, //连接CNTVAL(CountValue),输入0-26
OUT); //译码管输出
input [5-1:0]IN;
output [7-1:0] OUT;
reg [7-1:0] OUT;
always @(IN)begin
case(IN)
5'b 00000: OUT = 7'b 1000000;
5'b 00001: OUT = 7'b 1111001;
5'b 00010: OUT = 7'b 0100100;
5'b 00011: OUT = 7'b 0110000;
5'b 00100: OUT = 7'b 0011001;
5'b 00101: OUT = 7'b 0010010;
5'b 00110: OUT = 7'b 0000010;
5'b 00111: OUT = 7'b 1111000;
5'b 01000: OUT = 7'b 1000000;
5'b 01001: OUT = 7'b 1111001;
5'b 01010: OUT = 7'b 0100100;
5'b 01011: OUT = 7'b 0110000;
5'b 01100: OUT = 7'b 0011001;
5'b 01101: OUT = 7'b 0010010;
5'b 01110: OUT = 7'b 0000010;
5'b 01111: OUT = 7'b 1111000;
5'b 10000: OUT = 7'b 0000000;
5'b 10001: OUT = 7'b 1000000;
5'b 10010: OUT = 7'b 1111001;
5'b 10011: OUT = 7'b 0100100;
5'b 10100: OUT = 7'b 0110000;
5'b 10101: OUT = 7'b 0011001;
5'b 10110: OUT = 7'b 0010010;
5'b 10111: OUT = 7'b 0000010;
5'b 11000: OUT = 7'b 1111000;
5'b 11001: OUT = 7'b 0000000;
5'b 11010: OUT = 7'b 0010000;
endcase
end
endmodule
(2)BDF原理图
(3)RTL视图
(4)VWM波形仿真
VWM波形仿真显示的是CycleCondition模块的输出,可以看到一个完整循环“0…7 0…8 0…9”27个值的累计变化。
(5)SignalTap抓取波形
在用SignalTap抓取波形时,时钟选择CLK1(即时钟模块所分频出的10Hz时钟),采样深度设为512,选择“单次抓取波形”。在上图可以看到SignalTap抓取的波形结果,图中用Time bar标出了0 ~ 7,0 ~ 8,0 ~ 9各段波形,其中[-68,270]表示了一个完整循环“0…7 0…8 0…9”。
方法二的设计思路是设置三个状态00→01→10,并使这三个状态不断循环。当状态为00时计数器从0计数到7,当状态为01时计数器从0计数到8,当状态为10时计数器从0计数到9。整个设计包括时钟模块(clk module)、循环条件模块(CycleCondition module)以及7段译码器输出模块(cycle789)共三个模块。时钟模块和方法一一样,这里不再赘述。“循环条件模块”用于循环产生0…7 0…8 0…9这27个数。7段译码器输出模块用于把循环模块产生的27个数转化成对应译码器的逻辑值。
(1)循环条件模块和译码器模块代码如下
module CycleCondition(
CLK, //System Clock,50MHZ
IN, //三个状态,00,01,10
CNT, //count value
EN //连接时钟模块的OV(1HZ输出),使数字以1HZ的频率进行变化
);
input CLK;
input EN;
output [1:0]IN;
output [4-1:0] CNT;
parameter CNT1=7;
parameter CNT2=8;
parameter CNT3=9;
reg [1:0] IN;
reg [4-1:0] CNT;
always @(posedge CLK)begin
if(EN)begin
if(IN == 2'b00)begin
if(CNT >= CNT1)begin
CNT <= 4'b0000;
IN <= 2'b01;
end
else begin
CNT <= CNT + 1'b1;
IN <= IN;
end
end
else if(IN == 2'b01)begin
if(CNT >= CNT2)begin
CNT <= 4'b0000;
IN <= 2'b10;
end
else begin
CNT <= CNT + 1'b1;
IN <= IN ;
end
end
else if(IN == 2'b10)begin
if(CNT >= CNT3)begin
CNT <= 4'b0000;
IN <= 2'b00;
end
else begin
CNT <= CNT + 2'b1;
IN <= IN;
end
end
end
else begin
CNT <= CNT;
IN <= IN;
end
end
endmodule
module cycle789(
CNT, //CycleCondition模块CNT的累计值
OUT //译码器输出
);
input [4-1:0] CNT;
output [7-1:0] OUT;
reg [7-1:0] OUT;
always @(CNT)begin
case(CNT)
4'b 0000: OUT = 7'b 1000000;// 0
4'b 0001: OUT = 7'b 1111001;// 1
4'b 0010: OUT = 7'b 0100100;// 2
4'b 0011: OUT = 7'b 0110000;// 3
4'b 0100: OUT = 7'b 0011001;// 4
4'b 0101: OUT = 7'b 0010010;// 5
4'b 0110: OUT = 7'b 0000010;// 6
4'b 0111: OUT = 7'b 1111000;// 7
4'b 1000: OUT = 7'b 0000000;// 8
4'b 1001: OUT = 7'b 0010000;// 9
default: OUT = 7'b 0000110; // E
endcase
end
endmodule
(2)BDF原理图
(3)RTL视图
(4)VWM波形仿真
下图是VWM波形仿真的结果,可以看到0 ~ 7,0 ~ 8,0 ~ 9一个完整循环的波形。
(5)SignalTap抓取到的波形
在setup界面将采样时钟clk设置为用verilog HDL代码编写的频率为10HZ的CLK1,采样点数设置为512。点击单次采样,等待一段时间。因为计数从0 ~ 7,0 ~ 8,0 ~ 9所需的时间为27s,所以在点击 “单次采样” 后要等待至少27s的时间才能抓取到一次完整的循环波形。如图是Signaltap抓取到的波形,其中Time bar分隔的三段是抓取到的0 ~ 7,0 ~ 8,0 ~ 9的波形。
四、总结
- 程序编写时注意事项总结:
①在方法二中,最初实验结果只有0 ~ 7的循环,0 ~ 8和0 ~ 9出不来。经过调试程序,找出错误原因是:在CycleCondition模块中,CNT< CNT1、CNT<CNT2、CNT<CNT3里,没有写 IN <= IN 这句,所以循环不起来。
②在循环语句中,每当语句数>=2,都要用begin…end将循环语句包起来。 - 关于VWM波形仿真注意事项总结:
①由于在CycleCondition模块里,“0 ~ 7,0 ~ 8,0 ~ 9”循环启动的大前提是EN=1,所以应该在VWM波形仿真时把EN设置为高电平
②把需要进行VWM波形观察的模块CycleCondition设为顶层文件。 - SignalTap抓取波形注意事项总结:
①设置合理的采样深度
②当刚点击“单次运行”抓取波形后,需要等待一段时间再点击“暂停”,不能刚点击“单次运行”就立刻点击“暂停”截获波形。否则就会导致由于时间太短,采到的样点数并没有达到所设置的采样深度,导致抓取失败。
③时间轴范围的设置。点击鼠标左键为 放大时间轴,点击鼠标右键为缩小时间轴。可以选择Sample numbers显示采样点数,也可以选择Time Units显示采样时间。
最后
以上就是敏感小松鼠为你收集整理的FPGA|设计计数器实现0到M循环计数的全部内容,希望文章能够帮你解决FPGA|设计计数器实现0到M循环计数所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复