知识点(分频器)

1、奇偶数分频(经典)

module div_fre#(
	parameter DIV_N = 'd4
);
(
	input clk,
  	input rst_n,
  	output clk_div
);
reg [$clog2(DIV)-1:0]cnt;
always@(posedge clk or negedge rst_n)begin
		if(!rst_n)
          cnt <= 0;
		else if(add_cnt)
          begin
        	if(end_cnt)
              cnt <= 0;
        	else
              cnt <= cnt + 1;
        end
		
end
assign add_cnt = 1;
assign end_cnt = add_cnt&&(cnt == DIV_N -1);

always@(negedge clk or negedge rst_n)begin
		if(!rst)
          clk1 <= 0;
		else if(cnt == (DIV_N-1)/2)
          clk1 <= 1;
		else if(cnt == DIV_N-1)
          clk1 <= 0;
		else
          clk1 <= clk1;

end
always@(posedge clk or negedge rst_n)begin
		if(rst_n)
          clk2 <= 0;
		else if(cnt == (DIV_N-1)/2)
          clk2 <= 1;
		else if(cnt == DIV_N-1)
          clk2 <= 0;
		else 
          clk2 <= clk2;

end
assign clk_even = clk2;
assign clk_odd = clk1|clk2;
assign clk_out = (DIV_N%2)?clk_odd:clk_even;

2、N+0.5分频

对于常规的非50%分频,可以是在N+0.5的情况下,上升沿计数应到2N清零,并且在0与N+1时翻转。

下降沿计数应到2N清零,并且在0与N时翻转。

对于改进的接近50%分频比,可以是在N+0.5的情况下,上升沿计数应到2N清零,在0与2N+1/2时翻转,

下降沿计数应在N/2与N时翻转。

