奇偶、半整数、DDS分频器设计

前言

分频在数字设计中应用广泛,可利用锁相环或者计数器实现。

偶数分频

偶数分频较为简单,利用计数器计数到N-1时钟翻转即可,下面是四分频代码:

module divider_even(
	input clk,
	input rst_n,
	output reg clk4
    );
	 
	reg cnt;
	
	always @(posedge clk or negedge rst_n) begin
		if(!rst_n) begin
			cnt <= 1'b0;
		end
		else begin
			cnt <= cnt + 1'b1;
		end
	end
	
	always @(posedge clk or negedge rst_n) begin
		if(!rst_n) begin
			clk4 <= 1'b0;
		end
		else if(cnt == 1'b1)
			clk4 <= ~clk4;
		else
			clk4 <= clk4;
	end
	
endmodule

测试代码:

module divider_even_tb;

	// Inputs
	reg clk;
	reg rst_n;

	// Outputs
	wire clk4;

	// Instantiate the Unit Under Test (UUT)
	divider_even uut (
		.clk(clk), 
		.rst_n(rst_n), 
		.clk4(clk4)
	);

	initial begin
		// Initialize Inputs
		clk = 0;
		rst_n = 0;

		// Wait 100 ns for global reset to finish
		#100;
      rst_n = 1;  
		// Add stimulus here
		#400;
			$stop;
	end
	
	always #5 clk <= ~clk;
      
endmodule

仿真结果:
四分频

奇数分频

利用参数化设计的方法,可以实现任意奇数分频,便于模块复用。定义参数parameter N为分频系数,以五分频为例,利用时钟上升沿和下降沿分别作为触发条件,得到两个时钟,都是高电平2个时钟低电平3个时钟,但是相差半个时钟周期,最后相或能得到50%占空比的N分频时钟。
五分频代码:

module divider_odd #(parameter N = 8'd5)(
	input clk,
	input rst_n,
	output clk5
    );
	 
	reg [7:0]cnt1,cnt2;
	reg clk1,clk2;
	wire flag1,flag2;
	//上升沿触发
	always @(posedge clk or negedge rst_n) begin
		if(!rst_n) begin
			cnt1 <= 8'd0;
		end
		else if(cnt1 == N-1)
			cnt1 <= 8'd0;
		else 
			cnt1 <= cnt1 + 8'd1;
	end
	
	always @(posedge clk or negedge rst_n) begin
		if(!rst_n) begin
			clk1 <= 1'b0;
		end
		else if(flag1)
			clk1 <= ~clk1;
		else clk1 <= clk1;
	end
	
	
	//下降沿触发
	always @(negedge clk or negedge rst_n) begin
		if(!rst_n) begin
			cnt2 <= 8'd0;
		end
		else if(cnt2 == N-1)
			cnt2 <= 8'd0;
		else 
			cnt2 <= cnt2 + 8'd1;
	end
	
	always @(negedge clk or negedge rst_n) begin
		if(!rst_n) begin
			clk2 <= 1'b0;
		end
		else if(flag2)
			clk2 <= ~clk2;
		else clk2 <= clk2;
	end
	
	assign flag1 = ((cnt1 == (N-1)>>1) | (cnt1 == N-1));
	assign flag2 = ((cnt2 == (N-1)>>1) | (cnt2 == N-1));
	assign clk5 = clk1 | clk2;

endmodule

分别在测试文件中令N为5和7,仿真结果如下:
在这里插入图片描述在这里插入图片描述

半整数分频

整数分频无法做到50%占空比,以3.5分频为例,我们可以高电平1.5个周期,低电平2个周期。利用三个always块,一个计数模块,另外两个分别以时钟的上升沿和下降沿为触发条件,分别产生标志信号clk_1和clk_2,最后二者相或即可得到半整数分频结果。以3.5分频为例:

module divider_half(
	input clk,
	input rst_n,
	output clk_half
    );
	//参数定义
	parameter dou_coe = 7;
	reg [7:0]cnt;
	reg clk_1;
	reg clk_2;
	
	//计数模块
	always @(posedge clk or negedge rst_n) begin
		if(!rst_n) begin
			cnt <= 8'd0;
		end
		else if(cnt == dou_coe-1) begin
			cnt <= 8'd0;
		end
		else cnt <= cnt + 1;
	end
	//上升沿检测
	always @(posedge clk or negedge rst_n) begin
		if(!rst_n) begin
			clk_1 <= 1'b0;
		end
		else if((cnt == 8'd0) | (cnt ==((dou_coe+1)>>1))) begin
			clk_1 <= 1'b1;
		end
		else clk_1 <= 1'b0;
	end	
	//下降沿检测
	always @(negedge clk or negedge rst_n) begin
		if(!rst_n) begin
			clk_2 <= 1'b0;
		end
		else if((cnt == 8'd1) | (cnt ==((dou_coe+1)>>1))) begin
			clk_2 <= 1'b1;
		end
		else clk_2 <= 1'b0;
	end

	assign clk_half = clk_1 | clk_2;

endmodule

测试结果:
在这里插入图片描述

DDS任意分频

DDS,即直接数字频率合成技术。网上有说比常规的数字计数精度更高,但是我实际仿真结果却是一样的。我们以100MHz分频到115200Hz为例,常规的任意分频:
K=100_000_000/115200=868(取整)
100_000_000/868=115207,因此误差大概是7Hz
利用DDS进行任意分频器设计,首先我们一个取32位的计数器,K=115200 * 232/100_000_000=4947802.32499,取值为4947802,4947802 * 100_000_000/232=115199.9924,这个结果和115200Hz相差甚小,设计代码如下:

module divider_dds(
	input clk,
	input rst_n,
	output reg clk_dds
    );
	 
	parameter K1 = 32'd4947802;//115200,实际上是115199.99
	reg [31:0]cnt;
	
	always @(posedge clk or negedge rst_n) begin
		if(!rst_n) begin
			cnt <= 0;
		end
		else
			cnt <= cnt + K1;
	end
	
	always @(posedge clk or negedge rst_n) begin
		if(!rst_n) begin
			clk_dds <= 0;
		end
		else if(cnt > 32'h7FFF_FFFF)
			clk_dds <= 1;
		else
			clk_dds <= 0;
	end

endmodule

仿真结果如下:
在这里插入图片描述
不难看出,分频后的时钟周期是8680ns,频率约为115207Hz,这和常规的计数分频相比,精度上并没有提升。

ISE的工程文件:https://download.csdn.net/download/qq_39496263/85093066?spm=1001.2014.3001.5501

总结

欢迎交流进步!

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值