偶分频

偶分频

分频器是数字系统中最常见的基本电路之一。分频就是将输入信号的频率变成成倍地低于输入频率的输出信号。如输入信号频率为50MHZ,10分频后输出信号频率为5MHZ。这里10是分频系数,分频系数为偶数则为偶分频,分频系数为奇数则为奇分频。先说偶分频,有两种方法:分频法和降频法。
在这里插入图片描述

分频法

分频系数为N(N为偶数),就是N分频,分频器实现方法和计数器原理一致,当计数值到(N/2)-1时,输出信号电平翻转,此输出信号即为N分频的信号。
在这里插入图片描述
代码如下:

module divider_8
 (
	input		sys_clk,
	input		rst_n,
	
	output reg	clk_out
 );
 
 reg 	[1:0] cnt;
 
 always@(posedge sys_clk or negedge rst_n) begin
	if(rst_n == 1'b0)
		cnt <= 2'd0;
	else if(cnt == 2'd3)
		cnt <= 2'd0;
	else
		cnt <= cnt + 2'd1;
 end
 
 always@(posedge sys_clk or negedge rst_n)begin
	if(rst_n == 1'd0)
		clk_out <= 1'd0;
	else if(cnt == 2'd3)
		clk_out <= ~clk_out;
	else
		clk_out <= clk_out;
 end
 
 endmodule

上述方法生成了低频时钟clk_out,但是如果直接用clk_out作为驱动时钟实现一些功能会出现隐患。在FPGA中凡是时钟信号都需要连接到全局时钟网络(全局时钟树),是FPGA厂商专门为时钟路径设计的,它能使时钟信号到达每个寄存器的时间尽可能地相同,减少时序问题的产生。而分频方式产生的低频时钟并没有连接到全局时钟网络上,外部晶振产生的时钟信号通过管脚连接到FPGA专用的时钟引脚上,即连接到了全局时钟网络上。所以在系统时钟控制下的信号比低频时钟控制下的信号更能保持稳定。

降频法

下面采用生成标志位(脉冲标志信号cnt_flag)对上述方法进行一些改进。在计数值达到N-2(这里N-2为6,用N-2是因为时序逻辑生成信号会延迟一个周期)时,生成一个脉冲标志信号cnt_flag,并保持一个时钟周期。如此仍用系统时钟作为驱动时钟,而将cnt_flag作为标志信号进行条件判断,可以实现和上述方法相同的分频功能(由下图可知,每隔一个cnt_flag信号同样对应8个时钟周期)。但运用标志信号的方法在高速系统中能够减少时序错误,这种方法称之为降频。在这里插入图片描述

module divider_8
 (
	input		sys_clk,
	input		rst_n,
	
	//output reg	clk_out
	output  reg		cnt_flag
 );
 
 reg 	[2:0] cnt;
 
 /* always@(posedge sys_clk or negedge rst_n) begin //注释掉的部分为生成低频时钟的方法
	if(rst_n == 1'b0)
		cnt <= 2'd0;
	else if(cnt == 2'd3)
		cnt <= 2'd0;
	else
		cnt <= cnt + 2'd1;
 end
 
 always@(posedge sys_clk or negedge rst_n)begin
	if(rst_n == 1'd0)
		clk_out <= 1'd0;
	else if(cnt == 2'd3)
		clk_out <= ~clk_out;
	else
		clk_out <= clk_out;
 end */
 
 always@(posedge sys_clk or negedge rst_n) begin
	if(rst_n == 1'b0)
		cnt <= 3'd0;
	else if(cnt == 3'd7)
		cnt <= 3'd0;
	else
		cnt <= cnt + 3'd1;
 end
 
 always@(posedge sys_clk or negedge rst_n)begin
	if(rst_n == 1'd0)
		cnt_flag <= 1'd0;
	else if(cnt == 3'd6)	//注意是6(N-2)
		cnt_flag <= 1'd1;	//保持一个周期高电平
	else
		cnt_flag <= 1'd0;	//其他时刻为低电平
 end
 endmodule 

仿真文件如下:

`timescale 1ns/1ns
module divider_8_tb();

reg  sys_clk;
reg  rst_n;

//wire  clk_out;
wire  cnt_flag;

parameter CYCLE = 20;

initial begin
	sys_clk = 1'b0;
	forever #(CYCLE/2) sys_clk = ~sys_clk;
end

initial begin
	rst_n <= 1'b0;
	#20 
	rst_n <= 1'b1;
end

divider_8   divider_8_inst
 (
	.sys_clk(sys_clk)	,
	.rst_n	(rst_n)		,
	           
//	.clk_out   (clk_out)
	.cnt_flag   (cnt_flag)
 );
 
endmodule

仿真结果如下,经过对比,仿真结果和所绘时序图一致。
在这里插入图片描述
如果使用低频时钟作为驱动,则always块如以下形式:

always@(posedge clk_out or negedge rst_n) begin  //sys_clk改为clk_out
	if(rst_n == 1'b0)
		...
        ...
 end

采用系统时钟作为驱动,则形式如下:

always@(posedge sys_clk or negedge rst_n) begin
	if(rst_n == 1'b0)
		...
	else if(cnt_flag == 1’b1)	//以脉冲标志位作为条件判断,同样起到分频作用
		...
	else
		...
 end

来个简短的总结

	在高速系统用到分频时钟的时候,最好采用生成脉冲标志信号的方法,可减少时序错误。低速系统中甚至只有几个寄存器的情况下,采用两种方法皆可。
  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值