众所周知,分频器是FPGA设计中使用频率非常高的基本设计之一,尽管在目前大部分设计中,广泛使用芯片厂家集成的锁相环资源,如altera 的PLL,Xilinx的DLL.来进行时钟的分频,倍频以及相移。但是对于时钟要求不高的基本设计,通过语言进行时钟的分频相移仍然非常流行,首先这种方法可以节省芯片内部的锁相环资源,再者,消耗不多的逻辑单元就可以达到对时钟操作的目的。另一方面,通过语言设计进行时钟分频,可以看出设计者对设计语言的理解程度。因此很多招聘单位在招聘时往往要求应聘者写一个分频器,以考核应聘人员的设计水平和理解程度。
1、占空比为50%
偶数分频
比较简单,例如要进行N分频,当计数器计数到N/2-1时,让系统时钟翻转,就可以得到占空比为50%的偶数分频,下面举一个12分频的例子,看程序。
module clkdiv12( clk, //系统时钟; rst_n, //复位信号,低电平有效; clk_div //分频时钟输出; ); input clk; input rst_n; output clk_div; reg[3:0] time_cnt; always @ (posedge clk or negedge rst_n) begin if(!rst_n) time_cnt<=4'd0; else if(time_cnt==4'd5) time_cnt<=4'd0; else time_cnt<=time_cnt+1'b1; end reg clk_div_r; always @ (posedge clk or negedge rst_n) begin if(!rst_n) clk_div_r<=1'b0; else if(time_cnt==4'd5) clk_div_r<=~clk_div_r; end assign clk_div=clk_div_r; endmodule
仿真波形
奇数分频
例如进行占空比为50%的N分频,在时钟上升沿时,先让计数器1,在0是取高电平,当计数到N-1/2时,取低电平,得到一个分频时钟1;再在时钟下降沿时,让计数器2,在0时取高电平,在N-1/2时取低电平,得到分频时钟2,最后将分频时钟1和分频时钟2相或,就可以得到N分频时钟。下面是一个七分频例子
module fdiv7 ( clk, rst_n, clk_div ); input clk; input rst_n; output clk_div; reg[2:0] time_cnt1; always @ (posedge clk or negedge rst_n) begin if(!rst_n) time_cnt1<=3'd0; else if (time_cnt1==3'd6) time_cnt1<=3'd0; else time_cnt1<=time_cnt1+1'b1; end reg clk_div1; always @ (posedge clk or negedge rst_n) begin if(!rst_n) clk_div1<=1'b0; else if(time_cnt1==3'd0) clk_div1<=1'b1; else if(time_cnt1==3'd3) clk_div1<=1'b0; end reg[2:0] time_cnt2; always @ (negedge clk or negedge rst_n) begin if(!rst_n) time_cnt2<=3'd0; else if (time_cnt2==3'd6) time_cnt2<=3'd0; else time_cnt2<=time_cnt2+1'b1; end reg clk_div2; always @ (negedge clk or negedge rst_n) begin if(!rst_n) clk_div2<=1'b0; else if(time_cnt2==3'd0) clk_div2<=1'b1; else if(time_cnt2==3'd3) clk_div2<=1'b0; end assign clk_div=clk_div1||clk_div2; endmodule
波形图
2、占空比不为50%
偶数分频
如进行占空比1:3 的六分频,当计数器计数到0时,分频时钟取高电平,计数到2时,分频时钟取低电平,就可以得到一个占空比为1:3的六分频时钟
//占空比为1:3的六分频 module clk_div6 ( clk, rst_n, clk_div ); input clk; input rst_n; output clk_div; reg[2:0] time_cnt; always @(posedge clk or negedge rst_n) begin if(!rst_n) time_cnt<=3'd0; else if(time_cnt==3'd5) time_cnt<=3'd0; else time_cnt<=time_cnt+1'b1; end reg clk_div_r; always @ (posedge clk or negedge rst_n) begin if(!rst_n) clk_div_r<=1'b0; else if(time_cnt==3'd0) clk_div_r<=1'b1; else if(time_cnt==3'd2) clk_div_r<=1'b0; end assign clk_div=clk_div_r; endmodule
仿真波形
奇数分频
例如占空比为1:9的9分频:在计数器为8时,使分频时钟去高电平;为0时,取低电平,就可以得到占空比为1:9的9分频时钟
module clkdiv9 ( clk, rst_n, clk_div ); input clk; input rst_n; output clk_div; reg[3:0] time_cnt; always @(posedge clk or negedge rst_n) begin if(!rst_n) time_cnt<=4'd0; else if(time_cnt==4'd8) time_cnt<=4'd0; else time_cnt<=time_cnt+1'b1; end reg clk_div_r; always @(posedge clk or negedge rst_n) begin if(!rst_n) clk_div_r<=1'b0; else if(time_cnt==8) clk_div_r<=1'b1; else if(time_cnt==0) clk_div_r<=1'b0; end assign clk_div=clk_div_r; endmodule
仿真波形
好了,分频时钟就告一段落,大家如果有更好的方法,通知我一下,本人也是刚刚学习FPGA,欢迎大牛拍砖!