欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程资源 > 编程问答 >内容正文

编程问答

8分频verilog线_Verilog设计分频器(面试必看)

发布时间:2025/3/21 编程问答 60 豆豆
生活随笔 收集整理的这篇文章主要介绍了 8分频verilog线_Verilog设计分频器(面试必看) 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

分频器是指使输出信号频率为输入信号频率整数分之一的电子电路。在许多电子设备中如电子钟、频率合成器等,需要各种不同频率的信号协同工作,常用的方法是以稳定度高的晶体振荡器为主振源,通过变换得到所需要的各种频率成分,分频器是一种主要变换手段。

早期的分频器多为正弦分频器,随着数字集成电路的发展,脉冲分频器(又称数字分频器)逐渐取代了正弦分频器。

下面以Verilog HDL 语言为基础介绍占空比为50%的分频器。

1、偶分频

偶分频电路指的是分频系数为 2、4、6、8 ... 等偶数整数的分频电路,我们可以直接进行分频。

例如下面 divider.v 中,对输入时钟进行6分频,即假设clk 为 50MHz ,分频后的时钟频率为 (50/6) MHz。程序如下:

设计代码:

1 //rtl

2 moduledivider(3 clk,4 rst_n,5 clk_div6 );7 inputclk;8 inputrst_n;9 outputclk_div;10 regclk_div;11

12 parameter NUM_DIV = 6;13 reg [3:0] cnt;14

15 always @(posedge clk or negedgerst_n)16 if(!rst_n) begin

17 cnt <= 4'd0;

18 clk_div <= 1'b0;

19 end

20 else if(cnt < NUM_DIV / 2 - 1) begin

21 cnt <= cnt + 1'b1;

22 clk_div <=clk_div;23 end

24 else begin

25 cnt <= 4'd0;

26 clk_div <= ~clk_div;27 end

28 endmodule

View Code

仿真程序:

1 //tb

2 moduledivider_tb();3 regclk;4 regrst_n;5 wireclk_div;6 parameter DELY=100;7 divider U_divider(8 .clk (clk ),9 .rst_n (rst_n ),10 .clk_div(clk_div)11 );12 always #(DELY/2) clk=~clk;//产生时钟波形

13 initial begin

14 $fsdbDumpfile("divider_even.fsdb");15 $fsdbDumpvars(0,U_divider);16 end

17 initial begin

18 clk=0;rst_n=0;19 #DELY rst_n=1;20 #((DELY*20)) $finish;21 end

22 endmodule

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

2 moduledivider(3 clk,4 rst_n,5 clk_div6 );7 inputclk;8 inputrst_n;9 outputclk_div;10 regclk_div;11

12 parameter NUM_DIV = 5;13 reg[2:0] cnt1;14 reg[2:0] cnt2;15 regclk_div1, clk_div2;16

17 always @(posedge clk or negedgerst_n)18 if(!rst_n)19 cnt1 <= 0;20 else if(cnt1 < NUM_DIV - 1)21 cnt1 <= cnt1 + 1'b1;

22 else

23 cnt1 <= 0;24

25 always @(posedge clk or negedgerst_n)26 if(!rst_n)27 clk_div1 <= 1'b1;

28 else if(cnt1 < NUM_DIV / 2)29 clk_div1 <= 1'b1;

30 else

31 clk_div1 <= 1'b0;

32

33 always @(negedge clk or negedgerst_n)34 if(!rst_n)35 cnt2 <= 0;36 else if(cnt2 < NUM_DIV - 1)37 cnt2 <= cnt2 + 1'b1;

38 else

39 cnt2 <= 0;40

41 always @(negedge clk or negedgerst_n)42 if(!rst_n)43 clk_div2 <= 1'b1;

44 else if(cnt2 < NUM_DIV / 2)45 clk_div2 <= 1'b1;

46 else

47 clk_div2 <= 1'b0;

48

49 assign clk_div = clk_div1 |clk_div2;50 endmodule

View Code

仿真代码:

1 //tb

2 moduledivider_tb();3 regclk;4 regrst_n;5 wireclk_div;6 parameter DELY=100;7 divider U_divider(8 .clk (clk ),9 .rst_n (rst_n ),10 .clk_div(clk_div)11 );12 always #(DELY/2) clk=~clk;//产生时钟波形

13 initial begin

14 $fsdbDumpfile("divider_odd.fsdb");15 $fsdbDumpvars(0,U_divider);16 end

17 initial begin

18 clk=0;rst_n=0;19 #DELY rst_n=1;20 #((DELY*20)) $finish;21 end

22 endmodule

View Code

对其进行测试和验证(此仿真波形是三分频,占空比50%),即上述程序吧NUM_DIV改成3即可,得到如下波形:

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

在verilog程序设计中,我们往往要对一个频率进行任意分频,而且占空比也有一定的要求这样的话,对于程序有一定的要求。

现在在前面两个实验的基础上做一个简单的总结,实现对一个频率的任意占空比的任意分频。

