首页 > 其他分享 >verilog时序单元分频器

verilog时序单元分频器

时间:2023-07-22 10:23:05浏览次数:44  
标签:分频 分频器 clk 时序 计数 计数器 verilog rst div

分频电路

2.2.1 简单的计数器

计数器实质是对输入的驱动时钟进行计数,所以计数器在某种意义上讲,等同于对时钟进行分频。例如一个最大计数长度为N=2^M(从0计数到N-1)的计数器,也就是寄存器位数为M,那么寄存器最高位的输出为N=2^M分频,次高位为N/2分频...例如下面的代码:

module test#(parameter N=3)(
input clk,
input rst_n,
output clk_div  );
reg [N-1:0] div_reg        ;//分频计数器
assign clk_div = div_reg[N-1] ;
always @(posedge clk or negedge rst_n)
if (rst_n == 1'b0 )
    div_reg    <= 0 ;
else
    div_reg    <= div_reg + 1'b1 ;
endmodule

parameter例化方式

clk_div #(.N(3) ) u_clk_div(
       .clk(clk),
      .rst_n(rst_n),
       .clk_div(clk_div) );

该代码描述的将一个3位的计数器最高位输出,也就是计数长度为8(计数从0~7)波形如下所示:

可以看到最高位的输出为输入时钟的8分频。

当N不是2的整数次幂时,即N≠2^M时,从0计数到N-1,其最高位作为时钟输出(占空比不一定为 1:1)是输入时钟的1/N,也就是N分频。我们来举个例子,比如最大计数长度为5的计数器,即从0计数到4后又返回0,那么需要定义一个三位的寄存器。寄存器的计数过程为:

000-001-010-011-100-000-001-010-011-100-000-001-010-011-100-000-001-010-011-100······

我们取最高位,得到的信号变化就是:0-0-0-0-1-0-0-0-0-0-1-0-0-0-0-1-0-0-0-0-1···

 代码如下所示:

module test#(parameter N=3)(
input clk,
input rst_n,
output clk_div
);
reg [N-1:0] div_reg   ;//分频计数器
always @(posedge clk or negedge rst_n)
if (rst_n == 1'b0 )      
div_reg    <= 0 ;
else if(div_reg == 3'd4)
//从0计数到4,然后返回到0,5分频
     div_reg    <= 0;
else
     div_reg    <= div_reg + 1'b1 ;
assign clk_div = div_reg[N-1] ;
endmodule

由此可以看到,每一个分频后的时钟周期=5倍原来的时钟周期,因此是5分频。 

那么这个情况是不是也可以包含8分频的情况呢?我们设置为8分频,即前面的3'd4改成3'd7,得到的仿真波形如下所示:

可以看到,计数器的最高位输出也是输入频率的1/N。

因此我们得到结论:一个最大计数长度为N(从0计数到N-1)的计数器,其最高位的输出,是输入频率的N分频。

通常 ASIC 和 FPGA 中,时钟都是全局信号,都需要通过 PLL 处理才能使用,但某些简易场合,采用计数器输出时钟也是能够使用的,只是需要注意时序约束。

偶数倍分频(占空比50%)

偶数分频,也就是2分频、4分频、6分频...这个还是比较简单的,N(N当然是2的倍数)分频,那么计数到N/2-1,然后时钟翻转,例如N=6时,代码如下所示:

module test#(parameter N=6)(
input clk,
input rst_n,
output clk_div
);
reg div_reg ;
reg [N-1:0] div_cnt        ;//分频计数器
always @(posedge clk or negedge rst_n)
    if (rst_n == 1'b0 )begin
        div_cnt    <= 0 ;
 div_reg    <= 0 ;
  end
 else if(div_cnt == (N/2 - 1))begin
        div_cnt    <= 0;
        div_reg    <= ~div_reg ;
    end
    else
        div_cnt    <= div_cnt + 1'b1 ;
assign clk_div = div_reg ;
endmodule

当N=2的仿真波形如下所示

奇数倍分频

①占空比接近50%

对于占空比不是50%的计数分频,我们可以直接用上面的计数器方法,这里就不说了,我们介绍其他接近50%的占空比的方法,比如下面使用的状态机分频:

      

上图的状态机除了用一般的状态机设计方式之外,我们也可以用简单的计数器实现,这种方法如下所示:

假设时钟分频是N,则设置一个计数器,计数长度是N(即从0计数到N-1),然后在计数器为计数到(N-1)/2的时候,翻转一下分频时钟信号;在计数器计数到为N-1的时候,再翻转一下时钟。代码如下所示:

module test#(parameter N=3)(
//N分频,这里是3分频
input clk,
input rst_n,
output clk_div
);
reg [N-1:0] div_cnt     ;//分频计数器
reg div_reg ;
always @(posedge clk or negedge rst_n)begin
    if (rst_n == 1'b0 )begin
        div_cnt <= 0 ;
        div_reg <= 1 ;
end
else if (div_cnt == (N-1)/2)begin
//计数到(N-1)/2,进行翻转和继续计数
  div_reg <= ~div_reg;
        div_cnt <= div_cnt + 1'b1 ;
end
else if ( div_cnt == (N-1) )begin
//计数到N-1,进行清零和翻转
        div_cnt <= 0 ;
        div_reg <= ~div_reg;
end
else
        div_cnt <= div_cnt + 1'b1 ;
end
assign clk_div = (N == 1)?clk:div_reg ;
//注意这里
endmodule

分频,N=3: 

分频,N=5:

奇数分频(占空比50%)

产生具有50%占空比的奇数分频时钟的算法如下所示,假设N分频(N是计数):

设置一个计数长度为N的上升沿计数器,和一个信号寄存器;信号寄存器在上升沿计数器为(N-1)/2的时候进行翻转,然后再在计数到N-1的时候进行翻转(这里相当于得到一个N分频信号A)。

再设置一个计数长度为N的下降沿计数器,和另一个信号寄存器;信号寄存器在下降沿计数器为(N-1)/2的时候进行翻转,然后再在计数到N-1的时候进行翻转(这里相当于得到一个N分频信号B)。

将A和B相或就可以得到占空比50%的奇数分频信号;代码实现如下:

module test#(parameter N=5)(//N分频
input clk,
input rst_n,
output clk_div
);
reg sig_r ;//定义一个上升沿翻转的信号
reg sig_f ;//定义一个下降沿翻转的信号
reg [N-1:0]    cnt_r;//上升沿计数器
reg [N-1:0]    cnt_f;//下降沿计数器
wire clk_f ;
assign clk_f = ~clk ;
/*用来触发下降沿计数器的时钟,由于同时使用上升沿和下降沿触发器不好,因此我们为同一边沿,都使用上升沿触发,只不过是将时钟进行反向*/
always @(posedge clk or negedge rst_n)begin
//上升沿计数
    if(rst_n == 1'b0)begin
        sig_r <= 0 ;
        cnt_r <= 0 ;
end
else if( cnt_r == (N-1)/2 )begin
        sig_r <= ~sig_r ;
        cnt_r <= cnt_r + 1 ;
end
else if ( cnt_r == (N-1) )begin
        sig_r <= ~sig_r ;
        cnt_r <= 0 ;
end
else
        cnt_r <= cnt_r + 1 ;
end
always @(posedge clk_f or negedge rst_n)begin
//下降沿计数
    if(rst_n == 1'b0)begin
        sig_f    <= 0 ;
        cnt_f    <= 0 ;
end
else if( cnt_f == (N-1)/2 )begin
        sig_f    <= ~sig_f ;
        cnt_f    <= cnt_f + 1 ;
end
else if ( cnt_f == (N-1) )begin
        sig_f    <= ~sig_f ;
        cnt_f    <= 0 ;
end
else
        cnt_f    <= cnt_f + 1 ;
end
assign clk_div = sig_f || sig_r ;
endmodule 

奇数分频

若是奇数分频,则处理比较特殊,以5分频器为例,其要求产生的时序关系如下图所示

 

很显然,该电路要用上MCLK的上沿和下研,对上图时序进行分解,得下图: 

图中, COUNT0采用上沿计数, COUNT1采用下沿计数, DIV0和DIV1是分别是上沿触发器和下沿触发器的输出, DIV5_CLK是DIV0和DIV1的或门输出。

利用上升下降沿计数,刚好在一个计数周期内,经过或门之后,高电平时间加半个周期,低电平时间减半个周期,刚好使得50%占空比计数。

在使用该电路时,需要注意:

(1)DIV0和DIV1到DIV5_CLK的约束要严,越快越好。不然,无法保证1:1的占空比。
(2)MCLK频率要求较高,尽量不要出现窄脉冲,尤其是在高频电路里。
(3)COUNT1可有可无,视时钟频率高低而定。频率越高, COUNT1越需要。

50%占空比 2430分频器

我们推荐使用同步计数器最高位的方法,如果需要保证占空比,可以使用下图所示电路进行最后一次二分频。下图是19.44MHz分频到8kMHz(分频数为2430)的电路:计数到N/2-1清零。

分频数为2430的电路

module div_clk #(parameter N=11)(
input      clk,
input      rst_n,
output    clk_div
);
reg [N-1:0]    cnt_r;//上升沿计数器
always @(posedge clk or negedge rst_n)
if(rst_n == 1'b0)
cnt_r <= 0 ;
else if( cnt_r == 11'd1214 )
cnt_r <= 0 ;
else
cnt_r <= cnt_r+1 ;
wire ENA=(cnt_r==11'd1214);
reg Q;    
always@(posedge clk  or negedge rst_n)
if(rst_n==1'b0)begin
Q=1'b0;
end
else if(ENA)
Q<=~Q;
else
Q<=Q;   
       assign clk_div = Q;
 endmodule

分数分频(待补充)

边沿检测电路

上升沿检测电路

采用时钟检测信号,出现0->1的变化即为上升沿。当被测信号与时钟相关时,可以不用第一个触发器。

下降沿检测

采用时钟检测信号, 出现1->0的变化即为下降沿。 当被测信号与时钟相关时, 可以不用第一个触发器。

2.3.3 上升/下降沿检测

标签:分频,分频器,clk,时序,计数,计数器,verilog,rst,div
From: https://www.cnblogs.com/lanlancky/p/17572923.html

相关文章

  • java时序图怎么画
    项目简介本项目旨在提供一个方便易用的工具,用于生成Java程序的时序图。时序图是一种用于可视化展示对象之间交互的UML图形。通过生成时序图,开发人员可以更加清晰地了解程序的执行流程,方便分析和调试。方案提案1.确定需求在开始项目之前,我们首先需要明确项目的具体需求。在本项......
  • 时序特征构造
    信贷时序数据与特征工程介绍--求是汪1.常规统计特征把客户行为按最小时间粒度统计完毕后,我们就会得到一个分布。接下来则是利用统计函数最大值(MAX)、最小值(MIN)、平均值(AVG)、标准差(STD)来描述以上分布特征。但是,这些指标在统计时只能对给定的数据集合计算,没有考虑到时间序列变化......
  • TDengine 的查询性能与老牌时序数据库相比如何?来看看
    在上一篇文章《IoT场景下写入性能:TDengine=16.2xInfluxDB》中,我们基于IoT场景下的TSBS时序数据库(TimeSeriesDatabase)性能基准测试报告对三大数据库写入性能进行了相关解读,较为直观地展现出了TDengine的众多写入优势。本篇文章将以查询性能作为主题,给IoT场景下正在为......
  • m基于FPGA的各类存储器纯Verilog实现,包含testbench,包括RAM,SRAM等
    1.算法仿真效果本系统进行了Vivado2019.2平台的开发,Vivado2019.2仿真结果如下: ram   SRAM   2.算法涉及理论知识概要        FPGA(FieldProgrammableGateArray)是一种可编程逻辑器件,具有可重构性、高速度、低功耗等特点,被广泛应用于数字电路设计......
  • m基于FPGA的带相位偏差64QAM调制信号相位估计和补偿算法verilog实现,包含testbench
    1.算法仿真效果 本系统进行了Vivado2019.2平台的开发,其中Vivado2019.2仿真结果如下:   将FPGA的仿真结果导入到matlab中,显示星座图,结果如下所示:    2.算法涉及理论知识概要         在现代通信系统中,调制技术是实现高速数据传输和频谱效率优化的......
  • m基于FPGA的1024QAM调制信号产生模块verilog实现,包含testbench
    1.算法仿真效果本系统进行了Vivado2019.2平台的开发,Vivado2019.2仿真结果如下:将1024调制信号导入到matlab显示星座图2.算法涉及理论知识概要本文将详细介绍基于FPGA的1024QAM调制信号产生模块。本文将从以下几个方面进行介绍:1024QAM调制信号的基本原理、符号映射方式、并行化......
  • m基于FPGA的带相位偏差64QAM调制信号相位估计和补偿算法verilog实现,包含testbench
    1.算法仿真效果本系统进行了Vivado2019.2平台的开发,其中Vivado2019.2仿真结果如下:将FPGA的仿真结果导入到matlab中,显示星座图,结果如下所示:2.算法涉及理论知识概要在现代通信系统中,调制技术是实现高速数据传输和频谱效率优化的重要手段。其中,64QAM调制技术是一种常见的高......
  • m基于FPGA的1024QAM调制信号产生模块verilog实现,包含testbench
    1.算法仿真效果 本系统进行了Vivado2019.2平台的开发,Vivado2019.2仿真结果如下:   将1024调制信号导入到matlab显示星座图  2.算法涉及理论知识概要       本文将详细介绍基于FPGA的1024QAM调制信号产生模块。本文将从以下几个方面进行介绍:1024QAM调制信......
  • verilog数的表示和定点化
    1.数的表示1.1数制转换十进制整数转换成其他进制数:“除基取余”:十进制整数不断除以转换进制基数,直至商为0。每除一次取一个余数,从低位排向高位。十进制小数转换成其他进制数:乘基取整,直至ε,高位到低位;“乘基取整”:用转换进制的基数乘以小数部分,直至小数为0或达到转换精度要求的......
  • IoT 场景下 TDengine 与老牌时序数据库怎么选?看看这份TSBS报告
    上周一,TDengine正式发布了IoT场景下基于TSBS的时序数据库(TimeSeriesDatabase,TSDB)性能基准测试报告。该报告模拟虚拟货运公司车队中一组卡车的时序数据,预设了五种卡车规模场景,在相同的AWS云环境下运行了TDengine3.0、TimescaleDB2.10.1和InfluxDB1.8.10,从四大维度进......