Verilog实现奇分频电路
Posted 余你余生
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Verilog实现奇分频电路相关的知识,希望对你有一定的参考价值。
在FPGA中,计数器电路用途很广,一般计数器电路都可作为分频电路。实现占空比为50的偶分频电路很好实现。但实现占空比为50的奇分频电路有点难度。下面给出一个简单例子,记录学习奇分频电路的过程。
实现占空比为50的5分频电路,高低电平应都为2.5个时钟周期。即应当在上升沿和下降沿都要采样,这样才会产生出0.5个时钟周期的差。
公式为 奇分频 N 边沿的采集 每隔 N/2 翻转 和 每隔 N-1 翻转。
仿真波形图如下所示:
上升沿:
下降沿:
整体:
其中在上升沿采集中,低电平持续3个时钟周期,高电平持续2个时钟周期。其中在下升沿采集中,低电平持续3个时钟周期,高电平持续2个时钟周期。上升沿与下降沿之间错0.5个时钟周期,即整体为2.5+2.5=5。以后奇分频都可以这样操作。
下附代码和测试激励。
module divfreq( input clk, input rst_n, output clk1x, output reg clk1xpose, output reg clk1xnege, output reg [2:0] coutpose, output reg [2:0] coutnege ); parameter N=5; parameter div1 = N/2 , div2 = N-1; // div1 = 5 / 2, div2 = 5 - 1 always@(posedge clk or negedge rst_n) //上升沿触发波形 begin if(!rst_n) clk1xpose = 0; else if(coutpose == div1) clk1xpose = ~clk1xpose; else if(coutpose == div2) clk1xpose = ~clk1xpose; else clk1xpose = clk1xpose; end always@(negedge clk or negedge rst_n) //下降沿触发波形 begin if(!rst_n) clk1xnege = 0; else if(coutnege == div1) clk1xnege = ~clk1xnege; else if(coutnege == div2) clk1xnege = ~clk1xnege; else clk1xnege = clk1xnege; end always@(posedge clk or negedge rst_n) //上升沿计数5 begin if(!rst_n) coutpose = 0; else if(coutpose == div2) coutpose = 0; else coutpose = coutpose + 1; end always@(negedge clk or negedge rst_n) //下降沿计数5 begin if(!rst_n) coutnege = 0; else if(coutnege == div2) coutnege = 0; else coutnege = coutnege + 1; end assign clk1x = clk1xpose | clk1xnege; //输出波形 endmodule
`timescale 1ns/1ns module tb_divfreq (); reg clk ; reg rst_n ; wire clk1x ; wire clk1xpose ; wire clk1xnege ; wire [2:0] coutpose ; wire [2:0] coutnege ; initial begin clk = 1\'b1 ; rst_n <= 1\'b0 ; #10 rst_n <=1\'b1 ; end always #10 clk=~clk; divfreq divfreq_inst ( .clk (clk) , .rst_n (rst_n) , .clk1x (clk1x) , .clk1xpose (clk1xpose) , .clk1xnege (clk1xnege) , .coutpose (coutpose) , .coutnege (coutnege) ); endmodule
后附正点原子中的另外一种代码风格,但整体思路一致。
波形仿真:
上升沿:
下降沿:
整体:
后附正点原子奇分频代码和激励代码。
module divfreq1 ( input clk , // system clock 50Mhz on board input rst_n, // system rst, low active output out_clk // output signal ); parameter N = 5 ; reg [N/2 :0] cnt_1 ; reg [N/2 :0] cnt_2 ; reg out_clk1 ; reg out_clk2 ; //===================================================================== // ------------------------- MAIN CODE ------------------------------- //===================================================================== always @(posedge clk or negedge rst_n) begin //上升沿输出 out_clk1 if(!rst_n) begin out_clk1 <= 0; cnt_1 <= 1; //这里计数器从 1 开始 end else begin if(out_clk1 == 0) begin if(cnt_1 == N/2+1) begin out_clk1 <= ~out_clk1; cnt_1 <= 1; end else cnt_1 <= cnt_1+1; end else if(cnt_1 == N/2) begin out_clk1 <= ~out_clk1; cnt_1 <= 1; end else cnt_1 <= cnt_1+1; end end always @(negedge clk or negedge rst_n) begin //下降沿输出 out_clk2 if(!rst_n) begin out_clk2 <= 0; cnt_2 <= 1; //这里计数器从 1 开始 end else begin if(out_clk2 == 0) begin if(cnt_2 == N/2+1) begin out_clk2 <= ~out_clk2; cnt_2 <= 1; end else cnt_2 <= cnt_2+1; end else if(cnt_2 == N/2) begin out_clk2 <= ~out_clk2; cnt_2 <= 1; end else cnt_2 <= cnt_2+1; end end assign out_clk = out_clk1 | out_clk2; //输出最后波形 endmodule
`timescale 1ns/1ns module tb_divfreq1 (); reg clk ; reg rst_n ; wire out_clk ; initial begin clk = 1\'b1 ; rst_n <= 1\'b0 ; #10 rst_n <=1\'b1 ; end always #10 clk=~clk; divfreq1 divfreq1_inst ( .clk (clk) , // system clock 50Mhz on board .rst_n (rst_n) , // system rst, low active .out_clk (out_clk) // output signal ); endmodule
参考资料:
1、正点原子逻辑设计指南
2、某奇分频笔试题
以上是关于Verilog实现奇分频电路的主要内容,如果未能解决你的问题,请参考以下文章
IC面试常考题 Verilog三分频电路设计(占空比50%,三分之一,三分之二)
IC面试常考题 Verilog三分频电路设计(占空比50%,三分之一,三分之二)
IC面试常考题 Verilog三分频电路设计(占空比50%,三分之一,三分之二)