Verilog设计分频器(面试必看)

更新时间:2023-07-13 12:55:22 阅读: 评论:0

Verilog设计分频器(⾯试必看)
分频器是指使输出信号频率为输⼊信号频率整数分之⼀的电⼦电路。在许多电⼦设备中如电⼦钟、频率合成器等,需要各种不同频率的信号协同⼯作,常⽤的⽅法是以稳定度⾼的晶体振荡器为主振源,通过变换得到所需要的各种频率成分,分频器是⼀种主要变换⼿段。
 早期的分频器多为正弦分频器,随着数字集成电路的发展,脉冲分频器(⼜称数字分频器)逐渐取代了正弦分频器。
下⾯以Verilog HDL 语⾔为基础介绍占空⽐为50%的分频器。
1、偶分频
  偶分频电路指的是分频系数为 2、4、6、8 ... 等偶数整数的分频电路,我们可以直接进⾏分频。
例如下⾯ divider.v 中,对输⼊时钟进⾏6分频,即假设clk 为 50MHz ,分频后的时钟频率为 (50/6) MHz。程序如下:
设计代码:
英文翻译网
1//rtl
2module divider(
3    clk,
4    rst_n,
5    clk_div
6 );
7input clk;
8input rst_n;
9output clk_div;
10reg clk_div;
11
12parameter NUM_DIV = 6;
13reg    [3:0] cnt;
14
15always @(podge clk or negedge rst_n)
16if(!rst_n) beginstudy的第三人称单数
17        cnt    <= 4'd0;
18        clk_div    <= 1'b0;
19end
20el if(cnt < NUM_DIV / 2 - 1) begin
21        cnt    <= cnt + 1'b1;
22        clk_div    <= clk_div;
23end
24el begin
25        cnt    <= 4'd0;
26        clk_div    <= ~clk_div;
27end
28endmodule
View Code
仿真程序:
1//tb
2module divider_tb();
3reg clk;
4reg rst_n;
5wire clk_div;
6parameter DELY=100;
7 divider U_divider(
8    .clk    (clk    ),
9    .rst_n    (rst_n    ),
10    .clk_div(clk_div)
11 );
12always #(DELY/2) clk=~clk;//产⽣时钟波形
13initial begin
14    $fsdbDumpfile("divider_even.fsdb");
15    $fsdbDumpvars(0,U_divider);
16end
17initial begin
18          clk=0;rst_n=0;
19    #DELY rst_n=1;
20    #((DELY*20)) $finish;
21end
22endmodule
View Code
可以看到,clk的上升沿,采样到cnt=2的时候,就翻转,采样到0和1的时候,保持。这样就可以做到⼀半⾼电平,⼀半低电平。
2、奇分频
  由于奇分频需要保持分频后的时钟占空⽐为 50% ,所以不能像偶分频那样直接在分频系数的⼀半时使时钟信号翻转(⾼电平⼀半,低电平⼀半)。
    在此我们需要利⽤输⼊时钟上升沿和下降沿来进⾏设计。
     接下来我们设计⼀个 5 分频的模块,设计思路如下:
     采⽤计数器 cnt1 进⾏计数,在时钟上升沿进⾏加 1 操作,计数器的值为 0、1 时,输出时钟信号 clk_div 为⾼电平;计数器的值为2、3、4 时,输出时钟信号 clk_div 为低电平,计数到 5 时清零,从头开始计数。我们可以得到占空⽐为 40% 的波形 clk_div1。
    采⽤计数器 cnt2进⾏计数,在时钟下降沿进⾏加 1 操作,计数器的值为 0、1 时,输出时钟信号 clk_div 为⾼电平;计数器的值为2、3、4 时,输出时钟信号 clk_div 为低电平,计数到 5 时清零,从头开始计数。我们可以得到占空⽐为 40% 的波形 clk_div2。
    clk_div1 和clk_div2 的上升沿到来时间相差半个输⼊周期,所以将这两个信号进⾏或操作,即可得到占空⽐为 50% 的5分频时钟。程序如下:
