FPGA基础设计(二):任意分频器(奇数,偶数,小数)

前言

FPGA开发板上一般只有一个晶振,即一种时钟频率。数字系统设计中,时间的计算都要以时钟作为基本单元,对基准时钟进行不同倍数的分频而得到各模块所需时钟频率,可通过Verilog代码实现;倍频可通过锁相环【PLL】实现。

分频原理

把输入信号的频率变成成倍的低于输入频率的输出信号;每经历几个单位时钟周期就输出一个时钟周期。
例:clk_in为12MHz; clk_out为2MHz.则分频系数为6。那么如何实现6分频:
  把输入信号作为计数脉冲(边沿触发一次,计数一次),
当计数6次,为输出信号的一个周期,此时输入信号经历了6个周期,置0,重新开始计数,循环往复。(前提:输入信号占空比50%)
而输出信号的不同占空比的实现无非是输出信号经历的单位周期输出高低电平不同;

偶数分频

   6分频

占空比50%:6分频电路:一个always块实现一个模3计数器。
     另一个always块实现当计数到2(从0计数到2,计数,3次)输出信号翻转,
     占空比50%。
占空比不是50%:先实现模6计数器,然后可任意设计当计数到某个值输出高电平,再计数到另一个值输出低电平。

   代码
//不带标志位占空比50%
module divider_six(clk,reset,clk_out,cnt);

         input clk;
		 input reset;
		 output reg clk_out;
		 
		 output reg [1:0] cnt;//用于计数的寄存器; always块内,reg型变量
		 
		 always@(posedge clk)
		       if(reset == 1'b0)
				    cnt <= 2'd0;
				 else if(cnt == 2'd2)//从0开始,计数到2,计数为3,则6分频
				    cnt <= 2'd0;
				 else
				    cnt <= cnt + 1'b1;
//计数3次,输出翻转;所以cnt计数3次作为标志,实现翻转功能					 
		  always@(posedge clk)
		        if(reset == 1'b0)
				     clk_out <= 1'b0;
				  else if(cnt == 2'd2)
				     clk_out <= ~clk_out;
				  else;
endmodule
   tb
`timescale 1ns/100ps
`define clk_cycle 50

module divider_six_tb;
  
     reg clk;
	 reg reset;
	 
	 wire clk_out;
	 wire [1:0]cnt;
	 
	 always #(`clk_cycle) clk = ~clk;//产生测试时钟,时钟周期100ns(s>ms>us>ns>ps)
	 
	 initial begin
	 
	     clk = 0;
		 reset = 1;
		 
		 #10 reset = 0;
		 #110 reset = 1;
		 #100000
		 $stop;
		 
	 end
	 divider_six u1(
	          .reset(reset),
				 .clk(clk),
				 .clk_out(clk_out),
				 .cnt(cnt)
				 );
endmodule 
   仿真波形

在这里插入图片描述
在这里插入图片描述

奇数分频

算法:需要在系统时钟为上升沿和下降沿都工作(不是同时工作)
    产生50%的占空比,需要设计两个分频时钟跳变点,分频周期的N-1(N-1)/2
例:13分频:两个分频时钟跳变点:6[(13-1)/2]和12[13-1],此时输出保持7个高电平时钟周期,6个低电平时钟周期分别在上升沿触发clk1和下降沿触发clk2,两者相位相差半个单位周期,clk_out = clk1 & clk2; 之后clk_out占空比50%
如图仿真波形:

  仿真波形

在这里插入图片描述

  代码
//13分频,占空比为50%

module div_13(clk,reset,clk_out,clk1,clk2);

       input clk;
	   input reset;
		 
	   output  clk_out;
		 
	   reg [3:0] cnt;
		 
	   output reg clk1;
	   output reg clk2;

//计数从0到12		 
		 always@(posedge clk)
		       if(reset == 1'b0 || cnt == 4'd12)
				    cnt <= 4'd0;
				 else
				    cnt <= cnt + 1'b1;
					 
//实现分频,clk1:7个高电平时钟周期,6个低电平时钟周期,上升沿触发	
       always@(posedge clk)				 
				 if(reset == 1'b0)
				    clk1 <= 1'b0;
				 else if(cnt == 4'd6)//复位后,计数到6,开始低电平,保持6个周期,
			       clk1 <= 1'b0;   //此时计数到12,重新计数,保持高电平直至计数到6
				 else if(cnt == 4'd12)//计数到6和12,这两个是分频跳变点
			       clk1 <= 1'b1;	  //如何得到?N-1;(N-1)/2
//clk2:下降沿触发,7个高电平时钟周期,6个低电平时钟周期
       always@(negedge clk)	
             if(reset == 1'b0)
		          clk2 <= 1'b0;
			    else if(cnt == 4'd6)
		          clk2 <= 1'b0;
			    else if(cnt == 4'd12)
		          clk2 <= 1'b1;
//clk1,clk2两者相差半个时钟周期					 
//clk1,clk2配合作用,都计数7次后,clk1立即回到低电平,而clk2延迟半个周期					 
		 assign	clk_out = clk1 & clk2;		 					
endmodule		 
  tb
`timescale 1ns/100ps
`define clk_cycle 50

module div_13_tb;
  
    reg clk;
	 reg reset;
	 
	 wire clk_out;
	 wire clk1;
	 wire clk2;
	 
	 always #(`clk_cycle) clk = ~clk;//产生测试时钟,时钟周期100ns(s>ms>us>ns>ps)
	 
	 initial begin
	 
	    clk = 0;
		 reset = 1;
		 
		 #10 reset = 0;
		 #110 reset = 1;
		 #100000
		 $stop;
		 
	 end
	 div_13 u1(
	          .reset(reset),
			  .clk(clk),
		      .clk_out(clk_out),
			  .clk1(clk1),
		      .clk2(clk2)
			 );
endmodule 

小数分频

   说明

1.等效意义上的小数分频:例5.3分频,没有周期为5.3的分频电路,实际是输出时钟53的周期对应于输出时钟的10个周期。
2.按序输出:时钟用处不大,没有意义
3.插入乱序输出:防止相位抖动,把多出来的脉冲均匀分散开

 半整数分频:N+0.5

思路:例:5.5分频
原时钟的半周期为单位,此时周期为11可分频输出6高5低。
上升沿触发,使得clk1前6周期输出高电平【N-1=10为一个跳变点】后5周期输出低电平【N-1)/2=5为另一个跳变点】;
下降沿触发使得clk2前5周期为低电平(cnt为0时的跳变点),后6【cnt=N-1)/2=5】周期为高电平。两个信号相与即为分频信号clk_div = clk1 & clk2;,类似奇分频

  仿真波形

在这里插入图片描述

  代码
//5.5分频
//原时钟周期一半为单位,输出1高10低,从0到10计数,前6周期高电平,后5周期低电平;
//再使用下降沿触发前5周期低电平,前6周期高电平,最后相与
module div_half_1(clk,rst_n,clk_div,clk1,clk2,cnt);

      input clk;
	   input rst_n;
	   
	   output clk_div;
		
	   
	   output reg[3:0] cnt;
	   output reg clk1;
	   output reg clk2;
//从0到10计数 模11	   
	   always@(posedge clk or negedge rst_n)
	          if(!rst_n)
			    cnt <= 4'd0;
			  else if (cnt==4'd10)
			    cnt <= 0;
			  else
			    cnt <= cnt + 1'b1;
				
	    always@(posedge clk or negedge rst_n)
		       if(!rst_n)
			     clk1 <= 1'b0;
			   else if(cnt==4'd10)//6个周期的高电平N-1=10
			     clk1 <= 1'b1;
			   else if(cnt==4'd5)//5个周期的低电平(N-1)/2=5
			     clk1 <= 1'b0;  //两个跳变点,(N-1)/2;N-1
//clk2相比于clk1延时半个时钟周期,			 
		always@(negedge clk or negedge rst_n)
               if(!rst_n)
                 clk2 <= 1'b0;
               else if(cnt==4'd0)//5个周期的低电平
                 clk2 <= 1'b0;
               else if(cnt==4'd5)//6个周期的高电平
                 clk2 <= 1'b1;

assign clk_div = clk1 & clk2;
endmodule				 
  tb
`timescale 1ns/100ps
`define clk_cycle 50

module div_half_1_tb;
  
    reg clk;
	 reg reset;
	 
	 wire clk_out;
	 wire clk1;
	 wire clk2;
	 wire[3:0] cnt;
	 
	 always #(`clk_cycle) clk = ~clk;//产生测试时钟,时钟周期100ns(s>ms>us>ns>ps)
	 
	 initial begin
	 
	    clk = 0;
		 reset = 1;
		 
		 #10 reset = 0;
		 #110 reset = 1;
		 #100000
		 $stop;
		 
	 end
	 div_half_1 u1(
	             .rst_n(reset),
				 .clk(clk),
				 .clk_div(clk_out),
				 .clk1(clk1),
				 .clk2(clk2),
				 .cnt(cnt)
				 );
endmodule 

 小数分频

   5.3分频

53/10=5.3 设5分频a次;6分频次
a+b=10;
5a+6b=53 ->a=7 ; b=3
如何插入排序:6556556555
Verilog实现:
脉冲删除:53个单位周期删除43个
算法:分母作为累加值,在clk的上升沿cnt加上分母10,判断是否大于分子,若小于(脉冲删除标志为1,删除)继续累加,若大于(脉冲删除标志为0,不删除)在下一周期减去分子。结果刚好是6556556555(由来:分母-余数=7,作为累加值,大于分母,输出N分频,然后减去分母,继续累加7,;小于分母,输出N+1分频)

  代码
//脉冲删除小数分频

module div_5_3_1(clk,rst_n,clk_out,cnt);  

       input clk;
	   input rst_n;
	   
	   output clk_out;
	   
	   parameter fra = 6'd53;//分子
	   parameter den = 6'd10;//分母
	   
	   output reg[5:0] cnt;
	   reg flag_del;//脉冲删除标志位
				
	   always@(posedge clk or negedge rst_n) begin
	          if(!rst_n)begin
			    cnt <= 6'd0;
				 flag_del <= 1'b0;
			  end
			//大于分子,不删除  
			  else if(cnt>fra) begin
			    cnt <= cnt + den - fra;
				 flag_del <= 1'b0;
			  end
			//小于分子,累加;删除:保持高电平
			  else begin
			    cnt <= cnt + den;
			  	 flag_del <= 1'b1;
			  end
		end	
		
		assign clk_out = flag_del ? 1 : clk;

endmodule
  tb
`timescale 1ns/100ps
`define clk_cycle 50

module div_5_3_1_tb;
  
     reg clk;
	 reg reset;
	 
	 wire clk_out;
	 wire [5:0]cnt;
	 
	 always #(`clk_cycle) clk = ~clk;//产生测试时钟,时钟周期100ns(s>ms>us>ns>ps)
	 
	 initial begin
	 
	     clk = 0;
		 reset = 0;
		 
		 #10 reset = 0;
		 #110 reset = 1;
		 #100000
		 $stop;
		 
	 end

	 		 div_5_3_1 u1 (
		          .clk(clk),
				  .rst_n(reset),
				  .clk_out(clk_out),
				  .cnt(cnt)
				  );
endmodule 
  仿真波形

在这里插入图片描述

最后

不足之处:未实现参数化编程;

参考:

https://blog.csdn.net/weixin_43698385/article/details/122773225
https://blog.csdn.net/Reborn_Lee/article/details/97553078
https://blog.csdn.net/wangyanchao151/article/details/81204126?ops_request_misc=&request_id=&biz_id=102&utm_term=%E5%B0%8F%E6%95%B0%E5%88%86%E9%A2%91&utm_medium=distribute.pc_search_result.none-task-blog-2allsobaiduweb~default-5-81204126.nonecase&spm=1018.2226.3001.4187

  • 12
    点赞
  • 113
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
### 回答1: 基于CPLD(Complex Programmable Logic Device)的任意整数半整数分频器设计,是指使用CPLD芯片来实现对输入信号进行分频操作,分频倍数可以是任意的整数或半整数。 CPLD是一种由可编程逻辑单元和可编程连线网络组成的集成电路。它具有可编程性、灵活性和高速性的特点,能够完成多种逻辑功能。在设计基于CPLD的分频器,需要先确定分频的倍数,即输入频率与输出频率之间的比例关系。 设计步骤如下: 1. 确定输入信号的频率范围和输入电平。根据输入信号的特性选择相应的CPLD芯片,考虑其最大工作频率和I/O电平适配。 2. 根据所需的分频倍数,设计和编写实现该倍数的分频逻辑电路的VHDL或Verilog代码。 3. 使用CPLD开发工具,如Quartus II或Xilinx ISE,在CPLD芯片上创建项目并导入所编写的代码。 4. 进行逻辑综合和布局布线,生成逻辑网表和物理布局。 5. 将CPLD芯片烧录或下载到目标板上进行调试和测试。 6. 验证设计分频器是否能够按照预期的倍数对输入信号进行分频,检查输出频率是否满足要求。 在实际设计过程中,还可以考虑添加锁定电路或频率调整电路,以提高分频器的稳定性和灵活性。此外,还可以根据具体应用的需要,对设计进行优化,如引入FIFO缓冲区来处理高速输入信号等。 基于CPLD的任意整数半整数分频器可以广泛应用于无线通信、音视频处理、测量仪器等领域,提供了一种灵活可编程的频率处理解决方案。 ### 回答2: 基于CPLD的任意整数半整数分频器使用可编程逻辑器件(CPLD)实现,可以将输入频率分频任意整数或半整数倍的输出频率。以下是一个简单的设计概述: 该分频器主要由CPLD、钟源、计数器和控制逻辑组成。CPLD负责接收输入钟信号,并根据控制逻辑的设定进行分频操作。计数器用于计算分频比,并生成相应的输出频率。 设计过程如下: 1. 确定所需的输入和输出频率。例如,输入频率为100MHz,输出频率为50MHz。 2. 根据所需的分频比,即输出频率除以输入频率,计算所需的计数器宽度。在本例中,计数器宽度为2位。 3. 在CPLD中创建一个计数器,宽度为2位。首先,将计数器置零,并开始计数。 4. 当计数器的值达到所需的计数器宽度,将输出信号置高,表示输出一个脉冲。 5. 在输出信号上添加一个低通滤波器,以去除脉冲信号并生成平滑的输出频率。 6. 根据所需的分频比和计数器宽度,调整CPLD中的控制逻辑,以便在达到所需的计数器值,将计数器重置为零。 7. 设置适当的电源和钟源来供给CPLD工作。 总结: 基于CPLD的任意整数半整数分频器可以实现输入频率的任意整数或半整数倍的输出频率。通过使用CPLD与计数器和控制逻辑的组合,可以根据所需的分频比来设计和实现这样的系统。这样的设计可以用于各种应用,如通信、数字信号处理等领域。 ### 回答3: 基于CPLD(Complex Programmable Logic Device)的任意整数半整数分频器是一种电路设计分频器的作用是将输入信号的频率降低到输出信号的一半或者其整数倍。 设计这样的分频器可以通过利用CPLD的可编程逻辑单元来实现。CPLD是一种可编程计数器,可以根据用户的需求配置其内部电路的功能。 设计过程如下: 1. 确定输入信号的频率和分频系数。假设输入频率为F,分频系数为N。 2. 使用CPLD的可编程逻辑单元来实现一个计数器。计数器的初始值为0。 3. 定义计数器的计数规则。计数器每次计数到N-1,输出一个脉冲信号,然后将计数器的值重新设置为0。 4. 将输入信号连接到计数器的钟输入端口,当计数器工作,输入信号的频率就会被分频为输入频率的1/N。 5. 将计数器的输出连接到输出端口,即可得到分频后的信号。 设计这样的分频器的好处是可以根据需求自由设定分频系数,从而得到不同的输出频率。这在一些需要将信号频率匹配到特定电路或设备非常有用。 简而言之,基于CPLD的任意整数半整数分频器利用CPLD的可编程逻辑单元来设计一个计数器,通过设定合适的计数规则和分频系数,可以将输入信号的频率降低到输出信号的一半或其整数倍。这种设计能够灵活适应不同的频率需求。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值