首页 > 编程知识 正文

verilog语言数字时钟,时钟分频模块

时间:2023-05-05 04:06:15 阅读:153111 作者:1591

1.偶分频模块设计

偶分频意味着时钟模块的设计是最简单的。 首先得到分频系数m和计数器值n。

M=时钟输入频率/时钟输出频率

N=M/2

如果输入时钟为50M,输出时钟为25M,则M=2,N=1。 偶数分频意味着m是偶数。

以M=4,N=2为例,我们希望得到的输出时钟时序如下:

因此,counter可被计数为clk_in作为时钟驱动,且可在counter=(N-1 )时反转clk_out。

verilog代码如下,其中WIDTH为(N的位宽-1):

module time _ adv _ even # (parameter n=2,WIDTH=7) (input clk,input rst,output reg clk_out ); reg [ width :0 ]计数器; always@(posedgeclkorposedgerst ) beginif ) rst ) begin//resetcounter=0; endelseif(counter==n-1 ) begincounter=0; endelse begincounter=counter 1; 结束always @ (posedgeclkorposedgerst ) beginif ) rst ) begin//resetclk_out=0; endelseif(counter==n-1 ) beginclk_out=! clk_out; 结束模块

testbench测试8分频即N=4,ISE仿真结果如下:

2.奇分频模块设计

奇分频需要由两个时钟共同获得。 首先得到分频系数m和计数器值n。

M=时钟输入频率/时钟输出频率

n=(m-1 )/2

如果输入时钟为50M,输出时钟为10M,则M=5,N=2。 奇分频意味着m是奇数。

以M=5,N=2为例,我们希望得到的输出时钟时序如下:

这里,clk_out是最终输出时钟,clk_out1和clk_out2是辅助时钟生成部。

计数器counter从0技术到(M-1 )。

clk_out1通过clk_in中的上升来延长跳跃,条件为counter==(N-1 )或(M-1 )。

clk_out2通过clk_in的下降来延长转移。 条件为counter==(N-1 )或(M-1 )。

然后,通过clk_out=clk_out1 clk_out2获得m分频的时钟。

verilog代码如下,其中WIDTH为(N的位宽-1):

module time _ adv _ odd # (parameter n=2,WIDTH=7) (input clk,input rst,output clk_out ); reg [ width :0 ]计数器; always@(posedgeclkorposedgerst ) beginif ) rst ) begin//resetcounter=0; endelseif(counter==(n1 ) ) begincounter=0; endelse begincounter=counter 1; endendreg clk_out1; always@(posedgeclkorposedgerst ) beginif ) rst ) begin//resetclk_out1=0; endelseif(counter==n-1 ) beginclk_out1=! clk_out1; endelseif(counter==(n1 ) ) beginclk_out1=! clk_out1; endendreg clk_out2; always@(negedgeclkorposedgerst ) beginif ) rst ) begin//resetclk_out2=0; endelseif(counter==n-1 ) beginclk_out2=! clk_out2; endelseif(counter==(n1 ) ) beginclk_out2=! clk_out2; endendassignclk _ out=clk _ out1clk _ out 2; 结束模块

在testbench测试9分频即N=4时,ISE模拟结果如下。

p>3.半分频模块设计

半分频即2.5分频等,设计最为复杂。首先得到分频系数M:

M = 时钟输入频率 / 时钟输出频率

如输入为50M,输入为20M则分频系数为2.5。此次设计未能完成占空比为50%的半分频。

以M=2.5为例,我们希望得到的输出时钟时序如下:

可以看出输出时钟的两个上升沿之间为2.5个输入时钟周期。

设计的关键在于信号维持半个周期的处理,因此引入了辅助信号clk_cnt,clk_vld。

clk_vld信号受到clk_out的驱动,检测到clk_out的上升沿时,信号翻转。

clk_cnt信号受到clk_in驱动,受clk_vld控制,当clk_vld==0时,clk_cnt = clk_in;当clk_vld==1时,clk_cnt = !clk_in。

counter信号受clk_cnt驱动,计数(M-0.5)时归零。

clk_out信号受clk_cnt驱动,当counter == (M-1.5)或counter == (M-0.5)时翻转。(此处在仿真时做了改变,见下方)

M=2.5时,时序分析如下:

第一步:reset之后,clk_vld==0,clk_cnt = clk_in,counter由0开始计数;

第二步:counter == 1时,clk_out在clk_cnt的上升沿处跳变为1,引起clk_vld->1,进而clk_cnt = !clk_in,这意味着clk_cnt立即由1归为0;

第三步:半个周期后,clk_cnt 在此迎来上升沿,此时counter == 2,clk_out在clk_cnt的上升沿处跳变为0,counter也归0;(实现了信号维持半个周期)

第四步:继续正常计数,counter == 1时,clk_out在clk_cnt的上升沿处跳变为1,引起clk_vld->0,进而clk_cnt = clk_in,这意味着clk_cnt立即由1归为0;

第五步:重复至第一步。

然而在有一次的电路仿真中,可能受到仿真工具时钟采样影响,调整为

当counter == (M-0.5)或counter == 0时翻转

实现了正确的时钟分频。因此该值可能需要根据工具和开发板调整,或者说这样的设计是不可靠的,当然了如果需要半分频时候最好还是通过pll实现吧。

理论上是当counter == (M-0.5)或counter == (M-1.5)时翻转没错,给出的代码和波形也是这样的。

verilog代码如下,参数M实际为分频系数-0.5(即3.5->3),WIDTH为(M的位宽-1):

module time_adv_half #(parameter M = 2,WIDTH = 7)( input clk, input rst, output reg clk_out );wire clk_cnt;assign clk_cnt = (clk_vld) ? !clk : clk;reg [WIDTH : 0]counter;always @(posedge clk_cnt or posedge rst) beginif (rst) begin// resetcounter <= 0;endelse if (counter == M) begincounter <= 0;endelse begincounter <= counter + 1;endendreg clk_vld;always @(posedge clk_out or posedge rst) beginif (rst) begin// resetclk_vld <= 0;endelse beginclk_vld <= !clk_vld;endendalways @(posedge clk_cnt or posedge rst) beginif (rst) begin// resetclk_out <= 0;endelse if (counter == M-1) beginclk_out <= !clk_out;endelse if (counter == M) beginclk_out <= !clk_out;endendendmodule

M=3时候的仿真波形如下:


可以看出clk_out两个上升沿之间为3.5个输入时钟周期。

附:testbench

`timescale 1 ns / 1 psmodule TEST_gate;reg clk, rst;wire clk_out_even, clk_out_odd, clk_out_half;initial begin clk = 1'b0; forever #10 clk = ~clk; endinitial begin rst = 1'b0; #2 rst = 1'b1; #9 rst = 1'b0; end time_adv_even #( .N(4),.WIDTH(5) )u0( .clk (clk) ,.rst (rst) ,.clk_out (clk_out_even) );time_adv_odd #( .N(4),.WIDTH(5) )u1( .clk (clk) ,.rst (rst) ,.clk_out (clk_out_odd) );time_adv_half #( .M(3),.WIDTH(5) )u2( .clk (clk) ,.rst (rst) ,.clk_out (clk_out_half) );endmodule

波形

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。