设计代码:
1//rtl
2module divider(
3    clk,
4    rst_n,
5    clk_div
6 );
7input clk;
8input rst_n;
9output clk_div;
10reg clk_div;
11
12parameter NUM_DIV = 5;
13reg[2:0] cnt1;
14reg[2:0] cnt2;
15reg    clk_div1, clk_div2;
16
17always @(podge clk or negedge rst_n)
18if(!rst_n)
19        cnt1 <= 0;
20el if(cnt1 < NUM_DIV - 1)
21        cnt1 <= cnt1 + 1'b1;
22el
23        cnt1 <= 0;
24
25always @(podge clk or negedge rst_n)
26if(!rst_n)
27        clk_div1 <= 1'b1;
28el if(cnt1 < NUM_DIV / 2)
29        clk_div1 <= 1'b1;
30el
31        clk_div1 <= 1'b0;
32
33always @(negedge clk or negedge rst_n)
34if(!rst_n)
35        cnt2 <= 0;
36el if(cnt2 < NUM_DIV - 1)
37        cnt2 <= cnt2 + 1'b1;
38el
39        cnt2 <= 0;
40
41always @(negedge clk or negedge rst_n)
42if(!rst_n)
43        clk_div2 <= 1'b1;
44el if(cnt2 < NUM_DIV / 2)
45        clk_div2 <= 1'b1;
46el
47        clk_div2 <= 1'b0;
the same to you
48
49assign clk_div = clk_div1 | clk_div2;
50endmodule
View Code
仿真代码:
1//tb
2module divider_tb();
3reg clk;
4reg rst_n;
5wire clk_div;
6parameter DELY=100;
7 divider U_divider(
8    .clk    (clk    ),
9    .rst_n    (rst_n    ),
10    .clk_div(clk_div)
11 );
12always #(DELY/2) clk=~clk;//产⽣时钟波形
13initial begin
prior是什么意思>wspc
14    $fsdbDumpfile("divider_odd.fsdb");
15    $fsdbDumpvars(0,U_divider);
16end
17initial begin
18          clk=0;rst_n=0;
19    #DELY rst_n=1;
20    #((DELY*20)) $finish;
21end
22endmodule
View Code
对其进⾏测试和验证(此仿真波形是三分频,占空⽐50%),即上述程序吧NUM_DIV改成3即可,得到如下波形:
3.任意占空⽐的任意分频
在verilog程序设计中,我们往往要对⼀个频率进⾏任意分频,⽽且占空⽐也有⼀定的要求这样的话,对于程序有⼀定的要求。
现在在前⾯两个实验的基础上做⼀个简单的总结,实现对⼀个频率的任意占空⽐的任意分频。
⽐如: FPGA系统时钟是50M Hz,⽽我们要产⽣的频率是880Hz,那么,我们需要对系统时钟进⾏分频。很容易想到⽤计数的⽅式来分频:50000000/880 = 56818。显然这个数字不是2的整幂次⽅,那么我们可以设定⼀个参数,让它到56818的时候重新计数就可以实现了。程序如下:
设计代码:
1//rtl
2module div(
3    clk,
4    rst_n,
5    clk_div
6 );
7input clk,rst_n;
8output clk_div;
9reg clk_div;
10
11reg [15:0] counter;
12
13always @(podge clk or negedge rst_n)
14if(!rst_n)
15        counter <= 0;
16el if(counter==56817)
17        counter <= 0;
18el
19        counter <= counter+1;
20
21assign clk_div = counter[15];
22endmodule
View Code
仿真代码:
1//tb
2module div_tb();
3reg clk;
4reg rst_n;
5wire clk_div;
6parameter DELY=100;
金山在线快译7 div U_div(
8    .clk    (clk    ),
9    .rst_n  (rst_n),
10    .clk_div(clk_div)
11 );
12always #(DELY/2) clk=~clk;//产⽣时钟波形
13initial begin
14    $fsdbDumpfile("div_any.fsdb");
15    $fsdbDumpvars(0,U_div);
16endthumb是什么意思
17initial begin
18          clk=0;rst_n=0;
19    #DELY rst_n=1;
20    #((DELY*80000)) $finish;
21end
22endmodule
View Code
分频的应⽤很⼴泛,⼀般的做法是先⽤⾼频时钟计数,然后使⽤计数器的某⼀位输出作为⼯作时钟进⾏其他的逻辑设计,上⾯的程序就是⼀个体现。下⾯我们来算⼀下它的占空⽐:
我们清楚地知道,这个输出波形在counter为0到32767(2的14次⽅)的时候为低,在32768到56817的时候为⾼,占空⽐为40%多⼀些,
如果我们需要占空⽐为50%,那么我们需要再设定⼀个参数,使它为56817的⼀半,使达到它的时候波形翻转,就可以实现结果了。
程序如下:28408=56818/2-1,计数到28408就清零,翻转,其余的计数期间,保持不变。
设计代码:
1//rtl
2module div(
加油英语怎么说3    clk,
4    rst_n,
5    clk_div
6 );
7input clk,rst_n;
8output clk_div;英语四级计分器
9reg clk_div;
10reg [14:0] counter;
11always @(podge clk or negedge rst_n)
12if(!rst_n)
13        counter <= 0;
14el if(counter==28408)
15        counter <= 0;
clock是什么意思
16el
17        counter <= counter+1;
18
19always @(podge clk or negedge rst_n)
20if(!rst_n)
21        clk_div <= 0;
22el if(counter==28408)
23        clk_div <= ~clk_div;
24endmodule
View Code
仿真代码:
1//tb
2module div_tb();
3reg clk;
4reg rst_n=0;
5wire clk_div;
6parameter DELY=100;
7 div U_div(
8    .clk    (clk    ),
9    .rst_n  (rst_n),
10    .clk_div(clk_div)
11 );
12always #(DELY/2) clk=~clk;//产⽣时钟波形
13initial begin
14    $fsdbDumpfile("div_any.fsdb");
15    $fsdbDumpvars(0,U_div);
16end
17initial begin
18          clk=0;rst_n=0;
19    #DELY rst_n=1;
20    #((DELY*80000)) $finish;
21end
22endmodule
View Code
继续让我们来看如何实现任意占空⽐,⽐如还是由50M分频产⽣880Hz,⽽分频得到的信号的占空⽐为30%。
56818×30%=17045
设计代码:
1//rtl
2module div(
3    clk,
4    rst_n,
5    clk_div,
6    counter
7 );
8input clk,rst_n;
9output clk_div;
10reg clk_div;
11output [15:0] counter;
12reg [15:0] counter;
13
14always @(podge clk)
15if(!rst_n)
16        counter <= 0;
17el if(counter==56817)
18        counter <= 0;
19el counter <= counter+1;
20
21always @(podge clk)
22if(!rst_n)
23    clk_div <= 0;
24el if(counter<17045)
25    clk_div <= 1;
26el
27    clk_div <= 0;
28endmodule
View Code
仿真代码:
1//tb
2module div_tb();
3reg clk;
4reg rst_n;
5wire clk_div;
6wire [15:0] counter;
7parameter DELY=100;
8 div U_div(
9    .clk    (clk    ),
10    .rst_n  (rst_n  ),
11    .counter(counter),
12    .clk_div(clk_div)
13 );
14always #(DELY/2) clk=~clk;//产⽣时钟波形
15initial begin
16    $fsdbDumpfile("div_any.fsdb");
17    $fsdbDumpvars(0,U_div);
18end
19initial begin
20          clk=0;rst_n=0;
21    #DELY rst_n=1;
22    #((DELY*80000)) $finish;
23end
24endmodule
View Code
4 ⼩结
通过以上⼏个例⼦对⽐不难发现,借助计数器来实现任意点空⽐的任意分频的⽅法简单,且⽤verilog语⾔进⾏⾏为描述时,代码简洁、易懂、通⽤。通过以上的学习,对分频器有了⽐较深刻的认识,将在以后的学习中会有⼴泛的应⽤。
原出处:如有什么疑问,欢迎讨论:QQ:447574829

本文发布于:2023-07-13 12:55:22,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/fan/78/1094331.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

上一篇:多模分频器
标签:时钟   信号   分频器   频率   计数   输出
相关文章
留言与评论(共有 0 条评论)
   
验证码:
推荐文章
排行榜
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图