FPGA|设计计数器实现0到M循环计数

一、实验任务

设计一个计数器,计数器每个时钟信号变化一次计数值,从 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代码编写的频率为10HZCLK1,采样点数设置为512。点击单次采样,等待一段时间。因为计数从0 ~ 7,0 ~ 8,0 ~ 9所需的时间为27s,所以在点击 “单次采样” 后要等待至少27s的时间才能抓取到一次完整的循环波形。如图是Signaltap抓取到的波形,其中Time bar分隔的三段是抓取到的0 ~ 7,0 ~ 8,0 ~ 9的波形。
在这里插入图片描述

四、总结

  1. 程序编写时注意事项总结:
    ①在方法二中,最初实验结果只有0 ~ 7的循环,0 ~ 8和0 ~ 9出不来。经过调试程序,找出错误原因是:在CycleCondition模块中,CNT< CNT1CNT<CNT2CNT<CNT3里,没有写 IN <= IN 这句,所以循环不起来。
    ②在循环语句中,每当语句数>=2,都要用begin…end将循环语句包起来。
  2. 关于VWM波形仿真注意事项总结:
    ①由于在CycleCondition模块里,“0 ~ 7,0 ~ 8,0 ~ 9”循环启动的大前提是EN=1,所以应该在VWM波形仿真时把EN设置为高电平
    ②把需要进行VWM波形观察的模块CycleCondition设为顶层文件。
  3. SignalTap抓取波形注意事项总结:
    ①设置合理的采样深度
    ②当刚点击“单次运行”抓取波形后,需要等待一段时间再点击“暂停”,不能刚点击“单次运行”就立刻点击“暂停”截获波形。否则就会导致由于时间太短,采到的样点数并没有达到所设置的采样深度,导致抓取失败。
    ③时间轴范围的设置。点击鼠标左键为 放大时间轴,点击鼠标右键为缩小时间轴。可以选择Sample numbers显示采样点数,也可以选择Time Units显示采样时间。
  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值