7 - 简单状态机代码设计
三角波发生器
代码:
//2021.11.21 lyw
//The simplest state machine——triangle wave generator
`timescale 1ns/10ps
module tri_gen (
clk,
res,
d_out
);
input clk;
input res;
output[8:0] d_out; //299;2^8=256
reg state; //Main State Machine Register; 2 states need 1 bit
reg[8:0] d_out;
always @(posedge clk or negedge res) begin
if(~res)begin
state=0;
d_out=0;
end
else begin
case(state)
0://rise
begin
d_out<=d_out+1;
if (d_out==299) begin
state<=1;
end
end
1://drop
begin
d_out<=d_out-1;
if (d_out==1) begin
state<=0;
end
end
endcase
end
end
endmodule
//-----testbench of tri_gen------
module tri_gen_tb;
reg clk,res;
wire [8:0] d_out;
tri_gen U1 (
.clk(clk),
.res(res),
.d_out(d_out)
);
initial begin
clk<=0;
res<=0;
#17 res<=1;
#8000 $stop;
end
always #5 clk=~clk;
endmodule
仿真波形:
用模拟方式观察:
注意:判断 d_out=299 和 d_out+1 是同时进行的,此时 d_out 按照 298 来判断。到下一个时钟上升沿时,d_out=299,state=0,这个周期跑完以后 d_out=300,state=1。
梯形波发生器:
如果想把三角波换成梯形波:增加一个状态(上升、下降、平持三个状态)
代码:
//2021.11.21 lyw
//The simplest state machine——triangle wave generator
`timescale 1ns/10ps
module tri_gen (
clk,
res,
d_out
);
input clk;
input res;
output[8:0] d_out; //299;2^8=256
reg[1:0] state; //Main State Machine Register; 2 states need 1 bit
reg[8:0] d_out;
reg [7:0] con;
always @(posedge clk or negedge res) begin
if(~res)begin
state=0;
d_out=0;
con<=0;
end
else begin
case(state)
0://rise
begin
d_out<=d_out+1;
if (d_out==299) begin
state<=1;
end
end
1://flat
begin
if (con==200) begin
state<=2;
con<=0;
end
else begin
con<=con+1;
end
end
2://drop
begin
d_out<=d_out-1;
if (d_out==1) begin
state<=0;
end
end
default:
begin
state<=0;
con<=0;
d_out<=0;
end
endcase
end
end
endmodule
//-----testbench of tri_gen------
module tri_gen_tb;
reg clk,res;
wire [8:0] d_out;
tri_gen U1 (
.clk(clk),
.res(res),
.d_out(d_out)
);
initial begin
clk<=0;
res<=0;
#17 res<=1;
#20000 $stop;
end
always #5 clk=~clk;
endmodule
注意:用两位来表示三种状态还有剩余,需要一个 default。
仿真波形:
如果继续改改成【上-平-下-平】格式
代码:
//2021.11.21 lyw
//The simplest state machine——triangle wave generator
`timescale 1ns/10ps
module tri_gen (
clk,
res,
d_out
);
input clk;
input res;
output[8:0] d_out; //299;2^8=256
reg[1:0] state; //Main State Machine Register; 2 states need 1 bit
reg[8:0] d_out;
reg [7:0] con;
always @(posedge clk or negedge res) begin
if(~res)begin
state=0;
d_out=0;
con<=0;
end
else begin
case(state)
0://rise
begin
d_out<=d_out+1;
if (d_out==299) begin
state<=1;
end
end
1://flat
begin
if (con==200) begin
state<=2;
con<=0;
end
else begin
con<=con+1;
end
end
2://drop
begin
d_out<=d_out-1;
if (d_out==1) begin
state<=3;
end
end
/*
default:
begin
state<=0;
con<=0;
d_out<=0;
end
*/
3://flat
begin
if (con==200) begin
state<=0;
con<=0;
end
else begin
con<=con+1;
end
end
endcase
end
end
endmodule
//-----testbench of tri_gen------
module tri_gen_tb;
reg clk,res;
wire [8:0] d_out;
tri_gen U1 (
.clk(clk),
.res(res),
.d_out(d_out)
);
initial begin
clk<=0;
res<=0;
#17 res<=1;
#20000 $stop;
end
always #5 clk=~clk;
endmodule
仿真波形:
写状态机曾犯过的错误:
- 增加了状态,但 state 位数却没有随之增加。
- 当状态不够多时,要写 default。
- 增加了新状态,但跳转关系没改好。
PS:内容总结自网络,状态机好有意思啊(* ̄▽ ̄*)