二分频
二分频应该是最简单的,就是每当检测到输入时钟的高电平时就将输出翻转一下就行了。
实例如下:
1 2 3 4 5 6 7 8 9 10 11 |
module div2(clk,clkout,reset); input clk; input reset; output clkout; reg clkout; always @(posedge clk or posedge reset) clkout =~ clkout; endmodule |
激励文件如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
module div2_1; reg clk; reg reset; div2 d2 (clk,clkout,reset); always @ #20 clk=~clk; initial begin clk = 1'b0; reset = 1'b1; #24 reset = 1'b0; end endmodule |
!!!在这里出现了一个问题,always @ (posedge clk or negedge reset) 如果这样写的话,就会报错Assignment under multiple single edges is not supported for synthesis 只有把negedge换成posege才行,目前还不知道为什么会这样。
三分频
三分频的思想就是通过一个计数器,当累积到一定的数量的时候,就让输出信号进行翻转。这里的3分频占空比不是50%,而是75%。
实例如下
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 |
module div_3 (q,clk,reset); output q; input reset; input clk; reg q; reg [1:0] count; //设了一个2位的计数器可以从00计数到11; always @ (posedge clk or posedge reset) //同步复位,上升沿有效 if (reset) //复位 begin q<=1'b0; count<=2'b00; end else if(count==2'b00) //第一个CLK上升沿来的时候q翻转一次计数器加一; begin q<=~q; count<=count+1'b1; end else if(count==2'b10) //第3个CLK上升沿来的时候输出q翻转一次计数器归零; begin q=~q; count<=2'b00; end else //第二个CLK上升沿来的时候q不动作,计数器加一。 begin count<=count+1'b1; endendmodule |
下面这个是我自己写的三分频:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
module div3(clk,clkout,reset); input clk; input reset; output clkout; reg clkout; reg [1:0] count;//第一个错误,count作为一个寄存器,要标明大小[n:m] always @(posedge clk or posedge reset) if (reset) begin clkout <= 1'b0; count <= 2'b00; endelse if (count == 2'b00) begin clkout <= ~clkout;//第二个错误,clkout要用非阻塞语句,即<=而不是= count <= count+1; end else if (count == 2'b01) count <= count+1; else if (count == 2'b10) begin clkout <= ~clkout; count <= 2'b00; endendmodule |
激励文件如下:
1 2 3 4 5 6 7 8 9 10 11 |
module top1; reg clk; reg reset; div_3 d3 (q,clk,reset); always #20 clk=~clk; initial //initial中的语句只执行一次 begin clk=1'b0; reset=1'b1; #24 reset =1'b0; endendmodule |
任意分频
偶分频N
仿照之前3分频,当计数器记到2的时候,进行翻转。为什么这样呢?因为0代表第一个上升沿,1代表第二个上升沿,2代表第三个上升沿,所以我们想3分频,就需要在第三个上升沿的时候进行翻转,即N分频,就需要在第N个上升沿的时候进行翻转。
实例如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
module divn(clk_out,clk_in,rst); output clk_out; input clk_in; input rst; reg [3:0] cnt;//这里改成[1:0]也可以,为什么呢,因为只需要记到N/2-1就可以了,这里N=6,所以最大也就是2,所以够用。reg clk_out; parameter N=6; always @ (posedge clk_in or posedge rst) beginif(rst) begin cnt <= 0; clk_out <= 0; endelse begin if(cnt==N/2-1) begin clk_out <= !clk_out; cnt<=0; end else cnt <= cnt + 1; endendendmodule |
激励文件如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
module divnn; // Inputs reg clk_in; reg rst; // Outputs wire clk_out;//这里改成reg就不行了,clkout的值就变成了X,不知道为什么 // Instantiate the Unit Under Test (UUT) divn uut ( .clk_out(clk_out), .clk_in(clk_in), .rst(rst) ); always #20 clk_in=~clk_in; initial begin // Initialize Inputs clk_in = 1'b0; rst = 1'b1; #20 rst = 1'b0; end endmodule |
奇分频N
下面是实例程序,还没有看
关于奇分频的原理,讲解上是这么说的:
实现奇数(N)分频,分别用上升沿计数到(N-1)/2,再计数到N-1;用下降沿计数到(N-1)/2,再计数到N-1,得到两个波形,然后把它们相或即可得到N分频。
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 |
module fp_odd(clk_out,clk_p,clk_n,clk_in,rst); output clk_out; output clk_p,clk_n; input clk_in,rst; reg [2:0] cnt_p,cnt_n; reg clk_p,clk_n; parameter N=5; always @ (posedge clk_in or negedge rst) begin if(!rst) cnt_p <= 0; else if(cnt_p==N-1) cnt_p <=0; else cnt_p <= cnt_p + 1; endalways @ (posedge clk_in or negedge rst) begin if(!rst) clk_p <= 0; else if(cnt_p==(N-1)/2) clk_p <= !clk_p; else if(cnt_p==N-1) clk_p <= !clk_p; endalways @ (negedge clk_in or negedge rst) begin if(!rst) cnt_n <= 0; else if(cnt_n==N-1) cnt_n <=0; else cnt_n <= cnt_n + 1; endalways @ (negedge clk_in or negedge rst) begin if(!rst) clk_n <= 0; else if(cnt_n==(N-1)/2) clk_n <= !clk_n; else if(cnt_n==N-1) clk_n <= !clk_n; endassign clk_out = clk_p | clk_n; endmodule |
任意的
最后一个是非常经典的,可以任意分频,只需要更改K的值即可。
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 |
module m1k(rst_n,clk,k,clkk); input rst_n; input clk; input [3:0] k; reg clk1; reg clk2; output clkk; reg [3:0] k1; reg [3:0] k2; always@(negedge rst_n or posedge clk) begin if(~rst_n) begin k1 <= 4'b0; clk1 <= 1'b0; end else begin if(k1==(k-1)) clk1 <= ~clk1; if(k1==((k>>1)-1'b1)) clk1 <= ~clk1; if(k1==k-1) k1 <= 4'b0000; else k1 <= k1+4'b0001; endend always@(negedge rst_n or negedge clk) begin if(~rst_n) begin k2 <= 4'b0; clk2 <= 1'b0; end else begin if(k2 == k-1) k2 <= 4'b0000; else k2 <= k2+4'b0001; if(k2==k-1) clk2 <= ~clk2; if(k2==((k>>1)-1'b1)) clk2 <= ~clk2; end endassign clkk = (k%2)?clk1&clk2:clk1; endmodule |
下面是激励文件(只需要更改k的值即可,不过要注意寄存器的大小,不要超了):
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 |
module reny; // Inputs reg rst_n; reg clk; reg [3:0] k; // Outputs wire clkk; // Instantiate the Unit Under Test (UUT) m1k uut ( .rst_n(rst_n), .clk(clk), .k(k), .clkk(clkk) ); always #20 clk=~clk; initial begin // Initialize Inputs rst_n = 0; clk = 0; k = 5; #24 rst_n=1; end endmodule |
本文最后更新于2017年5月21日,已超过 1 年没有更新,如果文章内容或图片资源失效,请留言反馈,我们会及时处理,谢谢!