分频器 偶分频 奇分频 任意分频

今天学习了一下分频器及其Verilog实现

1.偶分频

实现一个NUM_DIV分频的分频器,下面代码中 NUM_DIV= 6,占空比50%

设计代码


module divider_even(
      clk,
      rst_n,
      clk_div
  );
      input clk;
      input rst_n;
      output clk_div;
     reg clk_div;
     
     parameter NUM_DIV = 6;
     reg    [3:0] cnt;
     
 always @(posedge clk or negedge rst_n)
     if(!rst_n) begin
         cnt     <= 4'd0;
         clk_div    <= 1'b0;
     end
     else if(cnt < NUM_DIV / 2 - 1) begin
         cnt     <= cnt + 1'b1;
         clk_div    <= clk_div;
     end
     else begin
         cnt     <= 4'd0;
         clk_div    <= ~clk_div;
     end
  endmodule

仿真代码

 module divider_tb();
    reg clk;
    reg rst_n;
    wire clk_div;
    parameter DELY=100;
divider_even U_divider(
    .clk    (clk    ),
    .rst_n    (rst_n    ),
    .clk_div(clk_div)
);
    always #(DELY/2) clk=~clk;//??????
/*initial begin
    $fsdbDumpfile("divider_even.fsdb");
    $fsdbDumpvars(0,U_divider);
 end
 */initial begin
          clk=0;rst_n=0;
    #DELY rst_n=1;
    //#((DELY*20)) $finish;
end
endmodule

波形图

从波形图中可以看到,clk_div的时钟频率是clk的1/6;计数cnt = 3清零

 

2.奇分频

设计目标:实现一个占空比50%,5分频的分频器

遇到一个错误,寄存器变量不能使用连续赋值语句

assign clk_div = clk_div1 | clk_div2;

** Error: E:/questasim/examples/labs/divider/odd_divider.v(53): Register is illegal in left-hand side of continuous assignment

解决方案很简单,只需要加一个initial,把这个赋值语句放在过程块里面就好了;

设计代码


//rtl
module divider_odd(
    clk,
    rst_n,
    clk_div
);
    input clk;
    input rst_n;
    output clk_div;
    reg clk_div;

    parameter NUM_DIV = 5;
    reg[2:0] cnt1;
    reg[2:0] cnt2;
    reg    clk_div1, clk_div2;

always @(posedge clk or negedge rst_n)
    if(!rst_n)
        cnt1 <= 0;
    else if(cnt1 < NUM_DIV - 1)
        cnt1 <= cnt1 + 1'b1;
    else
        cnt1 <= 0;

always @(posedge clk or negedge rst_n)
    if(!rst_n)
        clk_div1 <= 1'b1;
    else if(cnt1 < NUM_DIV / 2)
        clk_div1 <= 1'b1;
    else
        clk_div1 <= 1'b0;

always @(negedge clk or negedge rst_n)
    if(!rst_n)
       cnt2 <= 0;
    else if(cnt2 < NUM_DIV - 1)
       cnt2 <= cnt2 + 1'b1;
    else
       cnt2 <= 0;

always @(negedge clk or negedge rst_n)
begin
    if(!rst_n)
        clk_div2 <= 1'b1;
    else if(cnt2 < NUM_DIV / 2)
        clk_div2 <= 1'b1;
    else
        clk_div2 <= 1'b0;
end

initial
assign clk_div = clk_div1 | clk_div2;

endmodule

仿真代码

//tb
module divider_tb();
    reg clk;
    reg rst_n;
    wire clk_div;
    parameter DELY=100;
divider_odd 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

波形图

从波形图可以看到,实现了5分频,占空比50%

 3.任意占空比,任意分频

设计目标:时钟信号50M分频产生880Hz,而分频得到的信号的占空比为30%

设计代码


//rtl
module div_any(
    clk,
    rst_n,
    clk_div,
    counter
);
    input clk,rst_n;
    output clk_div;
    reg clk_div;
    output [15:0] counter;
    reg [15:0] counter;

always @(posedge clk)
    if(!rst_n)
        counter <= 0;
    else if(counter==56817)
        counter <= 0;
    else counter <= counter+1;

always @(posedge clk)
  if(!rst_n)
    clk_div <= 0;
  else if(counter<17045)
    clk_div <= 1;
  else
    clk_div <= 0;
 endmodule

仿真代码


//tb
module div_tb();
    reg clk;
    reg rst_n;
    wire clk_div;
    wire [15:0] counter;
    parameter DELY=100;
div_any U_div(
    .clk    (clk    ),
    .rst_n  (rst_n  ),
    .counter(counter),
    .clk_div(clk_div)
);
    always #(DELY/2) clk=~clk;//??????
/*initial begin
    $fsdbDumpfile("div_any.fsdb");
    $fsdbDumpvars(0,U_div);
 end*/
 initial begin
          clk=0;rst_n=0;
    #DELY rst_n=1;
    #((DELY*80000)) $finish;
end
endmodule

波形图

 

 参考Verilog设计分频器(面试必看) - Zhangxianhe - 博客园

本文的波形都是自己仿真生成的

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值