学習する前に、デューティサイクルを理解してください。
デューティサイクル:理想的なパルスシーケンス(方形波など)の場合、正のパルスの持続時間とパルスの周期の比率は、方形波のデューティサイクルと呼ばれます。
周波数分割も
偶数の乗算と除算は、おなじみの除算であり、カウンタで直接実現できる最も単純な除算カウンタである必要があります。たとえば、周波数がNの倍数と偶数で除算される場合、カウンターは分周するクロックによってトリガーできます。カウンターが0からN / 2-1までカウントすると、出力クロックが反転し、カウンターがリセットされます。次のクロックはゼロからカウントを開始します。このサイクルでは、任意の周波数分割を達成できます
奇数の周波数分割
奇数の乗算と除算はフォーラムでよく尋ねられます。実際、奇数の乗算と除算には2つの実装方法があります。1つ目は
、カウンターで実現できます。たとえば、3で除算し、除算するクロックの立ち上がりエッジでカウンターをトリガーします。モジュロ3カウントでは、カウンターが隣接する値までカウントすると2回反転します。たとえば、カウンターが1にカウントすると出力クロックが反転し、カウンターが2に達すると再び反転します。つまり、隣接する1と2でカウント値が2回反転します。このようにして実現された3ウェイ周波数のデューティ比は1/3または2/3です。デューティサイクルが50%の3周波数クロックを実現する場合は、分周するクロックの立ち下がりエッジでカウントをトリガーし、立ち上がりエッジと同じ方法で3カウントしてから、立ち下がりエッジで生成された3周波数クロックと立ち上がりエッジをカウントできます。生成されたクロックは、位相OR演算を実行して、デューティサイクルが50%の3周波数クロックを取得します。この方法は、奇数の周波数分割を実現できます。
一般に分類される方法は、50%のデューティサイクルでN倍の奇数の周波数分割を実現するために、立ち上がりエッジトリガーがモジュロNカウントに対して実行され、カウントが特定の値に選択され、出力クロックが反転され、次に(N- 1)/ 2が再び反転され、50%でない奇数のn周波数クロックが取得されます。同時に、負のエッジでトリガーされるモジュロNカウントが実行されます。値が立ち上がりエッジでトリガーされる出力クロックフリップの選択した値と同じ場合、出力クロッククロックフリップが実行されます。(N-1)/ 2も渡されると、出力クロックが再度フリップしてアカウントが生成されます空の比率が50%以外の奇数n分周クロック。50%以外のデューティサイクルを持つ2つのnで除算されたクロックはORされて、50%のデューティサイクルで奇数番号のn分割クロックが得られます。
別の方法:クロックを奇数倍のnで除算するには、最初にn / 2(小数で、(n-1)/2+0.5に等しい)で除算し、次に2で除算します。50%のデューティサイクルで奇数の周波数分割を取得します。
分数周波数
最初に、入力クロックでの操作が必要なn + 0.5での除算方法について説明します。基本的な設計アイデア:n + 0.5の周波数分割では、最初にnを法としてカウントします。カウントがn-1に達すると、出力クロックは「1」に割り当てられ、カウント0に戻ると、0に割り当てられます。したがって、次のことができます。カウント値がn-1の場合、出力クロックは1であることが知られています。したがって、カウント値n-1が入力クロックサイクルの半分の間維持される限り、n + 0.5分周クロックが実現されるため、n-1を半分に保ちます。 1クロックサイクルは困難です。カウンタはクロックの立ち上がりエッジでカウントするため、カウントがn-1のときにカウントトリガクロックが反転し、クロックの立ち下がりエッジが立ち上がりエッジになることがわかります。つまり、カウント値がn-1の場合、クロックの立ち下がりエッジは立ち上がりエッジになり、カウント値n-1は半クロックサイクルだけ維持されます。クロックが立ち下がりエッジを立ち上がりエッジにフリップするため、カウント値は0になります。したがって、n + 0.5分周クロック周期が生成されるたびに、トリガークロックを1回フリップする必要があります。設計のアイデアは次のとおりです
。以下は、任意の正の整数の周波数分割コードです。
module div_clk(
input clk,
input rst_n,
output o_clk
);
parameter WIDTH = 3;
parameter N = 6;
reg [WIDTH-1:0] cnt_p;
reg clk_p;
reg clk_n;
assign o_clk = (N==1)?clk : (N[0])?(clk_p | clk_n) : clk_p;//其中N==1是判断不分频,N[0]是判断是奇数还是偶数,若为1则是奇数分频,若是偶数则是偶数分频。
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
cnt_p <= {
WIDTH{
1'b0}};
else if(cnt_p == (N-1))
cnt_p <= {
WIDTH{
1'b0}};
else
cnt_p <= cnt_p + 1'b1;
end
always @(posedge clk or negedge rst_n) begin
if(rst_n == 1'b0)
clk_p <= 1;//此处设置为0也是可以的,这个没有硬性的要求,不管是取0还是取1结果都是正确的。
else if(cnt_p < (N>>1))/*N整体向右移动一位,最高位补零,其实就是N/2,不过在计算奇数的时候有很明显的优越性*/
clk_p <= 1;
else
clk_p <= 0;
end
always @(negedge clk or negedge rst_n) begin
if(rst_n == 1'b0)
clk_n <= 1;
else
clk_n <= clk_n;
end
endmodule
以下は、コードの奇数、偶数、および小数の除算です
module divf #
( parameter Div_num = 12 , // 分频数
parameter state=0 //半分频为0,奇数分频为1,偶数分频为2
)
(
input clr,
input clk,
output Div_clk
);
reg [24:0] count;
case(state)
1: begin //ji_shu
reg pos_clk;
reg neg_clk;
always@(posedge clk or negedge clr)
if(!clr) count<=0;
else if(count==0 & pos_clk) count<=Div_num/2-1;
else if(count==0) count<=Div_num/2;
else count<=count-1;
always@(posedge clk or negedge clr)
if(!clr) pos_clk<=0;
else if(count==0) pos_clk<=~pos_clk;
else pos_clk<=pos_clk;
always@(negedge clk or negedge clr)
if(!clr) neg_clk<=0;
else neg_clk<=pos_clk;
assign Div_clk = pos_clk & neg_clk;
end
2: begin //ou_shu
reg Div_clk1;
always@(posedge clk or negedge clr)
if(!clr) count<=0;
else if(count==0) count<=Div_num/2-1;
else count<=count-1;
always@(posedge clk or negedge clr)
if(!clr) Div_clk1<=0;
else if(count==0) Div_clk1<=~Div_clk1;
assign Div_clk = Div_clk1;
end
0: begin //ban_fen_pin
reg count_div;
reg count_div2;
wire clk_half;
assign clk_half = clk^count_div2;
always@(posedge clk_half or negedge clr) //模Div_num 计数
if(!clr) count<=0;
else if(count== Div_num-1) count<=0;
else count<=count+1;
always@(posedge clk_half or negedge clr) //模Div_num 计数
if(!clr) count_div<=0;
else if(count== Div_num-1) count_div<=1;
else count_div<=0;
always@(posedge count_div or negedge clr) //对count_div二分频
if(!clr) count_div2<=0;
else count_div2<=~count_div2;
assign Div_clk = count_div;
end
endcase
endmodule