当前位置:   article > 正文

FPGA硬件逻辑和数字IC中笔试面试常考的Verilog语言实现分频问题(包含偶数分频、计数分频、小数分频和任意整数分频)_整数分频和小数分频

整数分频和小数分频

FPGA硬件逻辑和数字IC中笔试面试常考的Verilog语言实现分频问题(包含偶数分频、计数分频、小数分频和任意整数分频)

由于2021秋招需要,我查找了很多奇偶分频的文章,将其中简单且便于理解的放出来,全部是经过Vivado仿真验证过的,请放心使用。
时钟信号的处理是FPGA的特色之一,因此分频器也是FPGA设计中使用频率非常高的基本设计之一。一般在FPGA中都有集成的锁相环可以实现各种时钟的分频和倍频设计,但是通过语言设计进行时钟分频是最基本的训练,在对时钟要求不高的设计时也能节省锁相环资源。

一、偶数分频

`timescale 1ns/1ps
///
//Create Date: 2020/03/05 
//Module Name: even_div
//Engineer: hewen 
///
module even_div(clk_in,reset,clk_out);
parameter N = 4;
input clk_in;
input reset;
output clk_out;

reg clk_out;
reg[N-1:0] cnt;

always @(posedge clk_in)
begin
	if(!reset) 
	begin
		cnt<=0;
		clk_out <= 0;
	end
	else
		if(cnt==(N/2-1))
		begin
			cnt<=0;
			clk_out=~clk_out;
		end
		else
		begin
			cnt<=cnt+1;
			clk_out<=clk_out;
		end
end
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

对应的testbench测试程序

//testbench程序
`timescale 1ns/1ps
///
//Create Date: 2020/03/05 
//Module Name: even_div_tb
//Engineer: hewen 
///
module even_div_tb;
reg clk_in;
reg reset;
wire clk_out;

even_div uut(
	.clk_in(clk_in),
	.reset(reset),
	.clk_out(clk_out)
);
initial begin
	clk_in = 0;
	reset = 0;
	#10 reset = 1;
end
	always #5 clk_in = ~clk_in;
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

举例–4分频的波形如下:
在这里插入图片描述
二、奇数分频

`timescale 1ns/1ps
///
//Create Date: 2020/03/05 
//Module Name: even_div
//Engineer: hewen 
///
module odd_div(clk_in,reset,clk_out);
input clk_in;
input reset;
output clk_out;

integer cnt1,cnt2;
reg clk_divp;
reg clk_divn;

parameter N=5;

always @(posedge clk_in)
begin
	if(!reset)
		begin
		clk_divp<=0;
		cnt1<=0;
		end
	else
		if(cnt1==(N-1))
			cnt1<=0;
		else
			if(cnt1==0|cnt1==(N-1)/2)
				begin
				cnt1<=cnt1+1;
				clk_divp<=~clk_divp;
				end
		else
			cnt1<=cnt1+1;
end

always @(negedge clk_in)
begin
	if(!reset)
	begin
		clk_divn<=0;
		cnt2<=0;
	end
	else
		if(cnt2==0|cnt2==(N-1)/2)
		begin
		cnt2<=cnt2+1;
		clk_divn<=~clk_divn;
		end
		else
			cnt2<=cnt2+1;	
end

assign clk_out = clk_divp | clk_divn;

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
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57

对应的testbench测试程序

//testbench程序
`timescale 1ns/1ps
///
//Create Date: 2020/03/05 
//Module Name: odd_div_tb
//Engineer: hewen 
///
module odd_div_tb;
reg clk_in;
reg reset;
wire clk_out;

odd_div uut(
	.clk_in(clk_in),
	.reset(reset),
	.clk_out(clk_out)
);

initial 
begin
	clk_in = 0;
	reset = 0;
	#10 reset = 1;
end

always #2 clk_in = ~clk_in;

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

举例–5分频的波形如下:
在这里插入图片描述
三、小数分频

