笨笨笔记---分频器的设计

本文介绍了分频器的基本概念和三种常见的分频方法:纯粹计数法、偶数分频和奇数分频。通过Verilog代码展示了如何设计不同类型的分频器,包括2的幂次方分频、非2的幂次方分频以及奇数分频,并提供了参数化的表达方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

<!-- /* Font Definitions */ @font-face {font-family:宋体; panose-1:2 1 6 0 3 1 1 1 1 1; mso-font-alt:SimSun; mso-font-charset:134; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:3 135135232 16 0 262145 0;} @font-face {font-family:"/@宋体"; panose-1:2 1 6 0 3 1 1 1 1 1; mso-font-charset:134; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:3 135135232 16 0 262145 0;} /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-parent:""; margin:0cm; margin-bottom:.0001pt; text-align:justify; text-justify:inter-ideograph; mso-pagination:none; font-size:10.5pt; mso-bidi-font-size:12.0pt; font-family:"Times New Roman"; mso-fareast-font-family:宋体; mso-font-kerning:1.0pt;} p {mso-margin-top-alt:auto; margin-right:0cm; mso-margin-bottom-alt:auto; margin-left:0cm; mso-pagination:widow-orphan; font-size:12.0pt; font-family:宋体; mso-bidi-font-family:宋体;} /* Page Definitions */ @page {mso-page-border-surround-header:no; mso-page-border-surround-footer:no;} @page Section1 {size:595.3pt 841.9pt; margin:72.0pt 90.0pt 72.0pt 90.0pt; mso-header-margin:42.55pt; mso-footer-margin:49.6pt; mso-paper-source:0; layout-grid:15.6pt;} div.Section1 {page:Section1;} -->

2011 1 10 17 24 58

分频方法解析

分频是最基本的操作之一,根据系数不同,有偶数分频,奇数分频,小数分频之分,根据使用的方法不同有:纯粹计数器法,单一计数器法,双重计数器法,奇数分频根据信号的生成方式,有与法,或法。

一:纯粹计数法(利用最高数据位的自然溢出)

如果是 25MHz 的时钟,那么这里利用数据的自然溢出,也就是取其最高位,而得到其输出频率为: 25000000/65536=381Hz ,周期为 1/381s ,则高电平时间为 1/(2*381)s ,其对应的计数值为: 32768

module music(clk, speaker);
input clk;
output speaker;

// Binary counter, 16-bits wide
reg [15:0] counter;
always @(posedge clk) counter <= counter+1;

// Use the highest bit of the counter (MSB) to drive the speaker
assign speaker = counter[15];//
只要 counter>=32767 ,那么 counter[15] 就等于 1 了,因为这里的计数是自然溢出的,所以低于 32767 和高于 32767 数据刚好各占用一半,所以占空比就是 50% 了。
endmodule

其中 counter[0] 的频率是 12.5MHz counter[1] 的频率是 6.125MHz ,以此类推。它是按照 2 n+1 次方来分频的,且是方波。

 

分频率为 440Hz ,这时就要除另外一个数了 440=25M/56818 ,代码如下:

module music(clk, speaker);
input clk;
output speaker;

reg [15:0] counter;
always @(posedge clk) if (counter==56817) counter <= 0; else counter <= counter+1;

assign speaker = counter[15];//
因为这里 56817 大于 32767 ,所以 counter[15] 还是会大于 1
endmodule

但是这里有个问题,其占空比不是 50 ,而是 42% (56817 32768 /56817 ),为了得到占空比为 50% 的信号,最简单的方法是加一个中间信号,所以我们先除以 28409(56818/2) ,然后再除 2.

module music(clk, speaker);
input clk;
output speaker;

reg [14:0] counter;
always @(posedge clk) if(counter==28408) counter <= 0; else counter <= counter+1;

reg speaker;//
注意,这里不是利用最高位和自然溢出了,而是利用达到最高位翻转
always @(posedge clk) if(counter==28408) speaker <= ~speaker; // 信号翻转,也就是除以 2
endmodule

参数化的表达方法

module music(clk, speaker);
input clk;
output speaker;
parameter clkdivider = 25000000/440/2;

