Menu Close

verilog 奇数,偶数分频逻辑

在fpga 设计中, 我们有时需要对输入的时钟进行分频。 例如:1/2,1/3,1/4,1/5 等等。在偶数分频时,分频逻辑比较容易实现,在奇数分频时,fpga 设计相对麻烦一些。

偶数分频逻辑设计:

even_div.v

module  even_div #
(
    parameter [31:0] N = 2
)
(
    input  clk,
    output clk_out,
    input  reset
);



reg [31:0] cnt;
always @(posedge clk or posedge reset) 
begin
    if(reset)
        cnt <= 0;
    else if(cnt == N - 1) 
        cnt <= 0;
    else cnt <= cnt + 1;
end

 
reg clk_reg;

always @(posedge clk or posedge reset) 
begin
    if(reset)
        clk_reg <= 0;
    else if(cnt == N/2 - 1) 
        clk_reg <= ~clk_reg;
    else if(cnt == N - 1)
        clk_reg <= ~clk_reg;
end

assign clk_out = clk_reg;
 
endmodule

偶数分频相对比较简单, 程序中使用cnt 作为计数器, 当计数器计数到分频值的一半时(N/2), clk 反转; 当计数器计数到分频值(N)时, clk 再次反转。

 

odd_div.v

module  odd_div #
(
    parameter [31:0] N = 3
)
(
    input  clk,
    output clk_out,
    input  reset
);



reg [31:0] cnt_p , cnt_n;
reg       clk_p , clk_n;
 


localparam BAUD_HALF = (N-1)/2 - 1;
localparam BAUD_TICK = N - 1;

 

always @(posedge clk or posedge reset) 
begin
    if(reset)
        cnt_p <= 4'd0;
    else if(cnt_p == BAUD_TICK)
        cnt_p <= 0;
    else 
        cnt_p <= cnt_p + 1'b1;
end
 

always @(negedge clk or posedge reset) 
begin 
    if(reset)
        cnt_n <= 4'd0;
    else if(cnt_n == BAUD_TICK)
        cnt_n <= 0;
    else 
        cnt_n <= cnt_n + 1'b1;
end
 
//clk_p 
always @(posedge clk or posedge reset) 
begin
    if(reset)
        clk_p <= 1;
    else if(cnt_p == BAUD_HALF) 
        clk_p <= ~clk_p;
    else if(cnt_p == BAUD_TICK)
        clk_p <= ~clk_p;
end
 
//clk_n
always @(negedge clk or posedge reset) 
begin
    if(reset)
        clk_n <= 1;
    else if(cnt_n == BAUD_HALF)
        clk_n <= ~clk_n;
    else if(cnt_n == BAUD_TICK)
        clk_n <= ~clk_n;
end  
  
  
assign clk_out = clk_n | clk_p;
 
endmodule

奇数分频相对比较麻烦, 步骤如下:

1)需要两个计数器:clk 上升沿计数器; clk 下降沿计数器。这两个计数器实现N计数。

2)分别在clk 的上升沿和下降沿 实现 clk_p,  clk_n。当cnt_x ==  N/2 – 0.5 时,clk_x 反转; 当cnt_x ==  N 时,clk_x 再次反转; 这样生成的时钟clk_x 是一个占空比不等的时钟(高电平 – 低电平 = 1)即要么高电平多0.5, 或者低电平多0.5 个时钟周期。

3)clk_out = clk_p | clk_n;  平衡占空比不等的现象,通过使用 或操作 ,实现%50 、%50 占空比的时钟。

 

仿真程序:

`timescale 1ns / 1ps
 
module tb
(
);

parameter PERIOD = 20   ; //50Mhz
 
reg clk; 
reg reset = 1;
initial 
begin
    clk = 0;
    #(PERIOD/2);
 
    forever 
        #(PERIOD/2) clk = ~clk;
end

initial
begin
    reset = 1;
    @(posedge clk);
    reset = 0;

    #800000; 
    $stop;
end

wire clk_out1;
odd_div #
(
    .N (7)
)
odd_div_inst
(
    .clk        (clk),
    .clk_out    (clk_out1),
    .reset      (reset)
);



wire clk_out2;
even_div #
(
    .N (4)
)
even_div_inst
(
    .clk        (clk),
    .clk_out    (clk_out2),
    .reset      (reset)
);


endmodule

仿真波形:

从仿真波形上可以看出,通过或操作实现 %50 , %50 的占空比时钟,从而实现计数分频。 偶数分频相对简单一些,只要通过计数分频即可。

 

Posted in FPGA, FPGA 教材教案, Verilog, 教材与教案, 文章

2 Comments

  1. 12班-孔晓瑞

    老师,关于奇分频的程序仿真中,摒弃复位期间的波形,我得到以下结论:
    1.clk_p和clk_n的复位期间的同为高电平时,若得到占空比为50%的clk_out波形,则clk_out=clk_p|clk_n;
    2.clk_p和clk_n的复位期间的同为低电平时,若得到占空比为50%的clk_out波形,则clk_out=clk_p&clk_n。

发表回复

相关链接