`timescale 1ns / 1ps

module divider_point5 #(parameter CLK_N = 2)
(
	input				clk_in,
	input				rst_n,
	
	output	reg			clk_2in,				// 2N倍频时钟
	output	reg			clk_2in_2,				// 下降沿2N倍频时钟
	//output				clk_en,
	output				clk_N_point5,
	output	reg			clk_out
    );
    
    reg		[7:0]		cnt_2N;					// 2N倍频时钟计数
    reg		[7:0]		cnt_2N_2;				// 下降沿2N倍频时钟计数
    
    reg					clk_out_g1;
    
    
    
    assign			clk_N_point5 = 	clk_2in && clk_2in_2;
    
    // 上升沿生成2N分频时钟电路
    always@(posedge clk_in or negedge rst_n) begin
    	if(!rst_n)
    		cnt_2N <= 8'b0;
    	else if(cnt_2N == 2*CLK_N)
    		cnt_2N <= 8'b0;
    	else 
    		cnt_2N <= cnt_2N + 1'b1;
    end
    always@(posedge clk_in or negedge rst_n) begin
    	if(!rst_n)
    		clk_2in <= 1'b0;
    	//else if((cnt_2N == CLK_N+1) ||( cnt_2N ==0 )) begin			// 这个是占空比为1:2N+1,未改进
    	else if((cnt_2N == CLK_N+1+CLK_N/2) ||( cnt_2N ==0 )) begin		// 这个是占空比尽量靠近0.5的方式
    		clk_2in <= ~clk_2in;
    	end
    	else 
    		clk_2in <= clk_2in;
    end
    
    // 下降沿生成2N分频时钟电路
    always@(negedge clk_in or negedge rst_n) begin
    	if(!rst_n)
    		cnt_2N_2 <= 8'b0;
    	else if(cnt_2N_2 == 2*CLK_N)
    		cnt_2N_2 <= 8'b0;
    	else 
    		cnt_2N_2 <= cnt_2N_2 + 1'b1;
    end
    always@(negedge clk_in or negedge rst_n) begin
    	if(!rst_n)
    		clk_2in_2 <= 1'b1;
    	//else if((cnt_2N_2 == CLK_N) ||( cnt_2N_2 == 0 )) begin		// 这个是占空比为1:2N+1,未改进
    	else if((cnt_2N_2 == CLK_N) ||( cnt_2N_2 == CLK_N/2 )) begin	// 这个是占空比尽量靠近0.5的方式
    		clk_2in_2 <= ~clk_2in_2;
    	end
    	else 
    		clk_2in_2 <= clk_2in_2;
    end  
    
    
endmodule


3、任意小数分频(两种方法)

(1)脉冲删除法

module point_clk(
	 output reg   clkout,
                  input        rstn,
                  input        refclk,
                  input [31:0] fenzi,//fenzi/fenmu must equal or more than 2
                  input [31:0] fenmu, //fenzi/fenmu must equal or more than 2
				  output  reg [31:0]               cnt
);
 reg [2:0]                   rstn_syn;
  
   always @(posedge refclk) begin
      rstn_syn[0] <= rstn;
      rstn_syn[1] <= rstn_syn[0];
      rstn_syn[2] <= rstn_syn[1];
   end
   always @(posedge refclk or negedge rstn_syn[2]) begin
      if(!rstn_syn[2]) cnt <= 0;
      else begin
         if(cnt < fenzi) cnt <= cnt + fenmu;
         else cnt <= cnt + fenmu - fenzi;
      end
   end
   
   always @(posedge refclk or negedge rstn_syn[2]) begin
      if(!rstn_syn[2]) clkout <= 0;
      else begin
         if(((cnt > (fenzi>>1)) || (cnt == (fenzi>>1))) && (cnt < fenzi)) clkout <= 1;
         else clkout <= 0;
      end
   end

endmodule

(2)双模置数法

以8.7分频为例,小数分频不可能50%

module DIV_M_N#(
parameter M_N = 'd87,
parameter ceo = 'd24,
parameter DIV_E = 'd8,
parameter DIV_O = 'd9
)
(
	input clk,
  	input rst_n,
  	output clk_out

);
reg[$clog2(M_N)-1:0] cnt;
reg[$clog2(DIV_E)-1:0]cnt2;
reg[$clog2(DIV_O)-1:0]cnt1;
always@(posedge clk or negedge rst_n)begin
		if(!rst_n)
          cnt <= 0;
		else if(cnt == M_N-1)
          cnt <= 0;
		else
          cnt <= cnt + 1;
end
always@(posedge clk or negedge rst_n)begin
		if(!rst_n)
          begin
          cnt1 <= 0;
          cnt2 <= 0;
		end
        else if(cnt <= ceo - 1)
          begin
          cnt1 <= 0;
          
          	if(cnt2 == DIV_E)
              cnt2 <= 0;
			else
              cnt2 <= cnt2 + 1;
          end
        else if(cnt > ceo)
          begin
          cnt2 <= 0;
          
          	if(cnt1 == DIV_O)
          	cnt1 <= 0;
			else
           cnt1 <= cnt1 + 1;
          end

end

always@(posedge clk or negedge rst_n)begin
		if(!rst_n)
          clk_M_N <= 0;
		else begin
        	if(cnt < ceo)
            begin
            	if(cnt2 ==0||cnt2==DIV_E/2)
                  clk_M_N <= ~clk_M_N;
            end
            else if(cnt>=ceo)
              begin
              	if(cnt1 == 0||cnt1 == (DIV_O-1)/2)
                  clk_M_N <= ~clk_M_N;
              end
        end

end
全部评论

相关推荐

💼公司岗位&nbsp;tx客户端岗本人背景中九硕,cpp选手。当时在牛子上看cpp选手找不到后端岗实习,遂投了腾子的客户端想练练手。🕐面试过程投递之后很快约面了,一面面试官比较和蔼问的也是正常八股加项目的模式。然后约了二面,二面面试官应该是入职后的leader,这轮面试就离谱了,一开始问了一些八股(感觉那面试官也不怎么懂技术像是照着书上写好的问题问一样),后面离谱的来了,直接疯狂压力测试(你为什么觉得你能xxx,你能不能接受xxx)。当时因为对tx还有滤镜,把自己当作一个牛马的姿态来回答这些问题。面完之后面试官可能觉得我是一个合格的牛马,他加了我微信,问我什么时候能去实习,我说六月初,他说有点晚了,然后考虑了一天还是给我过了面试,然后3面和hr面就也是正常流程了。🐶事件起因5月末的时候导师临时给安排了一个项目,于是我就去微信问那个leader,能不能推迟到6月24入职,如果不能我可以主动放弃offer,他当时犹豫再三还是同意了(现在回想起来可能是当时还没有备胎)。就在昨天他又问我什么时候入职,然后我说24号,他说有点晚叫我看看系统上还有没有其它入职时间,因为我还没在系统上填入职信息(在牛子上看到说只有快入职了,才会有人审核,遂想端午节后再填),查看不了可申请入职的时间。和他说了原因后,这下给他抓到把柄了,直接来一句&amp;quot;你对这次实习并不重视,确实没什么必要了&amp;quot;&nbsp;&nbsp;😅。感觉应该是找到备胎硬气了,就想把我踹走。不过爷也不想去了,客户端前景本来就不太好,这个leader也是个pua怪加压力怪,反正也是双向选择。最后再给大家一个建议,在面试过程中就感觉不舒服的组,一定不要去了,去了也只会更难受。 #不给转正的实习,你还去吗#&nbsp;&nbsp;#找实习多的是你不知道的事#
景洪:“在面试过程中就感觉不舒服的组,一定不要去了,去了也只会更难受。” 谢谢楼主的总结,这个太赞同了,我有次就是实习前面试感觉体验特别差,入职之后就是各种pua和压力。 大佬,你值得更好的
点赞 评论 收藏
分享
点赞 1 评论
分享
牛客网
牛客企业服务