设为首页 加入收藏

TOP

数字分频器设计(偶数分频、奇数分频、小数分频、半整数分频、状态机分频|verilog代码|Testbench|仿真结果)(四)
2023-07-23 13:25:05 】 浏览:164
Tags:数分 verilog 代码 Testbench
#(3*DIV_CLK) rst_n = 0; #(6*DIV_CLK) rst_n = 1; #(20*DIV_CLK); end //源时钟信号生成 always #DIV_CLK clk = ~clk; //模块例化 clk_div_fraction u_clk_div_fraction (.clk (clk), .rst_n (rst_n), .clk_frac (clk_frac) ); endmodule

4.4 仿真结果

请在此添加图片描述

请在此添加图片描述

把5.4小数分频和2.6小数分频进行比较,图一是5.4小数分频仿真时序图,可以看到波形较为整齐;图二是2.6小数分频仿真时序图,可以看到波形较为杂乱;

Tips:5.4小数分频并不是每一段都是均匀的长度(即局部不满足小数分频,总体满足小数分频)

那么是什么原因造成的呢?

从前面的基本原理可以知道,通过双模前置法得到的小数分频波形是差强人意的,5.4小数分频通过5分频和6分频差值得到,2.6小数分频通过2分频和3分频差值得到,同样差一个cnt,对于2.6小数分频的波形破坏要比5.4小数分频要严重。总而言之就是:局部不满足小数分频,总体满足小数分频。

五、半整数分频

5.1 占空比50%半整数分频

对于使用小数分频法得到的,以3.5分频为例,需要使用一个四分频和一个三分频,七个周期内,输出两个1,但是信号时序难以得到保障,时钟信号的质量得不到保证。

那有没有新的方法可以优化半整数分频呢?

可以这样实现半整数分频:
(1)在源时钟上升沿分别产生由 4 个和 3 个源时钟周期组成的 2 个分频时钟。

(2)在源时钟下降沿分别产生由 4 个和 3 个源时钟周期组成的 2 个分频时钟。

(3)两个分频时钟做相位一个延迟半个源时钟周期,一个提前半个源时钟周期。将两次产生的时钟进行“或”操作,便可以得到周期均匀的 3.5 倍分频时钟。分频波形示意图如下所示。

请在此添加图片描述

5.2 Verilog代码

//半整数分频电路设计
module clk_div_half
    (
    input               rst_n,
    input               clk,
    output              clk_div
    );

parameter            DIV_CLK = 7;			//3.5分频的高低电平总个数
reg [3:0]            cnt;					//总计数器
reg                  clk_p;					//上升沿触发生成的时钟信号
reg                  clk_n;					//下降沿触发生成的时钟信号

//计数器模块
always @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
        cnt <= 1'b0 ;
     end
     else if (cnt == DIV_CLK-1) begin 		//从0计数,到6清零
        cnt <= 'b0 ;
     end
     else begin
         cnt <= cnt + 1'b1 ;
     end
end

//上升沿触发生成的时钟信号模块
//计数器到0和4并且在上升沿触发信号翻转
always @(posedge clk or negedge rst_n) begin
    if(!rst_n) begin
          clk_p <= 1'b0;
     end
      else if (cnt == 0) begin					//计数器到0信号翻转
          clk_p <= 1;
      end
      else if (cnt == (DIV_CLK/2)+1) begin		//计数器到4信号翻转
          clk_p <= 1 ;
      end
      else begin
          clk_p <= 0 ;
      end 
end

//下降沿触发生成的时钟信号模块
//计数器到1和4并且在下降沿触发信号翻转
always@(negedge clk or negedge rst_n) begin
    if(!rst_n) begin
         clk_n <= 1'b0 ;
    end
    else if(cnt == 1) begin						//计数器到1信号翻转
         clk_n <= 1 ;
    end
    else if (cnt == (DIV_CLK/2)+1 ) begin		//计数器到4信号翻转
         clk_n<= 1 ;
    end
    else begin
         clk_n <= 0 ;
    end
end

//或逻辑运算得到占空比50%的3.5半整数分频信号
assign clk_div = clk_p | clk_n;

endmodule

5.3 Testbench

`timescale 1ns/1ps			//时间刻度:单位1ns,精度1ps
module clk_div_half_tb;

//信号申明
reg 			clk;
reg 			rst_n;
wire 			clk_div;
  
parameter DIV_CLK0 = 5;		//定义源时钟信号一周期时间

//复位信号生成 
initial begin
    clk = 0;				//时钟信号赋初值
	rst_n = 1;				//复位信号赋初值
	#(3*DIV_CLK0)
	rst_n = 0;
	#(6*DIV_CLK0)
	rst_n = 1;
	#(20*DIV_CLK0);
end

//源时钟信号生成
always #DIV_CLK0 clk = ~clk;

//模块例化
clk_div_half u_clk_div_half
    (.clk             (clk),
     .rst_n           (rst_n),
     .clk_div         (clk_div)
    );

endmodule

5.4仿真结果

请在此添加图片描述

六、状态机分频

6.1状态机分频

Verilog 中状态机主要用于同步时序逻辑的设计,能够在有限个状态之间按一定要求和规律切换时序电路的状态。状态的切换方向不但取决于各个输入值,还取决于当前所在状态。状态机可分为 2 类:Moore 状态机和 Mealy 状态机。

例如完成一个四分频且占空比为25%的分频器,此时可以列出四种状态,状态机在四种状态不断切换,根据下一个输出状态只与当前状态有关而与输出无关,可以知道此分频器可根据Moore状态机完成。

请在此添加图片描述

6.2 verilog代码

module clk_div_FSM
    (
    input wire clk,
    input wire rst_n,
    output reg clk_FSM
    );

//定义四种状态 
parameter	S0 = 2'b00;
parameter	S1 = 2'b01;
parameter	S2 = 2'b10;
parameter	S3 = 2'b11;
 
reg [1:0]	state;			//定义目前状态
reg [1:0]	next_state;		//下一状态

//信号复位模块
always @(posedge clk,negedge rst_n) begin
    if(!rst_n) begin 
        state <= S0;
    end
    else begin
        state <= next_state;
    end
end

//状态转换模块(相当于用状态机写计数器)
always @(*) begin
    case (state)
        S0:	next_state = S1;
        S1:	next_state = S2;
        S2:	next_state = S3;
        S3:	next_state = S0;
    endcase
end

//信号输出模块
always @(*) begin
    if(state == S0) begin
        clk_FSM = 1'b1;
    end
    else begin
        clk_FSM = 1'b0;
首页 上一页 1 2 3 4 5 下一页 尾页 4/5/5
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇「FPGA项目」—— 基于AMBA总线的.. 下一篇基于ZYNQ的OV5640摄像头的sobel算..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目