reg [14:0] counter;
always @(posedge clk) if (counter==0) counter <= clkdivider-1; else counter <= counter-1;

reg speaker;
always @(posedge clk) if (counter==0) speaker <= ~speaker;//
信号翻转,也就是除以 2
endmodule

 

二:偶数分频

       假设分频系数为 N( 偶数 ) ,则计数器的值计算从 0~N/2 ,然后信号翻转

module N_bit_even_divider (

output reg o_clk,
input       i_clk,
input       rst_n
);

parameter N = N_even; // 设置偶数倍分频

parameter M = ?;      // M="N/2-1"

// bit_of_N: N_even 的二进制位宽
reg [(bit_of_N - 1):0] cnt; //
计数器单元

// 上升沿计数 : 0~(N-1)
always @ (posedge i_clk, negedge rst_n)
begin
if (!rst_n)
   cnt <= 0;
else
begin
    if (cnt == N-1)
      cnt <= 0;
    else
      cnt <= cnt + 1'b1;//
这里将计数和根据计数值来输出电平,分开来做,这符合低级建模的思想
end
end

// 生成上升沿时钟
// 0~(N/2-1) ↑ -> 1; (N/2)~(N-1) ↑ -> 0
always @ (posedge i_clk, negedge rst_n)
begin
if (!rst_n)
    o_clk <= 0;
else
begin
    if (cnt <= M)

      o_clk <= 1;// 在小于 N/2 时,输出 1 ,大于 N/2 时,输出 0
    else
      o_clk <= 0;//
这里信号是人为的规定其高低值,和下面的手动翻转功能是一样的,个人喜欢用下面的方式
   end
end

endmodule

 

module odd_division(clk,rst,count,clk_odd);     /*count 没必要放在端口中,这里只是为了仿真时观察 */

input        clk,rst;

output       clk_odd;

output[3:0] count;

reg          clk_odd;

reg[3:0]     count;

parameter    N = 6;                     /*6 分频 * /

    always @ (posedge clk)

      if(! rst)

        begin

          count <= 1'b0;

          clk_odd <= 1'b0;

        end

      else      

        if ( count < N/2-1)

          begin          

            count <= count + 1'b1;            

          end

        else

          begin        

            count <= 1'b0; / / 赋值和信号输出是两部分动作,所以最好将其分开

            clk_odd <= ~clk_odd;  // 信号手动翻转     

          end

endmodule

 

       从上面可以看出,根据低级建模的思想:可以将偶数分频代码分为两种实现方式,计数和输出分离式,计数和输出不分离式,显然前者更加符合低级建模的思想。

 

三:奇数分频

       根据最后输出频率的产生方式,可以分为两类:与式输出,或式输出。二者的输出占空比都为 50% 。另外,奇数分频使用了双边沿触发,这一点要注意。

本人在此基础上实现了任意kk 为大于等于2 的自然数)倍分频,只要输入一个k 就相应的产生一个占空比为50% 的时钟,而频率为输入时钟的1/k. 主要思想参照上面介绍的,内部两个计数器,一个在输入时钟上升沿计数,另一个在下降沿计数,当计数到k>>1-1k-1 时分别翻转,这样可以产生两 个时钟:上升沿产生的k 分频时钟clk1 ,下降沿产生的k 分频时钟clk2 ,当k 为奇数时,将两个时钟clk1clk2 进行与运算,就可以得出占空比为 50% 的奇数倍分频时钟;而当k 为偶数时,取clk1 就刚好是分频好了的,占空比为50% 的时钟。

      下面是程序

与式

module m1k(rst_n,clk,k,clkk);

input rst_n;
input clk;
input [3:0] k;
reg clk1;
reg clk2;

output clkk;
reg [3:0] k1;
reg [3:0] k2;


always@(negedge rst_n or posedge clk)
begin
  if(~rst_n)
    begin
    k1 <= 4'b0;
    clk1 <= 1'b0;
    end
  else
   begin
    if(k1==(k-1))
      clk1 <= ~clk1;
    if(k1==((k>>1)-1'b1))
       clk1 <= ~clk1;
   
    if(k1==k-1)
       k1 <= 4'b0000;
    else
       k1 <= k1+4'b0001;
   
   
    end
 
end

always@(negedge rst_n or negedge clk)
begin
  if(~rst_n)
    begin
    k2 <= 4'b0;
    clk2 <= 1'b0;
   end
  else
   begin
    if(k2 == k-1)
       k2 <= 4'b0000;
    else
       k2 <= k2+4'b0001;
    if(k2==k-1)
       clk2 <= ~clk2;
    if(k2==((k>>1)-1'b1))
       clk2 <= ~clk2;
    end
 
end
assign clkk = (k%2)?clk1&clk2:clk1;
endmodule

 

或式:

module even_division(clk,rst,count1,count2,clk_even); /*count1 count2 没必要放在端口中,这里只是为了仿真时观察*/

