08 FPGA—计数器与分频器的应用

1. 理论

       时序逻辑电路中最基本的单元—寄存器,我们可以使用寄存器来做计数器。基本上关于时间的设计都离不开计数器。

     计数器在数字系统中主要是对脉冲的个数进行计数,以实现测量、计数控制的功能,同时兼有分频功能。计数器一般都是从 0 开始计数,计数到我们需要的值或者计数满溢出后清零,并可以进行不断的循环, 3 位数的十进制计数器最大可以计数到 999, 4 位数的最大可以计数到 9999; 3 位数的二进制计数器最大可以计数到 111(7), 4 位数的最大可以计数到 1111(15)。

    分频器:一般开发板上面只有一个晶振,即只有一种频率的时钟。要想获得其他频率的时钟有pll  ip和写代码实现。pll后面会讲。

计数器

2.实操

    实验目标:使小灯闪烁10次,闪烁频率为一秒。

2.1  模块框图 

2.2 波形设计

2.3 编写rtl代码

`timescale  1ns/1ns

 module  ledflash10
#(
    parameter CNT_MAX =  25'd24_999_999             
	                                                
)
(
input    wire    sys_clk,
input    wire    sys_rst_n,

output   reg    led_out     
);

reg       [24:0]         cnt; 
reg       [4:0]          led_flag;
reg                      cnt_flag;                           
 
//cnt:定时0.5s    
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 0)
	    cnt <= 0;
    else if ((cnt == CNT_MAX)  ||  (led_flag > 19))
	    cnt <= 0;
	else 
	    cnt <= cnt + 1'b1;                          

//cnt_flag:标记cnt是否计满0.5s   	
always@(posedge sys_clk or negedge sys_rst_n)		
    if(sys_rst_n == 0)
	   cnt_flag <= 0;  
    else if (cnt == CNT_MAX - 25'b1)
	   cnt_flag <= 1;
    else 
       cnt_flag <= 0;	
                     	  
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 0)
	    led_flag <= 0;
    else if(cnt_flag == 1 )
		led_flag <= led_flag + 1'b1; 
	
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 0)
	    led_out <= 0;
    else if((cnt_flag == 1)  &&  (led_flag  <  5'd20  ))
		led_out <= ~led_out;   
		
	
endmodule   

3. 分频器

       使用 parmaeter 参数化的方法做成通用的任意分频模块,方便以后的调用。

`timescale  1ns/1ns

module  divider
#(
    parameter   CNT_MAX = 3'd6  //六分频计数器
)
(
    input   wire    sys_clk     ,   
    input   wire    sys_rst_n   ,   

    output  reg      clk_flag       
);

reg     [3:0]   cnt;               

always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        cnt <= 1'b0;
    else    if(cnt == CNT_MAX )
        cnt <= 1'b0;
    else
        cnt <= cnt + 1'b1;
//clk_flag  
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        clk_flag <= 1'b0;
    else    if(cnt == CNT_MAX-1)
        clk_flag <= 1'b1;
	else    
	    clk_flag <= 1'b0;
   

endmodule

       这里不使用图一的分频的思想,而采用图二倍频的思想。一是因为实现奇分频更方便,二是因为分频的方式产生的 clk_out 信号并没有连接到全局时钟网络上,在高速系统会出现问题。
 

 图一

  图二

 说明:

       本人使用的是野火家Xilinx Spartan6系列开发板及配套教程,以上内容如有疑惑或错误欢迎评论区指出,或者移步B站观看野火家视频教程。

开发软件:ise14.7     仿真:modelsim 10.5 

如需上述资料私信或留下邮箱。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
FPGA分频器的设计主要分为两种方式:基于计数器分频器和基于查找表的分频器。 基于计数器分频器:这种分频器使用FPGA内部的计数器来实现分频功能。首先需要确定分频比例,然后将计数器的初始值设置为所需的分频比例减1,每当计数器计数到0时,产生一个分频后的时钟信号。这种分频器具有简单、灵活的优点,但其最高分频率受到FPGA内部时钟频率的限制。 基于查找表的分频器:这种分频器使用FPGA内部的查找表实现分频功能。分频器的输入是一个时钟信号,输出是分频后的时钟信号。可以通过修改查找表的内容来实现不同的分频比例。这种分频器具有高速、低功耗的优点,但其实现较为复杂。 下面是一个基于计数器分频器的VHDL代码示例: ```vhdl library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity clock_divider is Port ( clk_in : in STD_LOGIC; clk_out : out STD_LOGIC); end clock_divider; architecture Behavioral of clock_divider is signal count : integer := 0; begin process(clk_in) begin if (rising_edge(clk_in)) then count <= count + 1; if (count = 100) then clk_out <= not clk_out; count <= 0; end if; end if; end process; end Behavioral; ``` 该代码实现了一个将输入时钟信号分频100倍的分频器。其中,计数器的初始值为0,每当计数器计数到99时,产生一个分频后的时钟信号,并将计数器清零。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

咖啡0糖

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值