本文主要是介绍分频器 偶分频 奇分频 任意分频,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
今天学习了一下分频器及其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) begincnt <= 4'd0;clk_div <= 1'b0;endelse if(cnt < NUM_DIV / 2 - 1) begincnt <= cnt + 1'b1;clk_div <= clk_div;endelse begincnt <= 4'd0;clk_div <= ~clk_div;endendmodule
仿真代码
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 beginclk=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;elsecnt1 <= 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;elseclk_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;elsecnt2 <= 0;always @(negedge clk or negedge rst_n)
beginif(!rst_n)clk_div2 <= 1'b1;else if(cnt2 < NUM_DIV / 2)clk_div2 <= 1'b1;elseclk_div2 <= 1'b0;
endinitial
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 beginclk=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;elseclk_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 beginclk=0;rst_n=0;#DELY rst_n=1;#((DELY*80000)) $finish;
end
endmodule
波形图
参考Verilog设计分频器(面试必看) - Zhangxianhe - 博客园
本文的波形都是自己仿真生成的
这篇关于分频器 偶分频 奇分频 任意分频的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!