原创 Verilog实现时钟3分频

2009-2-17 17:22 4123 5 5 分类: FPGA/CPLD

 


Verilog实现3分频https://static.assets-stash.eet-china.com/album/old-resources/2009/2/17/2ba2f369-0b4b-4aa1-95fd-039aabb1a219.rar<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />


分析思路:


首先考虑输入输出,作为分频电路,有一个时钟输入端clk,输出端div3,再加一个复位端(这里不加也可以),所以输入端clkrst


                                                                输出端 div3


再考虑状态转换的问题


        既然是三分频,应该有3种状态:001 or 110011


在时钟的作用下,应该不停的在这三种状态下转换,并且输出仅仅依赖于当前的状态。


 


代码如下:


//moore fsm


//Written by keaty,<?xml:namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" />University of Southeast


 


module div_fsm(clk,rst,div3);


 


input  clk,rst;


output div3;


reg    div3;


 


parameter[1:0] S0=2'd0,


               S1=2'd1,


               S2=2'd2;


 


reg[1:0] state;


reg[1:0] next_state;


 


always@(posedge clk)


begin


   if(!rst) state<=S0;


   else state<=next_state;


end


 


always@(state)


begin


     //default values


     next_state=S0;


     case(state[1:0])


         S0:begin


              next_state=S1;


              div3=0;


            end


 


         S1:begin


              next_state=S2;


              div3=0;


            end


 


         S2:begin


              next_state=S0;


              div3=1;


            end


      endcase


 


end


 


endmodule


 


顶层测试模块


`timescale 1ns/1ps


 


module div_test;


    reg clk = 1'b0;


    reg rst = 1'b0;


    wire div3;


 


    parameter PERIOD = 200;


    parameter real DUTY_CYCLE = 0.5;


    parameter OFFSET = 100;


 


    initial    // Clock process for clk


    begin


        #OFFSET;


        forever


        begin


            clk = 1'b0;


            #(PERIOD-(PERIOD*DUTY_CYCLE)) clk = 1'b1;


            #(PERIOD*DUTY_CYCLE);


        end


    end


 


    div_fsm UUT (


        .clk(clk),


        .rst(rst),


        .div3(div3));


 


    initial begin


        // -------------  Current Time:  1785ns


        #1785;


        rst = 1'b1;


        // -------------------------------------


    end


 


endmodule


 


Post-Place & Route Simulate


<?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" />


 

点击看大图 


 


缺点:


1.      占空比非50%


2.      状态转换容易出毛刺,状态0110时其中状态输出的第二位会有毛刺,不推荐这样设计,建议改为三段式的写法。


 


三段式状态机三分频实现


代码如下:


module div_fsm3(clk,rst_n,div3);


 


input  clk,rst_n;


output div3;


reg    div3;


 


parameter[1:0] S0=2'd0,


               S1=2'd1,


               S2=2'd2;


 


reg[1:0] current_state;


reg[1:0] next_state;


 


//第一个进程,同步时序always模块,格式化描述次态寄存器迁移到现态寄存器


 


always @ (posedge clk or negedge rst_n)  //异步复位


  begin


       if(!rst_n)


           current_state <= S0;


       else


           current_state <= next_state; //注意,使用的是非阻塞赋值


  end


 


 


//第二个进程,组合逻辑always模块,描述状态转移条件判断


 


always @ (current_state)   //电平触发


  begin


     next_state = S0;  //要初始化,使得系统复位后能进入正确的状态


     case(current_state)


         S0:begin


              next_state=S1;


            end


         S1:begin


              next_state=S2;


            end


         S2:begin


              next_state=S0;


            end


      endcase


  end


 


//第三个进程,同步时序always模块,格式化描述次态寄存器输出


 


always @ (posedge clk)


  begin


     case(next_state)


        S0:div3 <= 1'b0;  //注意是非阻塞逻辑


        S1:div3 <= 1'b0;


        S2:div3 <= 1'b1;


                default:div3 <= 0;


     endcase


  end


 


endmodule


 


顶层测试模块


    与之前的顶层测试模块基本一样,只要把rst改为rst_n


 


Post-Place & Route Simulate



 

点击看大图 


 


    注意的是,第三个进程中,不能是always @ (posedge clk or negedge rst_n),这样的话,综合不了,会出现如下错误信息:


ERROR:Xst:899 - "div_fsm3.v" line 46: The logic for <div3> does not match a known FF or Latch template.


也就是硬件无法实现,综合不了,所以第三个进程要改为如下


                always @ (posedge clk)


 


还要注意的是对于三段式状态机来说


三段式状态机的写法可以参考下面文章


Verilog三段式状态机描述 -- 小倚危楼听春雨


http://blog.ednchina.com/wwh_nuaa/53109/message.aspx


 


三段式状态机要注意的问题可以参考下面文章


verilog 中三段状态机需要注意的问题-yzm520xx的博客-与非网


http://www.eefocus.com/myspace/blog/show.php?id=76269


 


三段式状态机中,需要注意的是第二部分case中的条件应该为当前态,第三部分case中的条件应该为次态。另外就是设计输入的时候一定要仔细。


 


 


参考资料:


13分频的verilog实现


http://www.edacn.net/html/76/27076-2348.html  


 
PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
EE直播间
更多
我要评论
0
5
关闭 站长推荐上一条 /3 下一条