verilog奇偶分频一段式两段式三段式状态机.docx
《verilog奇偶分频一段式两段式三段式状态机.docx》由会员分享,可在线阅读,更多相关《verilog奇偶分频一段式两段式三段式状态机.docx(16页珍藏版)》请在冰豆网上搜索。
![verilog奇偶分频一段式两段式三段式状态机.docx](https://file1.bdocx.com/fileroot1/2022-12/11/ee82f5a0-3b98-4048-be20-8289c33e466f/ee82f5a0-3b98-4048-be20-8289c33e466f1.gif)
verilog奇偶分频一段式两段式三段式状态机
汇报总结
1、偶数分频
偶数倍分频相对简单,可以通过计数器对预分频的脉冲沿计数实现,如果要进行N倍(N为整数)偶数分频,可由预分频的时钟触发计数器计数,当计数器从0计数到N/2—1时,输出时钟进行翻转,并给计数器一个复位信号,使得下一个时钟从零开始计数,以此循环下去。
分频的主体程序如下:
`definediv_en8
modulefreq_div_even(clk_in,
reset,
clk_out
);
inputclk_in;
inputreset;
outputclk_out;
regclk_out;
reg[2:
0]count;
initial
begin
count=0;
clk_out=0;
end
always@(posedgeclk_in)
begin
if(!
reset)
begin
count<=0;
clk_out<=0;
end
else
if(count==(`div_en/2-1))
begin
clk_out<=~clk_out;
count<=0;
end
else
begin
count<=count+1;
end
end
endmodule
下面定义N为8,对一个脉冲8分频,测试程序如下:
`timescale1ns/1ns
moduletestbench;
regreset;
regclk_in;
reg[2:
0]count;
wireclk_out;
freq_div_eventest(.clk_in(clk_in),
.reset(reset),
.clk_out(clk_out)
);
initial
begin
reset=0;
clk_in=0;
#5reset=1;
end
always#10clk_in=~clk_in;
endmodule
波形图如下:
2、奇数分频
对于对占空比没有特殊要求的奇数分频,需要对上升沿和下降沿脉冲进行计数,利用下降沿产生的波形移相半个输入脉冲的作用,最后用错位“异或”法实现。
一个n(n=3)分频的程序如下:
moduleclk_divN(
clk_in,
reset,
clk_out
);
inputclk_in;
inputreset;
outputclk_out;
integercnt1,cnt2;
regclk_divp;
regclk_divn;
parametern=3;
always@(posedgeclk_in)
begin
if(!
reset)
begin
clk_divp<=0;
cnt1<=0;
end
else
if(cnt1==(n-1))
cnt1<=0;
else
if(cnt1==0|cnt1==(n-1)/2)
begin
cnt1<=cnt1+1;
clk_divp<=~clk_divp;
end
else
cnt1<=cnt1+1;
end
always@(negedgeclk_in)
begin
if(!
reset)
begin
clk_divn<=0;
cnt2<=0;
end
else
if(cnt2==(n-1))
cnt2<=0;
else
if(cnt1==0|cnt1==(n-1)/2)
begin
cnt2<=cnt2+1;
clk_divn<=~clk_divn;
end
else
cnt2<=cnt2+1;
end
assignclk_out=clk_divp|clk_divn;
endmodule
测试程序如下:
`timescale1ns/1ns
moduleclk_div3_tb;
regclk_in;
regreset;
wireclk_out;
clk_divNuut(.clk_in(clk_in),
.reset(reset),
.clk_out(clk_out)
);
initial
begin
clk_in=0;
reset=0;
#10reset=1;
end
always#5clk_in=~clk_in;
endmodule
3分频、5分频和7分频仿真波形分别如下:
3分频
5分频
7分频
3、状态机
状态机分为两种、一种称为Mealy状态机,它的时序逻辑输出不但取决于状态还取决于输入;另外一种称为Moore状态机,它的输出只取决于当前的状态。
实际的设计工作中大部分都是Mealy状态机。
有限状态机设计一般步骤:
1、逻辑抽象,得出状态转换图;2、状态化简;3、状态分配;4、选定触发器的类型并求出状态方程、驱动方程和输出方程;5、按照方程得出逻辑图。
FSM的描述方法有3中:
1、在1个always模块里面,该模块中既描述状态转移,又描述状态的输入和输出,这种写法一般被称为一段式FSM描述方法;
2、还有一种写法是将用2个always模块,其中一个always模块采用同步时序描述状态转移;另一个模块采用组合逻辑判断状态转移条件,描述状态转移规律,这种写法被称为两段式FSM描述方法;
3、还有一种写法是在两段式描述方法基础上发展出来的,这种写法使用3个always模块,一个always模块采用同步时序描述状态转移;第二个采用组合逻辑判断状态转移条件,描述状态转移规律;第三个always模块使用同步时序电路描述每个状态的输出,这种写法本书称为三段式。
三种描述方式的优缺点比较如下表:
表6-13种FSM描述方法比较表
比较项目
一段式描述方法
两段式描述方法
三段式描述方法
推荐等级
不推荐
推荐
最优推荐
代码简洁程度(对于相对复杂的FSM)
冗长
最简洁
简洁
always模块个数
1
2
3
是否利于时序约束
不利于
利于
利于
是否有组合逻辑输出
可以无组合逻辑输出
多数情况有组合逻辑输出
无组合逻辑输出
是否利于综合与布局布线
不利于
利于
利于
代码的可靠性与可维护度
低
高
最好
代码风格的规范性
低,任意度较大,格式化
规范,格式化
规范
我们主要学习三段式的FSM描述方法。
例如:
需要编写下图所示状态机:
现状态
输入
次状态
输出
S0(00)
0
S0(00)
00
S0(00)
1
S1(01)
00
S1(01)
0
S0(00)
01
S1(01)
1
S2(10)
01
S2(10)
0
S0(00)
10
S2(10)
1
S3(11)
10
S3(11)
0
S0(00)
11
S3(11)
1
S3(11)
11
一段式的的程序,如下:
//state_1paragraph.v
modulestate_1para(reset,clk,x,out);
inputreset,clk;
inputx;
outputout;
reg[1:
0]out;
reg[2:
0]Next_state;//NextState
parameter[2:
0]//onehotwithzeroidle
S0=2'b00,
S1=2'b01,
S2=2'b10,
S3=2'b11;
always@(posedgeclkornegedgereset)
if(!
reset)
begin
Next_state<=S0;
out<=2'b00;
end
else
begin
Next_state<=2'bx;
out<=2'b00;
case(Next_state)
S0:
begin
if(x==0)
begin
out<=2'b00;
Next_state<=S0;
end
else
begin
out<=2'b01;//输出要看下一状态
Next_state<=S1;
end
end
S1:
begin
if(x==0)
begin
out<=2'b00;
Next_state<=S0;
end
else
begin
out<=2'b10;
Next_state<=S2;
end
end
S2:
begin
if(x==0)
begin
out<=2'b00;
Next_state<=S0;
end
else
begin
out<=2'b11;
Next_state<=S3;
end
end
S3:
begin
if(x==0)
begin
out<=2'b00;
Next_state<=S0;
end
else
begin
out<=2'b11;
Next_state<=S3;
end
end
endcase
end
endmodule
两段式的程序如下:
modulestate_2para(reset,clk,x,out);
inputreset,clk;
inputx;
outputout;
reg[1:
0]out;
reg[2:
0]Next_state,Current_state;
parameter[2:
0]//onehotwithzeroidle
S0=2’b00,
S1=2’b01,
S2=2’b10,
S3=2’b11;
//描述状态转移,非阻塞方式赋值
always@(posedgeclkornegedgereset)
if(!
reset)
Current_state<=S0;
else
Current_state<=Next_state;
//描述状态转移的条件,阻塞方式赋值
always@(Current_stateorx)
begin
Next_state=2’bx;
S3_out;
case(Current_state)
S0:
begin
S0_out;
if(x==0)Next_state=S0;
elseNext_state=S1;
end
S1:
begin
S1_out;
if(x==0)Next_state=S0;
elseNext_state=S2;
end
S2:
begin
S2_out;
if(x==0)Next_state=S0;
elseNext_state=S3;
end
S3:
begin
S3_out;
if(x==0)Next_state=S0;
elseNext_state=S3;
end
endcase
end
//定义输出任务
taskS0_out;
out=2'b00;
endtask
taskS1_out;
out=2'b01;
endtask
taskS2_out;
out=2'b10;
endtask
taskS3_out;
out=2'b11;
endtask
endmodule
三段式的程序如下:
modulestate3(reset,clk,x,out);
inputreset,clk;
inputx,;
outputout;
reg[1:
0]out;
reg[2:
0]Next_state,Current_state;
parameter[2:
0]
S0=2’b00,
S1=2’b01,
S2=2'b10,
S3=2’b11;
always@(posedgeclkornegedgereset)
if(!
reset)
Current_state<=S0;
else
Current_state<=Next_state;
always@(resetorCurrent_stateorx)//与二段式区别
begin
Next_state=2’bx;
case(Current_state)//注意
S0:
begin
if(x==0)Next_state=S0;
elseNext_state=S1;
end
S1:
begin
if(x==0)Next_state=S0;
elseNext_state=S2;
end
S2:
begin
if(x==0)Next_state=S0;
elseNext_state=S3;
end
S3:
begin
if(x==0)Next_state=S0;
elseNext_state=S3;
end
endcase
end
always@(posedgeclkornegedgereset)
if(!
reset)
out<=0;
else
begin
out<=0;
case(Next_state)//需要注意,不是Current_state
S0:
out<=2’b00;
S1:
out<=2’b01;
S2:
out<=2’b10;
S3:
out<=2’b11;
endcase
end
endmodule
三种方法的测试程序如下:
//state_1paragraph_tb.v
`timescale1ns/1ns
modulestate_1parag_tb;
regreset;
regclk;
regx;
wire[1:
0]out;
state_1paratb(.reset(reset),
.clk(clk),
.x(x),
.out(out)
);
initial
begin
clk=0;
reset=0;
x=0;
#10reset=1;
#1000reset=0;
#100reset=1;
end
always#20clk=~clk;
always@(posedgeclk)
begin
#10x={$random}%2;//输入x随机在0和1之间变化
end
endmodule
一段式的仿真波形图
二段式的仿真波形图
三段式的仿真波形图