等占空比任意整数分频器的verilog语言实现

等占空比任意整数分频器的verilog语言实现

    尽管在FPGA设计中,广泛使用芯片厂家集成的锁相环资源如altera的PLL,Xilinx的DLL来进行时钟的分频,倍频以及相移。但在对时钟要求不高或资源有限的情况下,使用硬件描述语言设计电路来进行时钟的分频相移非常实用。因此分频器的设计仍然是FPGA中比较常用的一个设计,同时又被许多公司拿来作为面试题,称其为经典设计也不为过。本文所要讨论的是使用Verilog语言来设计等占空比任意整数分频器。为方便使用和比较,将不同分频倍数的分频器放在了一个模块中。奇偶数分频只需修改参数即可实现任意分频倍数的分频,具体的设计思路可以参考代码的注释,及结合Modelsim的仿真时序图。设计经过Modelsim验证时序正确。设计过程中参考了网上的资料。

    有需要的童鞋可以参考下,欢迎批评指正。

    以下是设计的Verilog实现:freq_divide.v

View Code
  1 `timescale 1ns / 100ps
2 ////////////////////////////////////////////////////////////////////////////////
3 // Company: hangzhou dianzi university
4 // Engineer: D.H.j.
5 //
6 // Create Date: 2011.10.13
7 // Design Name: freq_divide
8 // Module Name: freq_divide
9 // Target Device: <target device>
10 // Tool versions: QuartusII9.0
11 // Description:
12 // 等占空比任意整数分频的verilog语言实现
13 ////////////////////////////////////////////////////////////////////////////////
14
15 module freq_divide(
16 clkin,
17 rst_n,
18 clkout1,//2分频
19 clkout2,//2的n次方分频
20 clkout3,//偶数倍(2J)分频
21 clkout4,
22 clkout5,
23 clkout6//奇数倍(2K+1)分频
24 );
25
26 input clkin;//50MHz
27 input rst_n;
28 output reg clkout1;
29 output clkout2;
30 output reg clkout3;
31 output reg clkout4;
32 output reg clkout5;
33 output clkout6;
34
35 //counter
36 reg[7:0] cnt1;
37 reg[7:0] cnt2;
38 reg[7:0] cnt3;
39 reg[7:0] cnt4;
40
41 /*
42 reg[7:0] cnt;//counter
43 always@( posedge clkin or negedge rst_n )
44 begin
45 if(!rst_n)
46 cnt <= 0;
47 else
48 cnt <= cnt + 1'b1;
49 end
50 */
51
52 //*****************任意整数分频*****************//华丽的分割线
53
54 //最简单的2分频
55 always@( posedge clkin or negedge rst_n )
56 begin
57 if(!rst_n)
58 clkout1 <= 0;
59 else
60 clkout1 <= ~clkout1;
61 end
62
63 //2的n次方分频
64 /*
65 2 0010
66 4 0100
67 8 1000
68 ...
69 */
70 parameter I = 2;//实现4分频 4=2^I I=2
71 always@( posedge clkin or negedge rst_n )
72 begin
73 if(!rst_n)
74 cnt1 <= 0;
75 else
76 cnt1 <= cnt1 + 1'b1;
77 end
78 assign clkout2 = cnt1[I-1];
79
80 //偶数倍(2J)分频
81 //计数器计到一半时,输出时钟翻转,计数器复位
82 parameter J = 3;//实现6分频 6=2M J=3
83 always@( posedge clkin or negedge rst_n )
84 begin
85 if(!rst_n) begin
86 clkout3 <= 0;
87 cnt2 <= 0;
88 end
89 else begin
90 if(cnt2==J-1) begin
91 clkout3 <= ~clkout3;
92 cnt2 <= 0;end
93 else
94 cnt2 <= cnt2 + 1'b1;
95 end
96 end
97
98 //奇数倍(2K+1)分频 经典面试题
99 /*
100 分别利用上升沿和下降沿触发产生两个占空比为(K+1)/(2K+1)的时钟,
101 再将两个时钟进行逻辑与操作,得到奇数倍分频的时钟
102 */
103 parameter K = 5;//实现11分频 11=2K+1 K=5
104 //上升沿计数器
105 always@( posedge clkin or negedge rst_n )
106 begin
107 if(!rst_n) begin
108 cnt3 <= 0;
109 end
110 else begin
111 if(cnt3==2*K)
112 cnt3 <= 0;
113 else
114 cnt3 <= cnt3 + 1'b1;
115 end
116 end
117
118 //一个周期内,正电平占(K+1)/(2K+1)
119 always@( posedge clkin or negedge rst_n )
120 begin
121 if(!rst_n) begin
122 clkout4 <= 0;
123 end
124 else begin
125 if(cnt3==K-1)
126 clkout4 <= 1;
127 else if(cnt3==2*K)
128 clkout4 <= 0;
129 end
130 end
131
132 //下降沿计数器
133 always@( negedge clkin or negedge rst_n )
134 begin
135 if(!rst_n) begin
136 cnt4 <= 0;
137 end
138 else begin
139 if(cnt4==2*K)
140 cnt4 <= 0;
141 else
142 cnt4 <= cnt4 + 1'b1;
143 end
144 end
145
146 always@( negedge clkin or negedge rst_n )
147 begin
148 if(!rst_n) begin
149 clkout5 <= 0;
150 end
151 else begin
152 if(cnt4==K-1)
153 clkout5 <= 1;
154 else if(cnt4==2*K)
155 clkout5 <= 0;
156 end
157 end
158
159 assign clkout6 = clkout4 & clkout5;
160
161 endmodule

 

以下是testbench代码:freq_divide_tb.v

View Code
 1 ////////////////////////////////////////////////////////////////////////////////
2 // Company: hangzhou dianzi university
3 // Engineer: D.H.j.
4 //
5 // Create Date: 2011.10.13
6 // Design Name: freq_divide_tb
7 // Module Name: freq_divide_tb
8 // Target Device: <target device>
9 // Tool versions: QuartusII9.0
10 // Description:
11 // 等占空比任意整数分频的verilog语言实现testbench
12 ////////////////////////////////////////////////////////////////////////////////
13
14 module freq_divide_tb;
15
16 reg clkin;
17 reg rst_n;
18 //counter
19 reg[7:0] cnt1;
20 reg[7:0] cnt2;
21 reg[7:0] cnt3;
22 reg[7:0] cnt4;
23
24 always #10 clkin = ~clkin;//50MHz
25
26 initial
27 begin
28 clkin = 0;
29 rst_n = 0;
30 #10 rst_n = 1;
31 end
32
33 freq_divide u(
34 .clkin(clkin),
35 .rst_n(rst_n),
36 .clkout1(clkout1),
37 .clkout2(clkout2),
38 .clkout3(clkout3),
39 .clkout4(clkout4),
40 .clkout5(clkout5),
41 .clkout6(clkout6)
42 );
43
44 endmodule

 

最后是Modelsim的仿真时序图:



posted @ 2011-10-16 15:08  阿拉灯神丁  阅读(2276)  评论(1编辑  收藏  举报