当前位置:   article > 正文

FPGA——分频器_fpga分频器

fpga分频器

野火学习备忘录——FPAG分频
时钟对于 FPGA 是非常重要的,但板载晶振提供的时钟信号频率是固定的,不一定满
足工程需求,所以分频和倍频还是很有必要的。这里通过计数的方式来实现分频。

1.通过计数器来实现6分频。两种方式。第一种直接通过计数方式直接获取获取。输入信号sys_clk和sys_rst_n,输出分频的信号clk_out,还有一个变量计数器cnt。
在这里插入图片描述

module      divider_six
(
        input wire      sys_rst,
        input wire      sys_clk,
        
        output reg      clk_out
);
reg     [2:0]   cnt;
always@(posedge sys_clk or negedge sys_rst)
    if(sys_rst == 1'b0)
    cnt <= 2'd0;
    else    if(cnt == 2'd2)
    cnt <= 2'd0;
    else
    cnt <= cnt+2'd1;
always@(posedge sys_clk or negedge sys_rst)
    if(sys_rst == 1'b0)
    clk_out <= 1'b0;
    else    if(cnt == 2'd2)
    clk_out <= ~clk_out;
    else
    clk_out <= clk_out;

endmodule

    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

testbench

`timescale 1ns/1ns
module  tb_divider_six();
        reg       sys_rst;
        reg       sys_clk;
        
        wire       clk_out;
initial
    begin
    sys_clk = 1'b1;
    sys_rst = 1'b0;
    #20
    sys_rst = 1'b1;
    end
always #10 sys_clk = ~sys_clk;


 divider_six  divider_six_inst
(
        .sys_rst(sys_rst),
        .sys_clk(sys_clk),
          
        .clk_out(clk_out)
);
endmodule

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

modelsim仿真结果
在这里插入图片描述

假设工作方式是直接把分频出来的时钟直接当作系统工作时钟

//直接使用clk_out作为工作时钟
always@(posedge clk_out or negedge sys_rst_n)
	if(sys_rst_n == 1'b0)
		a <= 0;
	else
		a <= a + 1
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

第二种是通过一个标志信号clk_flag和系统时钟sys_clk来作为一个6分频的工作时钟。

在这里插入图片描述

module      divider_six
(
        input wire      sys_rst,
        input wire      sys_clk,
        
        output reg      clk_flag
);
reg     [2:0]   cnt;

always@(posedge sys_clk or negedge sys_rst)
    if(sys_rst == 1'b0)
		cnt <= 2'd0;
    else    if(cnt == 3'd5)
		cnt <= 3'd0;
    else
		cnt <= cnt+3'd1;
		
always@(posedge sys_clk or negedge sys_rst)
    if(sys_rst == 1'b0)
		clk_flag <=1'b0;
    else    if(cnt == 3'd4)
		clk_flag <=1'b1;
    else
		clk_flag <=1'b0; 
endmodule

    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

这里工作的方式还是在系统的时钟条件下工作的

//工作时钟还是系统时钟 
always@(posedge sys_clk or negedge sys_rst_n)
	if(sys_rst_n == 1'b0)
		a <= 1'd0;
	else	if(clk_flag == 1'b1)
		a <= a + 1'b1;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

这里为什么要说明这两种方式呢?
这里就要说到FPGA中的全局时钟网络,因为在 FPGA 中凡是时钟信号都要连接到全局时钟网络上,全局时钟网络也称为全局时钟树,是 FPGA 厂商专为时钟路径而特殊设计的,它能够使时钟信号到达每个寄存器的时间都尽可能相同,以保证更低的时钟偏斜(Skew)和抖动(Jitter)。然而我们采用第一种方式产生的时钟clk_out信号并没有连接到全局时钟网络上,这种做法所衍生的潜在问题在低速系统中不易察觉,而在高速系统中就很容易出现问题,但 sys_clk 则是由外部晶振直接通过管脚连接到了 FPGA 的专用时钟管脚上,自然就会连接到全局时钟网络上,所以在 sys_clk 时钟工作下的信号要比在 clk_out 时钟工作下的信号更容易在高速系统中保持稳定。所以第二种方式相对来说更加安全。

上述已经说到6分频,属于偶数分频。下面就来介绍奇数分频。奇数分频采用上述第二种方式来实现的话,思路和步骤都差不多。我这里介绍一下奇数分频采用上述的第一种方式。那么问题又来了,既然上述第一种方式没有第二种好,为什么还有讲的,哈哈,是的。我记录他并不是因为他的好,而是因为这里奇数分频时的思路和逻辑思维。这里实现一个5分频。
在这里插入图片描述
首先是输入时钟和复位,一个计数器,两个变量分频时钟,一个输出时钟。要实现N奇数分频,计数器计数到N-1,这里5分频最大计数到4。然后变量clk1初始状态为高电平,系统时钟上升沿到来时有效,这里计数到2时拉低,其实这里可以计数到0,1,2,3都是可以的。clk2初始状态也是高电平,系统时钟下降沿到来时有效。这里计数到与clk1计数最大值一致就行,然后clk1与clk2做与运算就可以得到输出5分频时钟clk_out。

RTL代码

module	divider_five
(	
	
	input	wire			sys_clk		,
	input	wire			sys_rst_n	,
	
	output	wire			clk_out
);

reg	[2:0]	cnt;
reg			clk1;
reg			clk2;


always@(posedge sys_clk or negedge sys_rst_n)
	if(sys_rst_n == 1'b0)
		cnt <= 3'd0;
	else	if(cnt == 3'd4)
		cnt <= 3'd0;
	else
		cnt <= cnt + 1'b1;

always@(posedge sys_clk or negedge sys_rst_n)
	if(sys_rst_n == 1'b0)
		clk1 <= 1'b1;
	else	if(cnt == 3'd2)
		clk1 <= 1'b0;
	else	if(cnt == 3'd4)
		clk1 <= 1'b1;
	else
		clk1 <= clk1;
		

always@(negedge sys_clk or negedge sys_rst_n)
	if(sys_rst_n == 1'b0)
		clk2 <= 1'b1;
	else	if(cnt == 3'd2)
		clk2 <= 1'b0;
	else	if(cnt == 3'd4)
		clk2 <= 1'b1;
	else
		clk2 <= clk2;


assign  clk_out = clk1 & clk2;

endmodule

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48

testbench

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

reg			sys_clk;
reg			sys_rst_n;

wire		clk_out;

initial
	begin
		sys_clk = 1'b1;
		sys_rst_n <= 1'b0;
		#30
		sys_rst_n <= 1'b1;
	end
	
always	#10 sys_clk = ~sys_clk;

divider_five	divider_five_inst
(	
	
	.sys_clk		(sys_clk),
	.sys_rst_n		(sys_rst_n),

	.clk_out        (clk_out)
);
endmodule

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

modelsim仿真
在这里插入图片描述

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/人工智能uu/article/detail/872382
推荐阅读
相关标签
  

闽ICP备14008679号