Verilog实现时钟3分频<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
Verilog实现3分频
分析思路:
首先考虑输入输出,作为分频电路,有一个时钟输入端clk,输出端div3,再加一个复位端(这里不加也可以),所以输入端clk,rst
输出端 div3
再考虑状态转换的问题
既然是三分频,应该有3种状态:0、0、1 or 1、1、0(0、1、1)
在时钟的作用下,应该不停的在这三种状态下转换,并且输出仅仅依赖于当前的状态。
代码如下:
//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. 状态转换容易出毛刺,状态01变10时其中状态输出的第二位会有毛刺,不推荐这样设计,建议改为三段式的写法。
三段式状态机三分频实现
代码如下:
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中的条件应该为次态。另外就是设计输入的时候一定要仔细。
参考资料:
1)3分频的verilog实现
http://www.edacn.net/html/76/27076-2348.html
本文工程文件:https://static.assets-stash.eet-china.com/album/old-resources/2009/2/13/30d80efd-f330-4fed-88f9-2557fbfe1a9b.rar
文章评论(0条评论)
登录后参与讨论