`timescale 1ns/1ps
///
//Create Date: 2020/03/05 
//Module Name: half_integer_div
//Engineer: hewen 
///
module half_integer_div(
	input clk,
	input rst_n,
	output clk_out
);

parameter N = 3;  //3.5分频

reg[31:0] cnt1;
reg clk_p;
reg clk_n;
always @(posedge clk or posedge rst_n)
begin
	if(!rst_n)
		cnt1<=0;
	else if(cnt1 == 2*N)
		cnt1<= 0;
	else
		cnt1<=cnt1+1;
end

always @(posedge clk or posedge rst_n)	
begin 
	if(!rst_n)
		clk_p<=0;
	else if(cnt1 == 2*N)
		clk_p<=1;
	else if(cnt1 == N)
		clk_p<=0;
end

always @(negedge clk or posedge rst_n)
begin
	if(!rst_n)
	clk_n <= 0;
	else if (cnt1==0)
		clk_n <= 0;
	else if(cnt1 ==N)
		clk_n<=1;
end

assign clk_out = clk_p & clk_n;
	
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
  • 49
  • 50

对应的testbench测试程序

//testbench程序
`timescale 1ns/1ps
///
//Create Date: 2020/03/05 
//Module Name: half_integer_div_tb;
//Engineer: hewen 
///
module half_integer_div_tb;
reg clk_in;
reg reset;
wire clk_out;

half_integer_div uut(
	.clk(clk_in),
	.rst_n(reset),
	.clk_out(clk_out)
);

initial 
begin
	clk_in = 0;
	reset = 0;
	#10 reset = 1;
end

always #2 clk_in = ~clk_in;

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

举例–3.5分频的波形如下:
在这里插入图片描述
四、任意整数分频
//参考链接:http://mp.weixin.qq.com/s/962d_hkVh3qxHrwz0v8eSg

`timescale 1ns/1ps
///
//Create Date: 2020/03/05 
//Module Name: divide
//Engineer: hewen 
///
module divide #
(							
parameter WIDTH = 24, //计数器的位数,计数的最大值为 2**(WIDTH-1)
parameter N = 12_000_000  //分频系数,请确保 N<2**(WIDTH-1),否则计数会溢出
)
(input clk,  //clk连接到FPGA的C1脚,频率为12MHz
input rst_n,  //复位信号,低有效,
output clkout  //输出信号,可以连接到LED观察分频的时钟
); 
 reg [WIDTH-1:0] cnt_p,cnt_n;	
 reg clk_p,clk_n;	
 
/**********上升沿触发部分************/
//上升沿触发时计数器的控制
always @(posedge clk or negedge rst_n)	    
begin     
	if(!rst_n)
		cnt_p <= 1'b0;    
	else if(cnt_p == (N-1))
		cnt_p <= 1'b0;    
	else 
		cnt_p <= cnt_p + 1'b1;		    
end 
 //上升沿触发的分频时钟输出,如果N为奇数得到的时钟占空比不是50%;如果N为偶数得到的时钟占空比为50%
always @(posedge clk or negedge rst_n)    
begin    
	if(!rst_n)
		clk_p <= 1'b0;    
	else if(cnt_p < (N>>1))	
		clk_p <= 1'b0;
	else 
		clk_p <= 1'b1;	
end

/***********下降沿触发部分*************/
//下降沿触发时计数器的控制        	
always @(negedge clk or negedge rst_n)    
begin    
	if(!rst_n)
		cnt_n <= 1'b0;    
	else if(cnt_n == (N-1))
		cnt_n <= 1'b0;    
	else 
		cnt_n <= cnt_n + 1'b1;
end  
//下降沿触发的分频时钟输出,和clk_p相差半个clk时钟
always @(negedge clk or negedge rst_n)    
begin    
	if(!rst_n)
		clk_n <= 1'b0;    
	else if(cnt_n < (N>>1))  
		clk_n <= 1'b0;   
	else 
		clk_n <= 1'b1;    
end
wire clk1 = clk;  //当N=1时,直接输出clk
wire clk2 = clk_p;  //当N为偶数也就是N[0]=0,输出clk_p
wire clk3 = clk_p & clk_n;  //当N为奇数也就是N[0]=1,输出clk_p&clk_n。正周期多所以是相与  
assign clkout = (N==1)? clk1:(N[0]? clk3: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
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66

对应的testbench测试程序

//testbench程序
`timescale 1ns/1ps
///
//Create Date: 2020/03/05 
//Module Name: divide_tb;
//Engineer: hewen 
///
module divide_tb;
reg clk_in;
reg reset;
wire clk_out;

divide uut(
	.clk(clk_in),
	.rst_n(reset),
	.clkout(clk_out)
);

initial 
begin
	clk_in = 0;
	reset = 0;
	#10 reset = 1;
end

always #2 clk_in = ~clk_in;

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

举例–9分频的波形如下:
在这里插入图片描述

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

闽ICP备14008679号