比如: FPGA系统时钟是50M Hz,而我们要产生的频率是880Hz,那么,我们需要对系统时钟进行分频。很容易想到用计数的方式来分频:50000000/880 = 56818。

显然这个数字不是2的整幂次方,那么我们可以设定一个参数,让它到56818的时候重新计数就可以实现了。程序如下:

设计代码:

1 //rtl

2 modulediv(3 clk,4 rst_n,5 clk_div6 );7 inputclk,rst_n;8 outputclk_div;9 regclk_div;10

11 reg [15:0] counter;12

13 always @(posedge clk or negedgerst_n)14 if(!rst_n)15 counter <= 0;16 else if(counter==56817)17 counter <= 0;18 else

19 counter <= counter+1;20

21 assign clk_div = counter[15];22 endmodule

View Code

仿真代码:

1 //tb

2 modulediv_tb();3 regclk;4 regrst_n;5 wireclk_div;6 parameter DELY=100;7 div U_div(8 .clk (clk ),9 .rst_n (rst_n),10 .clk_div(clk_div)11 );12 always #(DELY/2) clk=~clk;//产生时钟波形

13 initial begin

14 $fsdbDumpfile("div_any.fsdb");15 $fsdbDumpvars(0,U_div);16 end

17 initial begin

18 clk=0;rst_n=0;19 #DELY rst_n=1;20 #((DELY*80000)) $finish;21 end

22 endmodule

View Code

分频的应用很广泛,一般的做法是先用高频时钟计数,然后使用计数器的某一位输出作为工作时钟进行其他的逻辑设计,上面的程序就是一个体现。

下面我们来算一下它的占空比:

我们清楚地知道,这个输出波形在counter为0到32767(2的14次方)的时候为低,在32768到56817的时候为高,占空比为40%多一些,

如果我们需要占空比为50%,那么我们需要再设定一个参数,使它为56817的一半,使达到它的时候波形翻转,就可以实现结果了。

程序如下:28408=56818/2-1,计数到28408就清零,翻转,其余的计数期间,保持不变。

设计代码:

1 //rtl

2 modulediv(3 clk,4 rst_n,5 clk_div6 );7 inputclk,rst_n;8 outputclk_div;9 regclk_div;10 reg [14:0] counter;11 always @(posedge clk or negedgerst_n)12 if(!rst_n)13 counter <= 0;14 else if(counter==28408)15 counter <= 0;16 else

17 counter <= counter+1;18

19 always @(posedge clk or negedgerst_n)20 if(!rst_n)21 clk_div <= 0;22 else if(counter==28408)23 clk_div <= ~clk_div;24 endmodule

View Code

仿真代码:

1 //tb

2 modulediv_tb();3 regclk;4 reg rst_n=0;5 wireclk_div;6 parameter DELY=100;7 div U_div(8 .clk (clk ),9 .rst_n (rst_n),10 .clk_div(clk_div)11 );12 always #(DELY/2) clk=~clk;//产生时钟波形

13 initial begin

14 $fsdbDumpfile("div_any.fsdb");15 $fsdbDumpvars(0,U_div);16 end

17 initial begin

18 clk=0;rst_n=0;19 #DELY rst_n=1;20 #((DELY*80000)) $finish;21 end

22 endmodule

View Code

继续让我们来看如何实现任意占空比,比如还是由50M分频产生880Hz,而分频得到的信号的占空比为30%。

56818×30%=17045

设计代码:

1 //rtl

2 modulediv(3 clk,4 rst_n,5 clk_div,6 counter7 );8 inputclk,rst_n;9 outputclk_div;10 regclk_div;11 output [15:0] counter;12 reg [15:0] counter;13

14 always @(posedgeclk)15 if(!rst_n)16 counter <= 0;17 else if(counter==56817)18 counter <= 0;19 else counter <= counter+1;20

21 always @(posedgeclk)22 if(!rst_n)23 clk_div <= 0;24 else if(counter<17045)25 clk_div <= 1;26 else

27 clk_div <= 0;28 endmodule

View Code

仿真代码:

1 //tb

2 modulediv_tb();3 regclk;4 regrst_n;5 wireclk_div;6 wire [15:0] counter;7 parameter DELY=100;8 div U_div(9 .clk (clk ),10 .rst_n (rst_n ),11 .counter(counter),12 .clk_div(clk_div)13 );14 always #(DELY/2) clk=~clk;//产生时钟波形

15 initial begin

16 $fsdbDumpfile("div_any.fsdb");17 $fsdbDumpvars(0,U_div);18 end

19 initial begin

20 clk=0;rst_n=0;21 #DELY rst_n=1;22 #((DELY*80000)) $finish;23 end

24 endmodule

View Code

4 小结

通过以上几个例子对比不难发现,借助计数器来实现任意点空比的任意分频的方法简单,且用verilog语言进行行为描述时,代码简洁、易懂、通用。

通过以上的学习,对分频器有了比较深刻的认识,将在以后的学习中会有广泛的应用。

总结

以上是生活随笔为你收集整理的8分频verilog线_Verilog设计分频器(面试必看)的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。