[笔记] Frequncy Divider
Abstract
本文讨论FPGA设计中最常用的分频器的设计,奇数分频,偶数分频,小数分频;
Introduction
偶数分频:如进行N倍偶数分频,那么可以通过由待分频的时钟触发计数器计数,当计数器从0计数到N/2-1时,输出时钟进行翻转,并给计数器一个复位信号,使得下一个时钟从零开始计数。以此循环下去。这种方法可以实现任意的偶数分频。
clkdiv_even.v
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | //clkdiv_24,n=12 module clkdiv_even( // input input clk_50, input rst_n, // output output reg clkdiv_even ); parameter PERIOD = 24, PULSEWIDTH = 12, SIZE =5; //24=11000,共5位; reg[SIZE-1:0] cnt; always@(posedge clk_50 or negedge rst_n) if (!rst_n) cnt <= 0; else if (cnt < PERIOD-1) cnt <= cnt+1; else cnt <= 0; always@(posedge clk_50 or negedge rst_n) if (!rst_n) clkdiv_even <= 0; else if (cnt < PULSEWIDTH) // 由此得到占空比为50% clkdiv_even <= 1; else clkdiv_even <= 0; endmodule |
clkdiv_even.vt
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | `timescale 1 ns/ 1 ns module clkdiv_even_vlg_tst(); // constants // general purpose registers reg clk_50; reg rst_n; // wires wire clkdiv_even; // assign statements (if any) clkdiv_even i1 ( // port map - connection between master ports and signals/registers .clk_50(clk_50), .clkdiv_even(clkdiv_even), .rst_n(rst_n) ); parameter PERIOD = 20; initial begin clk_50 = 0; #1000 rst_n = 0; #10000 rst_n = 1; forever #(PERIOD/2) clk_50 = ~clk_50; end endmodule |
simulation wave
奇数分频:用两个计数器,一个由输入时钟上升沿触发,一个由输入时钟下降沿触发,最后两个计数器输出相或。
clkdiv_odd.v
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | //clkdiv13,n=7; module clkdiv_odd( // input input clk_50, input rst_n, // output output clkdiv13 ); parameter PERIOD = 13, PULSEWIDTH = 6.5, SIZE = 4; //13=1101; reg[4:0] cnt1,cnt2; reg clkout1,clkout2; always@(posedge clk_50 or negedge rst_n) if (!rst_n) begin clkout1 <= 0; cnt1 <= 0; end else begin if (cnt1 == PERIOD-1) cnt1 <= 0; else cnt1 <= cnt1+1; if (cnt1<(PERIOD-1)/2) clkout1 <= 1; else clkout1 <= 0; end always@(negedge clk_50 or negedge rst_n) //clk_50下降沿触发 if (!rst_n) begin clkout2 <= 0; cnt2 <= 0; end else begin if (cnt2 == PERIOD-1) cnt2 <= 0; else cnt2 <= cnt2+1; if (cnt2<(PERIOD-1)/2) clkout2 <= 1; else clkout2 <= 0; end assign clkdiv13 = clkout1|clkout2; endmodule |
simulation wave
奇数分频两种方法总结:(Refer to http://blog.sina.com.cn/s/blog_4b03202d0100at7i.html)
一、对于实现占空比为50%的N倍奇数分频,首先进行上升沿触发进行模N计数,计数选定到某一个值进行输出时钟翻转,然后经过(N-1)/2再次进行翻转得到一个占空比非50%奇数n分频时钟。再者同时进行下降沿触发的模N计数,到和上升沿触发输出时钟翻转选定值相同值时,进行输出时钟时钟翻转,同样经过(N-1)/2时,输出时钟再次翻转生成占空比非50%的奇数n分频时钟。两个占空比非50%的n分频时钟相或运算,得到占空比为50%的奇数n分频时钟。
二、对进行奇数倍n分频时钟,首先进行n/2分频(带小数,即等于(n-1)/2+0.5),然后再进行二分频得到。得到占空比为50%的奇数倍分频。
半整数分频:
clkdiv_npn.v
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | // clkdiv_5.5 module clkdiv_npn( // input input clk_50, input rst_n, // output output reg clkdiv_out ); reg clk1; wire clk2; integer count; //Count为N的值 xor xor1(clk2,clk_50,clk1); //clk2:output, always@(posedge clkdiv_out or negedge rst_n) //clkdiv_out 2分频 if (!rst_n) clk1 <= 1'b0; else clk1 = ~clk1; always@(posedge clk2 or negedge rst_n) if (!rst_n) begin count <= 0; clkdiv_out <= 1'b0; end else if (count == 5) //计数到5时clkdiv_out输出1 begin count <= 0; clkdiv_out <= 1'b1; end else begin count <= count+1; clkdiv_out <= 1'b0; end endmodule |
simulation wave
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 为什么说在企业级应用开发中,后端往往是效率杀手?
· 用 C# 插值字符串处理器写一个 sscanf
· Java 中堆内存和栈内存上的数据分布和特点
· 开发中对象命名的一点思考
· .NET Core内存结构体系(Windows环境)底层原理浅谈
· 为什么说在企业级应用开发中,后端往往是效率杀手?
· 本地部署DeepSeek后,没有好看的交互界面怎么行!
· DeepSeek 解答了困扰我五年的技术问题。时代确实变了!
· 趁着过年的时候手搓了一个低代码框架
· 推荐一个DeepSeek 大模型的免费 API 项目!兼容OpenAI接口!