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 

对应的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

举例–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

对应的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

举例–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

对应的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

举例–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

对应的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

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

  • 3
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值