計數器是對於時鐘訊號進行計數,板載晶振的時脈頻率是固定的,有時候需要進行分頻和倍頻才能滿足需要
開發板上只有一種晶振,只有一種頻率的時鐘,想要通過對與固定時鐘進行分頻或者是倍頻的方式得到各個模組所需的時脈頻率,得到比固定時鐘快的時鐘通過倍頻,得到比固定時鐘慢的時鐘通過分頻
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 訊號
為高電平的時候有效。