分频器设计(采用或门,与门,异或门)

使用或门和与门的方法类似,思想就是采用下降沿产生一个半拍。对或门低电平持续周期为cnt<NUM_DIV/2;对与门低电平持续周期为cnt<=NUM_DIV/2;

对异或门先利用上升沿产生一个周期为2*NUM_DIV的div_clk1,利用下降沿产生一个与div_clk1相差NUM_DIV/2相位的div_clk2,两者异或即可。  

1、采用或门生成占空比为%50的分频器(5分频)

module divider( 
    clk,
    rst_n,
    clk_div
);
    input clk;
    input rst_n;
    output clk_div;
    wire clk_div;
    
    parameter NUM_DIV = 5;
    reg[2:0] cnt;
    reg    clk_div1, clk_div2;

always @(posedge clk or negedge rst_n)
    if(!rst_n)
        cnt <= 0;
    else if(cnt < NUM_DIV - 1)
        cnt <= cnt + 1'b1;
    else 
        cnt <= 0;
        
always @(posedge clk or negedge rst_n)
    if(!rst_n)
        clk_div1 <= 1'b1;
    else if(cnt < NUM_DIV / 2)//注意这里是小于,和与门的不同之处 
        clk_div1 <= 1'b1;
    else
        clk_div1 <= 1'b0;

always @(negedge clk or negedge rst_n)
    if(!rst_n)
        clk_div2 <= 1'b1;
    else if(cnt < NUM_DIV / 2) //注意这里是小于,和与门的方法的不同之处
        clk_div2 <= 1'b1;
    else
        clk_div2 <= 1'b0;
        
    assign clk_div = clk_div1 | clk_div2;
endmodule

仿真代码见3;

仿真波形

 

 

2、 采用与门产生占空比%50的分频电路(5分频)

module divider( 
    clk,
    rst_n,
    clk_div
);
    input clk;
    input rst_n;
    output clk_div;
    wire clk_div;
    
    parameter NUM_DIV = 5;
    reg[2:0] cnt;
    reg    clk_div1, clk_div2;

always @(posedge clk or negedge rst_n)
    if(!rst_n)
        cnt <= 0;
    else if(cnt < NUM_DIV - 1)
        cnt <= cnt + 1'b1;
    else 
        cnt <= 0;
        
always @(posedge clk or negedge rst_n)
    if(!rst_n)
        clk_div1 <= 1'b1;
    else if(cnt <= NUM_DIV / 2) //注意这里是小于等于
        clk_div1 <= 1'b1;
    else
        clk_div1 <= 1'b0;

always @(negedge clk or negedge rst_n)
    if(!rst_n)
        clk_div2 <= 1'b1;
    else if(cnt <= NUM_DIV / 2)  //注意这里是小于等于
        clk_div2 <= 1'b1;
    else
        clk_div2 <= 1'b0;
        
    assign clk_div = clk_div1 & clk_div2;
endmodule

仿真代码见3;

仿真波形

 

3、采用异或门产生占空比%50的分频电路(3分频)

//rtl
module divider( 
    clk,
    rst_n,
    clk_div
);
    input clk;
    input rst_n;
    output clk_div;
    wire clk_div;
    
    parameter NUM_DIV = 3;
    reg[2:0] cnt;
    reg    clk_div1, clk_div2;

always @(posedge clk or negedge rst_n)
    if(!rst_n)
        cnt <= 0;
    else if(cnt < NUM_DIV - 1)
        cnt <= cnt + 1'b1;
    else 
        cnt <= 0;
        
always @(posedge clk or negedge rst_n)
    if(!rst_n)
        clk_div1 <= 1'b1;
    else if(cnt == NUM_DIV-1 ) //计数器计数到最大值,上升沿采样
        clk_div1 <= ~clk_div1;
    else
        clk_div1 <= clk_div1;
        
always @(negedge clk or negedge rst_n)
    if(!rst_n)
        clk_div2 <= 1'b1;
    else if(cnt == NUM_DIV/2 ) //计数器计数到中间值,下降沿采样
        clk_div2 <= ~clk_div2;
    else
        clk_div2 <= clk_div2;
        
    assign clk_div = clk_div1 ^ clk_div2;
endmodule

仿真代码

//tb
module divider_tb();
    reg clk;
    reg rst_n;
    wire clk_div;
    parameter DELY=100;
divider U_divider(
    .clk    (clk    ),
    .rst_n    (rst_n    ),
    .clk_div(clk_div)
);
    always #(DELY/2) clk=~clk;//产生时钟波形
//initial begin
//   $fsdbDumpfile("divider_odd.fsdb");
//   $fsdbDumpvars(0,U_divider);
//end
 initial begin
          clk=0;rst_n=0;
    #DELY rst_n=1;
    #((DELY*20)) $finish;
end
endmodule

仿真波形

 

posted @ 2020-05-04 14:20  Mr_vol  阅读(828)  评论(0)    收藏  举报