input        clk,rst;

output[3:0] count1,count2;

output       clk_even;

reg[3:0]     count1,count2;

reg          clkA,clkB;

wire         clk_even,clk_re;

parameter    N = 5;          /*5 分频*/

assign clk_re   = ~clk;

assign clk_even = clkA | clkB;

    always @(posedge clk)

      if(! rst)  

        begin

          count1 <= 1'b0;

          clkA <= 1'b0;          

        end

      else

        if(count1 < (N - 1))

         begin

         count1 <= count1 + 1'b1; // 注意这里应该是非阻塞赋值

            if(count1 == (N - 1)/2)

              begin

                clkA <= ~clkA; // 当计数到一半时,翻转信号

              end                

          end          

        else // 计数到最大时,再次翻转信号

          begin

            clkA <= ~clkA;

            count1 <= 1'b0;

          end          

          

always @ (posedge clk_re)

    if(! rst)

      begin

        count2 <= 1'b0;

        clkB <= 1'b0;

      end

    else

      if(count2 < (N - 1))

        begin

          count2 <= count2 + 1'b1;            

            if(count2 == (N - 1)/2)

              begin

                clkB <= ~clkB;

              end                

        end          

      else

        begin

          clkB <= ~clkB;

          count2 <= 1'b0;

        end          

endmodule

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Pixhawk源码笔记一:APM代码基本结构 ................................ ......... 4 基础知识 ................................ ................................ . 4 第一部分:介绍 ................................ ....................... 4 第二部分: 学习sketch例程代码 ................................ ...... 5 Pixhawk源码笔记二:APM线程 ................................ ................. 8 第三部分 APM线程 ................................ ................... 8 Pixhawk源码笔记三:串行接口UART和Console ................................ . 14 第四部分 串行接口UART和Console ................................ ... 14 Pixhawk源码笔记四:学习RC Input and Output ................................ ... 18 第五部分 学习RC Input and Output ................................ ... 18 Pixhawk源码笔记五:存储与EEPROM管理 ................................ ...... 23 第六部分 存储与EEPROM管理 ................................ ......... 23 Pixhawk源码笔记六:源码预览与APM:Copter程序库 ............................. 31 第七部分 源代码预览与APM:Copter程序库 ............................. 31 APM:Copter程序库 ................................ ................... 31 1 核心库 ................................ ............................ 32 2 传感器相关库 ................................ ...................... 32 3 其他库 ................................ ............................ 32 Pixhawk源码笔记七:姿态控制预览 ................................ ............ 34 第八部分 姿态控制预览 ................................ .............. 34 Pixhawk源码笔记八:添加新的参数 ................................ ............ 37 第九部分 添加新的参数 ................................ .............. 37 1 在主执行代码中添加参数 ................................ ............ 37 2 向库中添加参数 ................................ .................... 41 Pixhawk源码笔记九:添加新的飞行模式 ................................ ........ 45 第十部分 添加新的飞行模式 ................................ ........... 45 Pixhawk源码笔记十:代码调度,使之定时运行 ................................ .. 51 第十一部分 调用代码,使之定时运行 ................................ ... 51 1、用代码调度器(scheduler)运行你的代码 ............................ 51 2、作为循环的一部分运行你的代码 ................................ ..... 52 Pixhawk源码笔记十一:增加新的MAVLi
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值