【温故而知新】【3】时钟分频-半整数分频N.5
2015-10-06 20:54
381 查看
【温故而知新】【3】时钟分频-半整数分频N.5
本次实现是半整数分频,或者叫做N.5分频。实现的方式是通过移位寄存器。这种方式的思路来源于文献“Clock dividers made easy”, writed by Mohit Arora from ST mircoelectronics, LTD。 Mohit Arora 也写过一本书,叫做“The art of hardware architecture”, 由Springer出版,这本书的第四章的内容跟上述论文的内容一致。实现步骤和方式(N=1)
定义移位寄存器的初值,将移位初值定义为3’b001;定义移位寄存器,每个周期将末位的‘1’向左移位1位,移位产生的中间数据跟初值位宽一致,设为tmp。
采用将tmp[1]寄存一拍,注意此处采用的时钟信号边沿与移位寄存器时钟边沿相反。设移位之后的信号分别位tmp_1_
将tmp[0]、tmp_1_进行 或操作
以下是实现1.5分频的Verilog代码
//=========================================================== // 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 1.5 //=========================================================== module iCLK_div_shift_register_15 ( input iCLK, input iRESET, output oCLK ); wire [2:0] tmp_shift; reg tmp_0_; reg tmp_1_; reg [2:0] tmp; assign tmp_shift = 3'b001; always@(posedge iCLK or negedge iRESET) begin if(!iRESET) tmp<=tmp_shift; else tmp<={tmp[1:0], tmp[2]}; end always@(negedge iCLK or negedge iRESET) begin if(!iRESET) tmp_1_<=1'b0; else tmp_1_<=tmp[1]; end assign oCLK = tmp[0]|tmp_1_; endmodule
1.5分频的仿真波形
实现步骤和方式(N>2):
定义移位寄存器的初值,比如4.5分频时,将移位初值定义为9’b0_0000_0001,3.5分频时,将移位器初值定义为7’b000_0001,以此类推。定义移位寄存器,每个周期将末位的‘1’向左移位1位,移位产生的中间数据跟初值位宽一致,设为tmp。
采用将tmp[0]、tmp[1]、tmp
和tmp[N+1]寄存一拍,注意此处采用的时钟信号边沿与移位寄存器时钟边沿相反。设移位之后的信号分别位tmp_0_, tmp_1_, tmp_N_, tmp_N+1_
将tmp[0]、tmp[1]、tmp_0_、tmp_N_, tmp_N+1_、tmp[N+1]进行 或操作
以下是实现2.5、3.5、4.5和13.5分频的Verilog代码
//=========================================================== // 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
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 3.5 //=========================================================== module iCLK_div_shift_register_35 ( input iCLK, input iRESET, output oCLK ); wire [6:0] tmp_shift; reg tmp_0_; reg tmp_3_; reg tmp_4_; reg [6:0] tmp; assign tmp_shift = 7'b000_0001; always@(posedge iCLK or negedge iRESET) begin if(!iRESET) tmp<=tmp_shift; else tmp<={tmp[5:0], tmp[6]}; 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_3_<=1'b0; else tmp_3_<=tmp[3]; end always@(negedge iCLK or negedge iRESET) begin if(!iRESET) tmp_4_<=1'b0; else tmp_4_<=tmp[4]; end assign oCLK = tmp[0]|tmp[1]|tmp_0_|tmp_4_|tmp_3_|tmp[4]; endmodule
3.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 4.5 //=========================================================== module iCLK_div_shift_register_45 ( input iCLK, input iRESET, output oCLK ); wire [8:0] tmp_shift; reg tmp_0_; reg tmp_4_; reg tmp_5_; reg [8:0] tmp; assign tmp_shift = 9'b0_0000_0001; always@(posedge iCLK or negedge iRESET) begin if(!iRESET) tmp<=tmp_shift; else tmp<={tmp[7:0], tmp[8]}; 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_4_<=1'b0; else tmp_4_<=tmp[4]; end always@(negedge iCLK or negedge iRESET) begin if(!iRESET) tmp_5_<=1'b0; else tmp_5_<=tmp[5]; end assign oCLK = tmp[0]|tmp[1]|tmp_0_|tmp_4_|tmp_5_|tmp[5]; endmodule
4.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 13.5 //=========================================================== module iCLK_div_shift_register_135 ( input iCLK, input iRESET, output oCLK ); wire [26:0] tmp_shift; reg tmp_0_; reg tmp_13_; reg tmp_14_; reg [26:0] tmp; assign tmp_shift = 27'b0_0000_0000_0000_0000_0000_0001; always@(posedge iCLK or negedge iRESET) begin if(!iRESET) tmp<=tmp_shift; else tmp<={tmp[25:0], tmp[26]}; 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_13_<=1'b0; else tmp_13_<=tmp[13]; end always@(negedge iCLK or negedge iRESET) begin if(!iRESET) tmp_14_<=1'b0; else tmp_14_<=tmp[14]; end assign oCLK = tmp[0]|tmp[1]|tmp_0_|tmp_13_|tmp_14_|tmp[14]; endmodule
13.5分频的仿真波形
调整分频信号占空比
上述波形显示,13.5分频时钟信号的占空比很小,那么如果想要占空比40%~60%的分频信号呢?应该怎么调整代码?答案是增加或操作中的信号数,依然以13.5分频为例,assign oCLK = tmp[0]|tmp[1]|tmp[2]|tmp[3]|tmp[4]|tmp[5]|tmp_0_|tmp_1_|tmp_2_| tmp_3_ |tmp_4_ | tmp_13_|tmp_14_|tmp_15_|tmp_16_|tmp_17_|tmp_18_|tmp[14]|tmp[15]|tmp[16]|tmp[17]|tmp[18];
两行代码分别产生两个周期的分频信号,其中上一行是移位寄存器信号的或操作,而tmp_0_~tmp_4_则是为了消除或操作可能产生的毛刺,下一行是经过相反时钟边沿寄存之后的信号,同样的道理,tmp[14]~tmp[18]是为了消除或操作可能造成的毛刺信号。
以下是13.5分频,占空比大于40%的Verilog代码
//===========================================================
// 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 13.5,clock duty > 40%
//===========================================================
module iCLK_div_shift_register_135
(
input iCLK,
input iRESET,
output oCLK
);
wire [26:0] tmp_shift;
reg tmp_0_;
reg tmp_1_;
reg tmp_2_;
reg tmp_3_;
reg tmp_4_;
reg tmp_5_;
reg tmp_13_;
reg tmp_14_;
reg tmp_15_;
reg tmp_16_;
reg tmp_17_;
reg tmp_18_;
reg [26:0] tmp;
assign tmp_shift = 27'b0_0000_0000_0000_0000_0000_0001;
always@(posedge iCLK or negedge iRESET)
begin
if(!iRESET)
tmp<=tmp_shift;
else
tmp<={tmp[25:0], tmp[26]};
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_1_<=1'b0;
else
tmp_1_<=tmp[1];
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
always@(negedge iCLK or negedge iRESET)
begin
if(!iRESET)
tmp_4_<=1'b0;
else
tmp_4_<=tmp[4];
end
always@(negedge iCLK or negedge iRESET)
begin
if(!iRESET)
tmp_5_<=1'b0;
else
tmp_5_<=tmp[5];
end
always@(negedge iCLK or negedge iRESET)
begin
if(!iRESET)
tmp_13_<=1'b0;
else
tmp_13_<=tmp[13];
end
always@(negedge iCLK or negedge iRESET)
begin
if(!iRESET)
tmp_14_<=1'b0;
else
tmp_14_<=tmp[14];
end
always@(negedge iCLK or negedge iRESET)
begin
if(!iRESET)
tmp_15_<=1'b0;
else
tmp_15_<=tmp[15];
end
always@(negedge iCLK or negedge iRESET)
begin
if(!iRESET)
tmp_16_<=1'b0;
else
tmp_16_<=tmp[16];
end
always@(negedge iCLK or negedge iRESET)
begin
if(!iRESET)
tmp_17_<=1'b0;
else
tmp_17_<=tmp[17];
end
always@(negedge iCLK or negedge iRESET)
begin
if(!iRESET)
tmp_18_<=1'b0;
else
tmp_18_<=tmp[18];
end
//assign oCLK = tmp[0]|tmp[1]|tmp_0_|tmp_13_|tmp_14_|tmp[14];
assign oCLK = tmp[0]|tmp[1]|tmp[2]|tmp[3]|tmp[4]|tmp[5]|tmp_0_|tmp_1_|tmp_2_| tmp_3_ |tmp_4_ | tmp_13_|tmp_14_|tmp_15_|tmp_16_|tmp_17_|tmp_18_|tmp[14]|tmp[15]|tmp[16]|tmp[17]|tmp[18];
endmodule
13.5分频,占空比大于40%的仿真波形
后续将继续研究时钟分频
相关文章推荐
- 关于mysql_affected_rows()
- 软件工程之程序编码
- 【转】不要学习代码,要学会思考
- 【bzoj4144】[AMPPZ2014]Petrol
- adb 命令
- 关于线程操作的waitpid()
- 面向对象的一些概念及举例说明
- C++顺序循环队列
- Foj 2203 Problem 2203 单纵大法好 stl应用
- 解决UIGestureRecognizer手势与视图上其他滑动视图的冲突
- 视图(View) – ASP.NET MVC 4 系列
- [算法运用研究]局部标准差实现对比度增强
- Swift属性
- Linux命令之wc命令使用详解
- Pain类的常用属性设置方法
- 关于用C操作mysql的一些函数介绍
- 关于 微软必应词典客户端 的案例分析
- CodeForcesGym 100212E Long Dominoes
- storyboard设置圆角按钮
- 【Python】Learn Python the hard way, ex0 学习使用Terminal