计数器是对于时钟信号进行计数,板载晶振的时钟频率是固定的,有时候需要进行分频和倍频才能满足需要
开发板上只有一种晶振,只有一种频率的时钟,想要通过对与固定时钟进行分频或者是倍频的方式得到各个模块所需的时钟频率,得到比固定时钟快的时钟通过倍频,得到比固定时钟慢的时钟通过分频
module 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/1ns module 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) ); endmodule
module 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/1ns module 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 信号
为高电平的时候有效。