环球新消息丨12-分频器 -偶分频
                  来源:博客园
                  •
                  2023-05-26 02:16:16
                
               (资料图)
(资料图)
计数器是对于时钟信号进行计数,板载晶振的时钟频率是固定的,有时候需要进行分频和倍频才能满足需要开发板上只有一种晶振,只有一种频率的时钟,想要通过对与固定时钟进行分频或者是倍频的方式得到各个模块所需的时钟频率,得到比固定时钟快的时钟通过倍频,得到比固定时钟慢的时钟通过分频
分频和倍频都有两种方式:第一种是通过锁相环(PLL),另外一种是编写verilog代码分频器是数字系统设计中最常见的基本电路之一,所谓分频就是把输入信号的频率变成成倍数地低于输入频率的输出信号分频器原理是将输入的信号做为计数脉冲,计数器的输出端口的脉冲是按一定频率输出的,就可以看作是输出端口的分频分频器分为偶数分频器和奇数分频器,分频器和计数器非常类似,有时可以认为是同一种东西2.FPGA实现实现对于固定时钟6分频的电路2.1 模块框图和波形图2.2 RTLmodule divider_six(  input wire sys_clk,  input wire sys_rst_n,    output reg clk_out);  reg [1:0] cnt;    // cnt变量  always@(posedge sys_clk or negedge sys_rst_n)    if(sys_rst_n == 1"b0)      cnt <= 2"d0;    else if(cnt == 2"d2)      cnt <= 2"d0;    else      cnt <= cnt + 2"d1;  always@(posedge sys_clk or negedge sys_rst_n)    if(sys_rst_n == 1"b0)      clk_out <= 1"b0;    else if(cnt == 2"d2)      clk_out <= ~clk_out;    else       clk_out <= clk_out;endmodule`timescale 1ns/1nsmodule tb_divider_six();  reg sys_clk;  reg sys_rst_n;    wire [1:0] clk_out;  // 初始化时钟和复位信号  initial begin    sys_clk = 1"b0;    sys_rst_n = 1"b0;    #20;    sys_rst_n = 1"b1;  end      // 模拟时钟信号  always #10 sys_clk = ~sys_clk;    // 模块的实例化  divider_six divider_six_inst(    .sys_clk (sys_clk),    .sys_rst_n (sys_rst_n),    .clk_out (clk_out)  );endmodulemodule divider_six(  input wire sys_clk,  input wire sys_rst_n,    // output reg clk_out  output reg clk_flag;);  reg [2:0] cnt;    // cnt变量  always@(posedge sys_clk or negedge sys_rst_n)    if(sys_rst_n == 1"b0)      cnt <= 2"d0;    else if(cnt == 3"d5)      cnt <= 3"d0;    else      cnt <= cnt + 3"d1;  always@(posedge sys_clk or negedge sys_rst_n)    if(sys_rst_n == 1"b0)      clk_flag <= 1"b0;    else if(cnt == 3"d4)    // flag信号是在计数最大值减一的时候产生一个周期脉冲      clk_flag <= 1"b1;    else       clk_flag <= 1"b0;  // 按照之前产生的分频时钟给变量a赋值   reg a ;  always @(posedge clk_out or negedge sys_rst_n) // 使用产生的分频时钟clk_out    if(sys_rst_n == 1"b0)      a <= 1"b0;      else       a <= a + 1"b1;  // 时钟标志位产生的分频时钟对于变量进行赋值  always@(posedge sys_clk or sys_rst_n)     // 仍然使用系统时钟,更加稳定    if(sys_rst_n == 1"b0)       a <= 1"b0;    else if(cnt_flag == 1"b1)      a <= 1"b1;  endmodule`timescale 1ns/1nsmodule tb_divider_six();  reg sys_clk;  reg sys_rst_n;    wire [2:0] clk_flag;  // 初始化时钟和复位信号  initial begin    sys_clk = 1"b0;    sys_rst_n = 1"b0;    #20;    sys_rst_n = 1"b1;  end      // 模拟时钟信号  always #10 sys_clk = ~sys_clk;    // 模块的实例化  divider_six divider_six_inst(    .sys_clk (sys_clk),    .sys_rst_n (sys_rst_n),    .clk_flag (clk_flag)  );endmodule产生一个用于标记 6 分频的 clk_flag 标志信号,这样每两 clk_flag 脉冲之间的频率就是对 sys_clk 时钟信号的 6 分频,但是计数器计数的个数我们需增加一些,如图 18-4 所示需要从 0~5 共 6 个数,否则不能实现 6 分频的功能。和方法 1 对比可以发现,相当于把 clk_out 的上升沿信号变成了 clk_flag 的脉冲电平信号cnt_flag 是一样的道理),为后级模块实现相同的降频效果。**虽然这样会多使用一些寄存器资源,不过不用担心我们的系统是完全可以承担的起的,而得到的好处却远远大于这点资源的使用,能让系统更加稳定。在后级模块中需要使用低频时钟的情况,我们就可以不用 clk_out 这种信号作为时钟了,而是继续使用 sys_clk 系统时钟来作为时钟,但让其执行语句的条件以 clk_flag 信号为高电平的时候有效。
关键词:
 
              
              
             
             
                     
                     
                     
                     
                     
                     
                     
                     
                     
                     
                     
                     
                     
                     
                     
                    