这里对之前写的时钟分频模块做了整合,整合为完整的时钟分频模块,可以进行偶分频、奇分频和半分频。
接口如下:
clk:输入时钟
rst:复位信号
adv_select:分频类型选择,0->偶分频,1->奇分频,2->半分频
M:分频系数,在半分频情况下为向下取整(4.5分频->M=4)
clk_out:输出时钟
rst:复位信号
adv_select:分频类型选择,0->偶分频,1->奇分频,2->半分频
M:分频系数,在半分频情况下为向下取整(4.5分频->M=4)
clk_out:输出时钟
通过testbench进行了仿真,分别仿了4分频、9分频和5.5分频
initial begin
adv_select = 2'b00;
M = 4;
#1086 adv_select = 2'b01;
M = 9;
#1086 adv_select = 2'b10;
M = 5;
end
代码如下:
module work(
clk
,rst
,adv_select
,M
,clk_out
);
input clk, rst;
input [1:0]adv_select; //0->even 1->odd 2->half
input [31:0]M;
output clk_out;
wire clk_out_even, clk_out_odd, clk_out_half;
assign clk_out = (adv_select == 0) ? clk_out_even :
(adv_select == 1) ? clk_out_odd :
(adv_select == 2) ? clk_out_half : 0;
wire clk_even, clk_odd, clk_half;
assign clk_even = (adv_select == 0) ? clk : 0;
assign clk_odd = (adv_select == 1) ? clk : 0;
assign clk_half = (adv_select == 2) ? clk : 0;
time_adv_even u0
(
.clk (clk_even)
,.rst (rst)
,.M (M)
,.clk_out (clk_out_even)
);
time_adv_odd u1
(
.clk (clk_odd)
,.rst (rst)
,.M (M)
,.clk_out (clk_out_odd)
);
time_adv_half u2
(
.clk (clk_half)
,.rst (rst)
,.M (M)
,.clk_out (clk_out_half)
);
endmodulemodule time_adv_even
(
input clk,
input rst,
input [31:0]M,
output reg clk_out
);
wire [31:0]N;
assign N = M>>1;
reg [7:0]counter;
always @(posedge clk or posedge rst) begin
if (rst) begin
// reset
counter <= 0;
end
else if (counter == N-1) begin
counter <= 0;
end
else begin
counter <= counter + 1;
end
end
always @(posedge clk or posedge rst) begin
if (rst) begin
// reset
clk_out <= 0;
end
else if (counter == N-1) begin
clk_out <= !clk_out;
end
end
endmodulemodule time_adv_odd (
input clk,
input rst,
input [31:0]M,
output clk_out
);
wire [31:0]N;
assign N = (M-1)>>1;
reg [7:0]counter;
always @(posedge clk or posedge rst) begin
if (rst) begin
// reset
counter <= 0;
end
else if (counter == (N << 1)) begin
counter <= 0;
end
else begin
counter <= counter + 1;
end
end
reg clk_out1;
always @(posedge clk or posedge rst) begin
if (rst) begin
// reset
clk_out1 <= 0;
end
else if (counter == N-1) begin
clk_out1 <= !clk_out1;
end
else if (counter == (N << 1)) begin
clk_out1 <= !clk_out1;
end
end
reg clk_out2;
always @(negedge clk or posedge rst) begin
if (rst) begin
// reset
clk_out2 <= 0;
end
else if (counter == N-1) begin
clk_out2 <= !clk_out2;
end
else if (counter == (N << 1)) begin
clk_out2 <= !clk_out2;
end
end
assign clk_out = clk_out1 & clk_out2;
endmodulemodule time_adv_half(
input clk,
input rst,
input [31:0]M,
output reg clk_out
);
wire clk_cnt;
assign clk_cnt = (clk_vld) ? !clk : clk;
reg [7:0]counter;
always @(posedge clk_cnt or posedge rst) begin
if (rst) begin
// reset
counter <= 0;
end
else if (counter == M) begin
counter <= 0;
end
else begin
counter <= counter + 1;
end
end
reg clk_vld;
always @(posedge clk_out or posedge rst) begin
if (rst) begin
// reset
clk_vld <= 0;
end
else begin
clk_vld <= !clk_vld;
end
end
always @(posedge clk_cnt or posedge rst) begin
if (rst) begin
// reset
clk_out <= 0;
end
else if (counter == M-1) begin
clk_out <= !clk_out;
end
else if (counter == M) begin
clk_out <= !clk_out;
end
end
endmodulemodule testbench;
// Inputs
reg clk;
reg rst;
reg [1:0] adv_select;
integer M;
// Outputs
wire clk_out;
// Instantiate the Unit Under Test (UUT)
work uut(
.clk(clk),
.rst(rst),
.adv_select(adv_select),
.M(M),
.clk_out(clk_out)
);
initial begin
clk = 1'b0;
forever #10 clk = ~clk;
end
initial begin
rst = 1'b0;
#2 rst = 1'b1;
#9 rst = 1'b0;
end
initial begin
adv_select = 2'b00;
M = 4;
#1086 adv_select = 2'b01;
M = 9;
#1086 adv_select = 2'b10;
M = 5;
end
endmodule
本文介绍了一个完整的时钟分频模块,支持偶分频、奇分频和半分频功能,并提供了详细的Verilog实现代码及仿真结果。
1万+

被折叠的 条评论
为什么被折叠?



