赞
踩
分频即分割频率,把周期增大,频率减小。由于晶振产生的时钟信号频率是固定的,因此当需要其他周期的时钟信号时就需要分频。例如,一个时钟源的周期为1ms,其频率为1000Hz,经过二分频,1000Hz频率就会减少为500Hz,周期增加为2ms。
偶数倍分频通过计数器计数是完全可以实现的。如进行N倍偶数分频,那么可以通过由待分频的时钟触发计数器计数,当计数器从0计数到N-1时,输出时钟进行翻转,并给计数器一个复位信号,使得下一个时钟从零开始计数。以此循环下去。这种方法可以实现任意的偶数分频。
二分频的简单实现如下:
功能模块:
module div_clk2(clk_out,clk_in,rst);
output clk_out;
input clk_in,rst;
reg clk_out;
always @(posedge clk_in)
begin
if(rst)
clk_out <= 0;
else
clk_out <= ~clk_out;
end
endmodule
测试模块:
module t9_14; reg clk_in,rst; wire clk_out; initial clk_in = 0; always #5 clk_in = ~clk_in; initial begin rst = 1; #20 rst = 0; #100 $stop; end div_clk2 mydiv_2(clk_out,clk_in,rst); endmodule
仿真结果:
可修改参数的偶数分频计数器:
功能模块:
module div_clkn(clk_out,clk_in,rst); output clk_out; input clk_in,rst; reg clk_out; reg [width(n)-1:0] count; parameter n=4; always @(posedge clk_in) begin if(rst) count <= 0; else if(count == n-1) count <= 0; else count <= count + 1; end always @(count) begin if(rst) clk_out = 0; else if(count == n-1) clk_out = ~clk_out; else clk_out = clk_out; end function integer width; input integer size; begin for(width = 0;size > 0;width = width + 1) size = size >> 1; end endfunction endmodule
测试模块:
module t9_15; reg clk_in,rst; wire clk_out; initial clk_in = 0; always #5 clk_in = ~clk_in; initial begin rst = 1; #20 rst = 0; #100 $stop; end div_clkn mydiv_clkn(clk_out,clk_in,rst); endmodule
仿真结果:
对于实现占空比为50%的N倍奇数分频,首先进行上升沿触发进行模N计数,经过(N-1)/2时,翻转一次;到(N-1)时,计数器置零;就可以实现占空比为(N-1)/2N的N分频信号;同样的,进行下降沿触发进行模N计数,经过(N-1)/2时,翻转一次;到(N-1)时,计数器置零;就可以实现占空比为(N-1)/2N的N分频信号;最终将两个信号相或就能得到占空比为50%的N分频信号。
功能模块:
module div_clk3(clk_out,clk_in,rst); output clk_out; input rst; input clk_in; reg clk_out; reg [1:0] count; always @ (posedge clk_in or posedge rst)//同步复位 begin if (rst) begin clk_out<=1'b0; count<=2'b00; end else if(count==0)// 第一个clk_in上升沿来的时候clk_out翻转一次计数器加一; begin clk_out <= ~clk_out; count<=count+1; end else if(count==2)//第3个clk_in上升沿来的时候输出clk_out翻转一次计数器归零; begin clk_out = ~clk_out; count<=2'b00; end else//第二个clk_in上升沿来的时候clk_out保持不变,计数器加一。 begin count<=count+1; end end endmodule
测试模块:
module t9_16;
reg clk_in;
reg rst;
initial clk_in=0;
always #5 clk_in=~clk_in;
initial
begin
rst=1;
#7 rst =0;
end
div_clk3 clk3(clk_out,clk_in,rst);
endmodule
仿真结果:
module div_clk3(clk_out,clk,rst); output clk_out; input rst; input clk; reg q1,q2; //内部寄存器变量,分别是两个占空比为1/3的分频; reg [1:0] count1,count2; assign clk_out = q1|q2; always @ (posedge clk or posedge reset) //上升沿生成的三分频q1; begin if (reset) begin clk_out <= 1'b0; count1 <= 2'b00; end else if(count1 == 0) begin clk_out <= ~clk_out; count1 <= count1 + 1'b1; end else if(count1 == 1) begin clk_out = ~clk_out; count1 <= count1+1'b1; end else begin count1 <= 2'b00; end end always @ (negedge clk or posedge rst)//同上一段always结构 begin if (rst) begin clk_out <= 1'b0; count2<=2'b00; end else if(count2 == 0) begin clk_out <= ~clk_out; count2<=count2+1'b1; end else if(count2 == 1'b1) begin clk_out = ~clk_out; count2<=count2+1'b1; end else begin count2<=2'b00; end end endmodule
测试模块:
module t9_16;
reg clk_in;
reg rst;
initial clk_in=0;
always #5 clk_in=~clk_in;
initial
begin
rst=1;
#7 rst =0;
end
div_clk3 clk3(clk_out,clk_in,rst);
endmodule
仿真结果:
功能模块:
module clk_div_5(clk_out, clk_in, rst); input clk_in; input rst; output clk_out; reg [2:0] cnt1, cnt2; reg q1, q2; parameter CNT_M = 3'd4,//N-1 CNT_N = 3'd2;//(N-1)/2 always @(posedge clk_in) //上升沿 5 分频,占空比为 2/5 begin if(!rst) begin cnt1 <= 0; q1 <= 0; end else begin if( cnt1 == CNT_M ) begin cnt1 <= 0; q1 <= ~q1; end else begin cnt1 <= cnt1 + 1'b1; if ( cnt1 == CNT_N ) q1 <= ~q1; else q1 <= q1; end end end always @(negedge clk_in) //下降沿 5 分频,占空比为 2/5 begin if(!rst) begin cnt2 <= 0; q2 <= 0; end else begin if( cnt2 == CNT_M ) begin cnt2 <= 0; q2 <= ~q2; end else begin cnt2 <= cnt2 + 1'b1; if ( cnt2 == CNT_N ) q2 <= ~q2; else q2 <= q2; end end end assign clk_out = q1 | q2; //错位相或 endmodule
测试模块:
module t9_16;
reg clk_in;
reg rst;
initial clk_in=0;
always #5 clk_in=~clk_in;
initial
begin
rst=1;
#7 rst =0;
end
div_clk5 clk5(clk_out,clk_in,rst);
endmodule
仿真结果:
使用上升沿和下降沿,两个always结构,通过状态机实现。
功能模块:
module div_clk3(clk_out,clk_in,rst); output clk_out; input clk_in,rst; reg [1:0] temp1,temp2; always @(posedge clk_in) begin if(!rst) temp1 <= 2'b00; else begin case(temp1) 2'b00:temp1 <= 2'b01; 2'b01:temp1 <= 2'b10; 2'b10:temp1 <= 2'b000; default:temp1 <= 2'b00; endcase end end always @(negedge clk_in) begin if(!rst) temp2 <= 2'b00; else begin case(temp2) 2'b00:temp2 <= 2'b01; 2'b01:temp2 <= 2'b10; 2'b10:temp2 <= 2'b00; default:temp2 <=2'b00; endcase end end assign clk_out = temp1[0] | temp2[0]; endmodule
测试模块:
module t9_16; reg clk_in; reg rst; initial clk_in=1; always #10 clk_in=~clk_in; initial begin rst=1; #20 rst =0; #50 rst=1; #1000 $stop; end div_clk3 clk3(clk_out,clk_in,rst); endmodule
仿真结果:
功能模块:
module div_clk5(clk_out,clk_in,rst); output clk_out; input clk_in,rst; reg [2:0] temp1,temp2; always @(posedge clk_in) begin if(!rst) temp1 <= 3'b000; else begin case(temp1) 3'b000:temp1 <= 3'b001; 3'b001:temp1 <= 3'b011; 3'b011:temp1 <= 3'b100; 3'b100:temp1 <= 3'b010; 3'b010:temp1 <= 3'b000; default:temp1 <= 3'b000; endcase end end always @(negedge clk_in) begin if(!rst) temp2 <= 3'b000; else begin case(temp2) 3'b000:temp2 <= 3'b001; 3'b001:temp2 <= 3'b011; 3'b011:temp2 <= 3'b100; 3'b100:temp2 <= 3'b010; 3'b010:temp2 <= 3'b000; default:temp2 <=3'b000; endcase end end assign clk_out = temp1[0] | temp2[0]; endmodule
测试模块:
module t9_16; reg clk_in; reg rst; initial clk_in=1; always #10 clk_in=~clk_in; initial begin rst=1; #20 rst =0; #50 rst=1; #1000 $stop; end div_clk5 clk5(clk_out,clk_in,rst); endmodule
仿真结果:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。