FPGA等占空比奇偶分频和半整数分频
1. 偶数分频比较简单,如果分频系数是N(如果N是偶数,那么N/2是整数),那么在输入时钟的每隔N/2个周期时(计数器从0到N/2-1),改变输出时钟的电平即可得到50%固定占空比的时钟。需要的代码如下
module even(clk_in,clk_out,rst_n); input clk_in; input rst_n; output clk_out; parameter N=6; reg [3:0] cnt; reg clk_out; always @(posedge clk_in or negedge rst_n) begin if(!rst_n) begin cnt<=4'b0000; clk_out<=0; end else if(cnt==(N/2-1)) begin clk_out<=~clk_out; cnt<=4'b0000; end else cnt<=cnt+1; end endmodule
2. 如果N是奇数,那么N/2非整数,使用2个寄存器,分别用上升沿寄存器计数到(N-1)/2-1电平翻转信号A,再计数到N-1电平翻转信号A,再用下降沿寄存器计数到(N-1)/2-1电平翻转信号B,再计数到N-1电平翻转信号B,,得到两个波形A和B,然后A和B相或即可,代码如下:
module div3(clk,clk_out,rst_n); input clk,rst_n; output clk_out; reg [3:0] cnt_p,cnt_n; reg clk_p,clk_n; parameter N=5; always @(posedge clk or negedge rst_n) begin if(!rst_n) cnt_p<=4'h0; else if(cnt_p==N-1) cnt_p<=0; else cnt_p<=cnt_p+1; end always @(negedge clk or negedge rst_n) begin if(!rst_n) cnt_n<=4'h0; else if(cnt_n==N-1) cnt_n<=0; else cnt_n<=cnt_n+1; end always @(posedge clk or negedge rst_n) begin if(!rst_n) clk_p<=1; else if(cnt_p==(N-1)/2-1) clk_p<=~clk_p; else if(cnt_p==(N-1)) clk_p<=~clk_p; end always @(negedge clk or negedge rst_n) begin if(!rst_n) clk_n<=1; else if(cnt_n==(N-1)/2-1) clk_n<=~clk_n; else if(cnt_n==(N-1)) clk_n<=~clk_n; end assign clk_out=clk_n|clk_p; endmodule
仿真截图如下
3. 半整数分频,本次以2.5分频为例子
//=========================================================== // Author: seuchenrui@126.com // // Description: // This is a simple verilog code for clock frequency division // this code can be used to get // 1. divided by 2.5 //=========================================================== module iCLK_div_shift_register_25 ( input iCLK, input iRESET, output oCLK ); wire [4:0] tmp_shift; reg tmp_0_; reg tmp_2_; reg tmp_3_; reg [4:0] tmp; assign tmp_shift = 5'b0_0001; always@(posedge iCLK or negedge iRESET) begin if(!iRESET) tmp<=tmp_shift; else tmp<={tmp[3:0], tmp[4]}; end always@(negedge iCLK or negedge iRESET) begin if(!iRESET) tmp_0_<=1'b0; else tmp_0_<=tmp[0]; end always@(negedge iCLK or negedge iRESET) begin if(!iRESET) tmp_2_<=1'b0; else tmp_2_<=tmp[2]; end always@(negedge iCLK or negedge iRESET) begin if(!iRESET) tmp_3_<=1'b0; else tmp_3_<=tmp[3]; end assign oCLK = tmp[0]|tmp[1]|tmp_0_|tmp_2_|tmp_3_|tmp[3]; endmodule
3. 半整数分频,这个主要是利用时钟的上升沿和下降沿进行计数。不过分出来的占空比不是50%。问题在于如果被分的时钟不是50%占空比,那么按照下面出来的时钟频率还对吗?不对。
//2.5分频 module div_5(clk,clk_div, rst, temp_out1, temp_out2);//N+0.5 input clk; input rst; output clk_div; reg [3:0] cnt1,cnt2; //output reg temp1,temp2; reg temp1,temp2; output temp_out1, temp_out2; parameter N = 2; //设定分频系数为N+0.5 reg start_negedge; //inital语句不可被综合 //initial //begin // temp1=0;temp2=1; //end //首先进行初始化,temp1=0;temp2=1 //所有的判断信号都要写入 always @(posedge clk or negedge rst) //temp1上升沿跳变 begin if(!rst) begin cnt1<=4'b0; temp1<=0; start_negedge <= 0; end else begin if(cnt1 == 2*N) begin cnt1<=4'b0;end else begin cnt1 <= cnt1 + 4'b1;end if(cnt1==4'b0) begin temp1<=1; start_negedge <= 1;end //高电平时间为N+1; else if(cnt1==N+1) begin temp1<=0;end //低电平时间为N; end end always@(negedge clk or negedge rst) //temp2下降沿跳变 begin if(!rst) begin cnt2<=4'b0; temp2<=1; end else if(start_negedge == 0) begin cnt2<=4'b0; temp2<=1; end else begin if(cnt2==2*N) //2*N begin cnt2<=4'd0;end else begin cnt2<=cnt2+4'd1;end if(cnt2==4'd0) begin temp2<=0;end //低电平时间为N; else if(cnt2==N) begin temp2<=1;end //高电平时间为N+1; end end assign clk_div=temp1&temp2; //逻辑与 assign temp_out1 = temp1; assign temp_out2 = temp2; endmodule
仿真截图如下