FPGA 三分频 五分频 任意分频 Vreilog实现

目录

三分频

 三分频verilog代码

Testbench 

 五分频

 Verilog实现

任意分频后面再写吧


三分频

3 分频的本质是我们需要在每次 1.5 倍的时钟周期的时候实现 3 分频寄存器的翻转,但是我们无法直接实现 1.5 倍的分频。因此采取分别采取 2 个计数器 pos_cnt 和 neg_cnt,分别对上升沿和下降沿计数。计数周期是 0-1-2,共计 3 个时钟周期。

我们取 pos_cnt == 2'd1 的时候 div_pos输出高电平,neg_cnt == 2'd1 的时候 div_neg输出高电平。
由于 div_pos和 div_neg输出 1 个时钟的高电平,但是相位相差 180°,因此只要执行 div3_o = div_pos|div_neg运算,就能实现 1.5 倍周期的输出高电平,那么剩余的 1.5 倍源时钟周期就是输出低电平了。

时序图分析:

 三分频verilog代码

module clk_divider
(
	input sys_clk,
	input sys_rst_n,
	output clk_div_o
);

reg [1:0] pos_cnt,neg_cnt;
reg div_pos,div_neg;

//上升沿计数器
always@(posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n)
	pos_cnt <= 0;
else if(pos_cnt == 2'd2) //
	pos_cnt <= 0;
else
	pos_cnt <= pos_cnt + 1'b1;
end
//下降沿计数器
always@(negedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n)
	neg_cnt <= 0;
else if(neg_cnt == 2'd2)
	neg_cnt <= 0;
else
	neg_cnt <= neg_cnt + 1'b1;
end

//上升沿电平变换
always@(posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n)
	div_pos <= 0;
else if(pos_cnt < 2'd1)
	div_pos <= 1;
else
	div_pos <= 0;
end
//下降沿电平变换
always@(negedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n)
	div_neg <= 0;
else if(neg_cnt < 2'd1 )
	div_neg <= 1;
else
	div_neg <= 0;
end
//输出相或
assign clk_div_o = div_pos | div_neg;
endmodule

Testbench 

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

	reg sys_clk;
	reg sys_rst_n;
	wire clk_div_o;


parameter T = 20;
always #(T/2) sys_clk = ~sys_clk;


clk_divider clk_divider_inst
(
	.sys_clk(sys_clk) ,
	.sys_rst_n(sys_rst_n) ,
	.clk_div_o(clk_div_o)
);


initial begin
	sys_clk = 0;
	sys_rst_n = 0;
	#50;
	sys_rst_n = 1;
end

endmodule

 仿真示意图 ,clk_div_o 高低电平各占1.5个时钟周期

 五分频

三分频,每1.5个时钟周期就要翻转一次,因此我们通过时钟上升沿构造低电平占1个时钟周期,高电平占2个时钟周期的信号,再通过时钟的下降沿产生相同的信号,这相当与把原信号右移了半个时钟周期,相与后高电平被削掉了半个周期,低电平添了半个周期,就产生了1.5个时钟周期翻转一次的效果。

五分频类似。

由此猜测11分频可以由上升沿构造低电平占5个时钟周期,高电平占6个时钟周期的信号产生。

五分频的思想是用一个上升沿的计数器计 0-4,上升沿和下降沿分别计数,高电平2个周期,低电平3个周期,2者相与

 Verilog实现

module clk_div5
(
	input sys_clk,
	input sys_rst_n,
	output clk_div_o
);

reg [2:0] clk_cnt;
reg div_pos,div_neg;

//上升沿计数器 clk_cnt=0-4
always@(posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n)
	clk_cnt <= 0;
else if(clk_cnt == 3'd4) //
	clk_cnt <= 0;
else
	clk_cnt <= clk_cnt + 1'b1;
end


//上升沿计数高电平2个周期 低电平3个周期
always@(posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n)
	div_pos <= 1'b1;
else if(clk_cnt < 3'd3)
	div_pos <= 1'b1;
else
	div_pos <= 0;
end

//下降沿计数高电平2个周期 低电平3个周期
always@(negedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n)
	div_neg <= 1'b1;
else if(clk_cnt < 3'd3 )
	div_neg <= 1'b1;
else
	div_neg <= 0;
end

//输出相与
assign clk_div_o = div_pos & div_neg;
endmodule 

Tb 还用上面的

 

任意分频等后面再写吧

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值